github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/triage/node_modules/glob/sync.js (about)

     1  module.exports = globSync
     2  globSync.GlobSync = GlobSync
     3  
     4  var fs = require('fs')
     5  var rp = require('fs.realpath')
     6  var minimatch = require('minimatch')
     7  var Minimatch = minimatch.Minimatch
     8  var Glob = require('./glob.js').Glob
     9  var util = require('util')
    10  var path = require('path')
    11  var assert = require('assert')
    12  var isAbsolute = require('path-is-absolute')
    13  var common = require('./common.js')
    14  var alphasort = common.alphasort
    15  var alphasorti = common.alphasorti
    16  var setopts = common.setopts
    17  var ownProp = common.ownProp
    18  var childrenIgnored = common.childrenIgnored
    19  var isIgnored = common.isIgnored
    20  
    21  function globSync (pattern, options) {
    22    if (typeof options === 'function' || arguments.length === 3)
    23      throw new TypeError('callback provided to sync glob\n'+
    24                          'See: https://github.com/isaacs/node-glob/issues/167')
    25  
    26    return new GlobSync(pattern, options).found
    27  }
    28  
    29  function GlobSync (pattern, options) {
    30    if (!pattern)
    31      throw new Error('must provide pattern')
    32  
    33    if (typeof options === 'function' || arguments.length === 3)
    34      throw new TypeError('callback provided to sync glob\n'+
    35                          'See: https://github.com/isaacs/node-glob/issues/167')
    36  
    37    if (!(this instanceof GlobSync))
    38      return new GlobSync(pattern, options)
    39  
    40    setopts(this, pattern, options)
    41  
    42    if (this.noprocess)
    43      return this
    44  
    45    var n = this.minimatch.set.length
    46    this.matches = new Array(n)
    47    for (var i = 0; i < n; i ++) {
    48      this._process(this.minimatch.set[i], i, false)
    49    }
    50    this._finish()
    51  }
    52  
    53  GlobSync.prototype._finish = function () {
    54    assert(this instanceof GlobSync)
    55    if (this.realpath) {
    56      var self = this
    57      this.matches.forEach(function (matchset, index) {
    58        var set = self.matches[index] = Object.create(null)
    59        for (var p in matchset) {
    60          try {
    61            p = self._makeAbs(p)
    62            var real = rp.realpathSync(p, self.realpathCache)
    63            set[real] = true
    64          } catch (er) {
    65            if (er.syscall === 'stat')
    66              set[self._makeAbs(p)] = true
    67            else
    68              throw er
    69          }
    70        }
    71      })
    72    }
    73    common.finish(this)
    74  }
    75  
    76  
    77  GlobSync.prototype._process = function (pattern, index, inGlobStar) {
    78    assert(this instanceof GlobSync)
    79  
    80    // Get the first [n] parts of pattern that are all strings.
    81    var n = 0
    82    while (typeof pattern[n] === 'string') {
    83      n ++
    84    }
    85    // now n is the index of the first one that is *not* a string.
    86  
    87    // See if there's anything else
    88    var prefix
    89    switch (n) {
    90      // if not, then this is rather simple
    91      case pattern.length:
    92        this._processSimple(pattern.join('/'), index)
    93        return
    94  
    95      case 0:
    96        // pattern *starts* with some non-trivial item.
    97        // going to readdir(cwd), but not include the prefix in matches.
    98        prefix = null
    99        break
   100  
   101      default:
   102        // pattern has some string bits in the front.
   103        // whatever it starts with, whether that's 'absolute' like /foo/bar,
   104        // or 'relative' like '../baz'
   105        prefix = pattern.slice(0, n).join('/')
   106        break
   107    }
   108  
   109    var remain = pattern.slice(n)
   110  
   111    // get the list of entries.
   112    var read
   113    if (prefix === null)
   114      read = '.'
   115    else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
   116      if (!prefix || !isAbsolute(prefix))
   117        prefix = '/' + prefix
   118      read = prefix
   119    } else
   120      read = prefix
   121  
   122    var abs = this._makeAbs(read)
   123  
   124    //if ignored, skip processing
   125    if (childrenIgnored(this, read))
   126      return
   127  
   128    var isGlobStar = remain[0] === minimatch.GLOBSTAR
   129    if (isGlobStar)
   130      this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
   131    else
   132      this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
   133  }
   134  
   135  
   136  GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
   137    var entries = this._readdir(abs, inGlobStar)
   138  
   139    // if the abs isn't a dir, then nothing can match!
   140    if (!entries)
   141      return
   142  
   143    // It will only match dot entries if it starts with a dot, or if
   144    // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
   145    var pn = remain[0]
   146    var negate = !!this.minimatch.negate
   147    var rawGlob = pn._glob
   148    var dotOk = this.dot || rawGlob.charAt(0) === '.'
   149  
   150    var matchedEntries = []
   151    for (var i = 0; i < entries.length; i++) {
   152      var e = entries[i]
   153      if (e.charAt(0) !== '.' || dotOk) {
   154        var m
   155        if (negate && !prefix) {
   156          m = !e.match(pn)
   157        } else {
   158          m = e.match(pn)
   159        }
   160        if (m)
   161          matchedEntries.push(e)
   162      }
   163    }
   164  
   165    var len = matchedEntries.length
   166    // If there are no matched entries, then nothing matches.
   167    if (len === 0)
   168      return
   169  
   170    // if this is the last remaining pattern bit, then no need for
   171    // an additional stat *unless* the user has specified mark or
   172    // stat explicitly.  We know they exist, since readdir returned
   173    // them.
   174  
   175    if (remain.length === 1 && !this.mark && !this.stat) {
   176      if (!this.matches[index])
   177        this.matches[index] = Object.create(null)
   178  
   179      for (var i = 0; i < len; i ++) {
   180        var e = matchedEntries[i]
   181        if (prefix) {
   182          if (prefix.slice(-1) !== '/')
   183            e = prefix + '/' + e
   184          else
   185            e = prefix + e
   186        }
   187  
   188        if (e.charAt(0) === '/' && !this.nomount) {
   189          e = path.join(this.root, e)
   190        }
   191        this._emitMatch(index, e)
   192      }
   193      // This was the last one, and no stats were needed
   194      return
   195    }
   196  
   197    // now test all matched entries as stand-ins for that part
   198    // of the pattern.
   199    remain.shift()
   200    for (var i = 0; i < len; i ++) {
   201      var e = matchedEntries[i]
   202      var newPattern
   203      if (prefix)
   204        newPattern = [prefix, e]
   205      else
   206        newPattern = [e]
   207      this._process(newPattern.concat(remain), index, inGlobStar)
   208    }
   209  }
   210  
   211  
   212  GlobSync.prototype._emitMatch = function (index, e) {
   213    if (isIgnored(this, e))
   214      return
   215  
   216    var abs = this._makeAbs(e)
   217  
   218    if (this.mark)
   219      e = this._mark(e)
   220  
   221    if (this.absolute) {
   222      e = abs
   223    }
   224  
   225    if (this.matches[index][e])
   226      return
   227  
   228    if (this.nodir) {
   229      var c = this.cache[abs]
   230      if (c === 'DIR' || Array.isArray(c))
   231        return
   232    }
   233  
   234    this.matches[index][e] = true
   235  
   236    if (this.stat)
   237      this._stat(e)
   238  }
   239  
   240  
   241  GlobSync.prototype._readdirInGlobStar = function (abs) {
   242    // follow all symlinked directories forever
   243    // just proceed as if this is a non-globstar situation
   244    if (this.follow)
   245      return this._readdir(abs, false)
   246  
   247    var entries
   248    var lstat
   249    var stat
   250    try {
   251      lstat = fs.lstatSync(abs)
   252    } catch (er) {
   253      if (er.code === 'ENOENT') {
   254        // lstat failed, doesn't exist
   255        return null
   256      }
   257    }
   258  
   259    var isSym = lstat && lstat.isSymbolicLink()
   260    this.symlinks[abs] = isSym
   261  
   262    // If it's not a symlink or a dir, then it's definitely a regular file.
   263    // don't bother doing a readdir in that case.
   264    if (!isSym && lstat && !lstat.isDirectory())
   265      this.cache[abs] = 'FILE'
   266    else
   267      entries = this._readdir(abs, false)
   268  
   269    return entries
   270  }
   271  
   272  GlobSync.prototype._readdir = function (abs, inGlobStar) {
   273    var entries
   274  
   275    if (inGlobStar && !ownProp(this.symlinks, abs))
   276      return this._readdirInGlobStar(abs)
   277  
   278    if (ownProp(this.cache, abs)) {
   279      var c = this.cache[abs]
   280      if (!c || c === 'FILE')
   281        return null
   282  
   283      if (Array.isArray(c))
   284        return c
   285    }
   286  
   287    try {
   288      return this._readdirEntries(abs, fs.readdirSync(abs))
   289    } catch (er) {
   290      this._readdirError(abs, er)
   291      return null
   292    }
   293  }
   294  
   295  GlobSync.prototype._readdirEntries = function (abs, entries) {
   296    // if we haven't asked to stat everything, then just
   297    // assume that everything in there exists, so we can avoid
   298    // having to stat it a second time.
   299    if (!this.mark && !this.stat) {
   300      for (var i = 0; i < entries.length; i ++) {
   301        var e = entries[i]
   302        if (abs === '/')
   303          e = abs + e
   304        else
   305          e = abs + '/' + e
   306        this.cache[e] = true
   307      }
   308    }
   309  
   310    this.cache[abs] = entries
   311  
   312    // mark and cache dir-ness
   313    return entries
   314  }
   315  
   316  GlobSync.prototype._readdirError = function (f, er) {
   317    // handle errors, and cache the information
   318    switch (er.code) {
   319      case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
   320      case 'ENOTDIR': // totally normal. means it *does* exist.
   321        var abs = this._makeAbs(f)
   322        this.cache[abs] = 'FILE'
   323        if (abs === this.cwdAbs) {
   324          var error = new Error(er.code + ' invalid cwd ' + this.cwd)
   325          error.path = this.cwd
   326          error.code = er.code
   327          throw error
   328        }
   329        break
   330  
   331      case 'ENOENT': // not terribly unusual
   332      case 'ELOOP':
   333      case 'ENAMETOOLONG':
   334      case 'UNKNOWN':
   335        this.cache[this._makeAbs(f)] = false
   336        break
   337  
   338      default: // some unusual error.  Treat as failure.
   339        this.cache[this._makeAbs(f)] = false
   340        if (this.strict)
   341          throw er
   342        if (!this.silent)
   343          console.error('glob error', er)
   344        break
   345    }
   346  }
   347  
   348  GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
   349  
   350    var entries = this._readdir(abs, inGlobStar)
   351  
   352    // no entries means not a dir, so it can never have matches
   353    // foo.txt/** doesn't match foo.txt
   354    if (!entries)
   355      return
   356  
   357    // test without the globstar, and with every child both below
   358    // and replacing the globstar.
   359    var remainWithoutGlobStar = remain.slice(1)
   360    var gspref = prefix ? [ prefix ] : []
   361    var noGlobStar = gspref.concat(remainWithoutGlobStar)
   362  
   363    // the noGlobStar pattern exits the inGlobStar state
   364    this._process(noGlobStar, index, false)
   365  
   366    var len = entries.length
   367    var isSym = this.symlinks[abs]
   368  
   369    // If it's a symlink, and we're in a globstar, then stop
   370    if (isSym && inGlobStar)
   371      return
   372  
   373    for (var i = 0; i < len; i++) {
   374      var e = entries[i]
   375      if (e.charAt(0) === '.' && !this.dot)
   376        continue
   377  
   378      // these two cases enter the inGlobStar state
   379      var instead = gspref.concat(entries[i], remainWithoutGlobStar)
   380      this._process(instead, index, true)
   381  
   382      var below = gspref.concat(entries[i], remain)
   383      this._process(below, index, true)
   384    }
   385  }
   386  
   387  GlobSync.prototype._processSimple = function (prefix, index) {
   388    // XXX review this.  Shouldn't it be doing the mounting etc
   389    // before doing stat?  kinda weird?
   390    var exists = this._stat(prefix)
   391  
   392    if (!this.matches[index])
   393      this.matches[index] = Object.create(null)
   394  
   395    // If it doesn't exist, then just mark the lack of results
   396    if (!exists)
   397      return
   398  
   399    if (prefix && isAbsolute(prefix) && !this.nomount) {
   400      var trail = /[\/\\]$/.test(prefix)
   401      if (prefix.charAt(0) === '/') {
   402        prefix = path.join(this.root, prefix)
   403      } else {
   404        prefix = path.resolve(this.root, prefix)
   405        if (trail)
   406          prefix += '/'
   407      }
   408    }
   409  
   410    if (process.platform === 'win32')
   411      prefix = prefix.replace(/\\/g, '/')
   412  
   413    // Mark this as a match
   414    this._emitMatch(index, prefix)
   415  }
   416  
   417  // Returns either 'DIR', 'FILE', or false
   418  GlobSync.prototype._stat = function (f) {
   419    var abs = this._makeAbs(f)
   420    var needDir = f.slice(-1) === '/'
   421  
   422    if (f.length > this.maxLength)
   423      return false
   424  
   425    if (!this.stat && ownProp(this.cache, abs)) {
   426      var c = this.cache[abs]
   427  
   428      if (Array.isArray(c))
   429        c = 'DIR'
   430  
   431      // It exists, but maybe not how we need it
   432      if (!needDir || c === 'DIR')
   433        return c
   434  
   435      if (needDir && c === 'FILE')
   436        return false
   437  
   438      // otherwise we have to stat, because maybe c=true
   439      // if we know it exists, but not what it is.
   440    }
   441  
   442    var exists
   443    var stat = this.statCache[abs]
   444    if (!stat) {
   445      var lstat
   446      try {
   447        lstat = fs.lstatSync(abs)
   448      } catch (er) {
   449        if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
   450          this.statCache[abs] = false
   451          return false
   452        }
   453      }
   454  
   455      if (lstat && lstat.isSymbolicLink()) {
   456        try {
   457          stat = fs.statSync(abs)
   458        } catch (er) {
   459          stat = lstat
   460        }
   461      } else {
   462        stat = lstat
   463      }
   464    }
   465  
   466    this.statCache[abs] = stat
   467  
   468    var c = true
   469    if (stat)
   470      c = stat.isDirectory() ? 'DIR' : 'FILE'
   471  
   472    this.cache[abs] = this.cache[abs] || c
   473  
   474    if (needDir && c === 'FILE')
   475      return false
   476  
   477    return c
   478  }
   479  
   480  GlobSync.prototype._mark = function (p) {
   481    return common.mark(this, p)
   482  }
   483  
   484  GlobSync.prototype._makeAbs = function (f) {
   485    return common.makeAbs(this, f)
   486  }