Вход Регистрация
Файл: error-kitty/node_modules/mocha/node_modules/glob/glob.js
Строк: 653
<?php
// Approach:
//
// 1. Get the minimatch set
// 2. For each pattern in the set, PROCESS(pattern)
// 3. Store matches per-set, then uniq them
//
// PROCESS(pattern)
// Get the first [n] items from pattern that are all strings
// Join these together.  This is PREFIX.
//   If there is no more remaining, then stat(PREFIX) and
//   add to matches if it succeeds.  END.
// readdir(PREFIX) as ENTRIES
//   If fails, END
//   If pattern[n] is GLOBSTAR
//     // handle the case where the globstar match is empty
//     // by pruning it out, and testing the resulting pattern
//     PROCESS(pattern[0..n] + pattern[n+1 .. $])
//     // handle other cases.
//     for ENTRY in ENTRIES (not dotfiles)
//       // attach globstar + tail onto the entry
//       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $])
//
//   else // not globstar
//     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
//       Test ENTRY against pattern[n]
//       If fails, continue
//       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
//
// Caveat:
//   Cache all stats and readdirs results to minimize syscall.  Since all
//   we ever care about is existence and directory-ness, we can just keep
//   `true` for files, and [children,...] for directories, or `false` for
//   things that don't exist.



module.exports glob

var fs = require("graceful-fs")
minimatch = require("minimatch")
Minimatch minimatch.Minimatch
inherits = require("inherits")
EE = require("events").EventEmitter
path = require("path")
isDir = {}
assert = require("assert").ok

function glob (patternoptionscb) {
  if (
typeof options === "function"cb optionsoptions = {}
  if (!
optionsoptions = {}

  if (
typeof options === "number") {
    
deprecated()
    return
  }

  var 
= new Glob(patternoptionscb)
  return 
g.sync g.found g
}

glob.fnmatch deprecated

function deprecated () {
  throw new 
Error("glob's interface has changed. Please see the docs.")
}

glob.sync globSync
function globSync (patternoptions) {
  if (
typeof options === "number") {
    
deprecated()
    return
  }

  
options options || {}
  
options.sync true
  
return glob(patternoptions)
}


glob.Glob Glob
inherits
(GlobEE)
function 
Glob (patternoptionscb) {
  if (!(
this instanceof Glob)) {
    return new 
Glob(patternoptionscb)
  }

  if (
typeof cb === "function") {
    
this.on("error"cb)
    
this.on("end", function (matches) {
      
cb(nullmatches)
    })
  }

  
options options || {}

  
this.EOF = {}
  
this._emitQueue = []

  
this.maxDepth options.maxDepth || 1000
  this
.maxLength options.maxLength || Infinity
  this
.cache options.cache || {}
  
this.statCache options.statCache || {}

  
this.changedCwd false
  
var cwd process.cwd()
  if (!
options.hasOwnProperty("cwd")) this.cwd cwd
  
else {
    
this.cwd options.cwd
    this
.changedCwd path.resolve(options.cwd) !== cwd
  
}

  
this.root options.root || path.resolve(this.cwd"/")
  
this.root path.resolve(this.root)
  if (
process.platform === "win32")
    
this.root this.root.replace(/\/g"/")

  
this.nomount = !!options.nomount

  
if (!pattern) {
    throw new 
Error("must provide pattern")
  }

  
// base-matching: just use globstar for that.
  
if (options.matchBase && -=== pattern.indexOf("/")) {
    if (
options.noglobstar) {
      throw new 
Error("base matching requires globstar")
    }
    
pattern "**/" pattern
  
}

  
this.strict options.strict !== false
  this
.dot = !!options.dot
  this
.mark = !!options.mark
  this
.sync = !!options.sync
  this
.nounique = !!options.nounique
  this
.nonull = !!options.nonull
  this
.nosort = !!options.nosort
  this
.nocase = !!options.nocase
  this
.stat = !!options.stat

  this
.debug = !!options.debug || !!options.globDebug
  
if (this.debug)
    
this.log console.error

  this
.silent = !!options.silent

  
var mm this.minimatch = new Minimatch(patternoptions)
  
this.options mm.options
  pattern 
this.pattern mm.pattern

  this
.error null
  this
.aborted false

  
// list of all the patterns that ** has resolved do, so
  // we can avoid visiting multiple times.
  
this._globstars = {}

  
EE.call(this)

  
// process each pattern in the minimatch set
  
var this.minimatch.set.length

  
// The matches are stored as {<filename>: true,...} so that
  // duplicates are automagically pruned.
  // Later, we do an Object.keys() on these.
  // Keep them as a list so we can fill in when nonull is set.
  
this.matches = new Array(n)

  
this.minimatch.set.forEach(iterator.bind(this))
  function 
iterator (patterniset) {
    
this._process(pattern0i, function (er) {
      if (
erthis.emit("error"er)
      if (-- 
<= 0this._finish()
    })
  }
}

Glob.prototype.log = function () {}

Glob.prototype._finish = function () {
  
assert(this instanceof Glob)

  var 
nou this.nounique
  
all nou ? [] : {}

  for (var 
0this.matches.lengthl++) {
    var 
matches this.matches[i]
    
this.log("matches[%d] ="imatches)
    
// do like the shell, and spit out the literal glob
    
if (!matches) {
      if (
this.nonull) {
        var 
literal this.minimatch.globSet[i]
        if (
nouall.push(literal)
        else 
all[literal] = true
      
}
    } else {
      
// had matches
      
var Object.keys(matches)
      if (
nouall.push.apply(allm)
      else 
m.forEach(function (m) {
        
all[m] = true
      
})
    }
  }

  if (!
nouall Object.keys(all)

  if (!
this.nosort) {
    
all all.sort(this.nocase alphasorti alphasort)
  }

  if (
this.mark) {
    
// at *some* point we statted all of these
    
all all.map(function (m) {
      var 
sc this.cache[m]
      if (!
sc)
        return 
m
      
var isDir = (Array.isArray(sc) || sc === 2)
      if (
isDir && m.slice(-1) !== "/") {
        return 
"/"
      
}
      if (!
isDir && m.slice(-1) === "/") {
        return 
m.replace(//+$/, "")
      
}
      return 
m
    
}, this)
  }

  
this.log("emitting end"all)

  
this.EOF this.found all
  this
.emitMatch(this.EOF)
}

function 
alphasorti (ab) {
  
a.toLowerCase()
  
b.toLowerCase()
  return 
alphasort(ab)
}

function 
alphasort (ab) {
  return 
? -0
}

Glob.prototype.abort = function () {
  
this.aborted true
  this
.emit("abort")
}

Glob.prototype.pause = function () {
  if (
this.paused) return
  if (
this.sync)
    
this.emit("error", new Error("Can't pause/resume sync glob"))
  
this.paused true
  this
.emit("pause")
}

Glob.prototype.resume = function () {
  if (!
this.paused) return
  if (
this.sync)
    
this.emit("error", new Error("Can't pause/resume sync glob"))
  
this.paused false
  this
.emit("resume")
  
this._processEmitQueue()
  
//process.nextTick(this.emit.bind(this, "resume"))
}

Glob.prototype.emitMatch = function (m) {
  if (!
this.stat || this.statCache[m] || === this.EOF) {
    
this._emitQueue.push(m)
    
this._processEmitQueue()
  } else {
    
this._stat(m, function(existsisDir) {
      if (
exists) {
        
this._emitQueue.push(m)
        
this._processEmitQueue()
      }
    })
  }
}

Glob.prototype._processEmitQueue = function (m) {
  while (!
this._processingEmitQueue &&
         !
this.paused) {
    
this._processingEmitQueue true
    
var this._emitQueue.shift()
    if (!
m) {
      
this._processingEmitQueue false
      
break
    }

    
this.log('emit!'=== this.EOF "end" "match")

    
this.emit(=== this.EOF "end" "match"m)
    
this._processingEmitQueue false
  
}
}

Glob.prototype._process = function (patterndepthindexcb_) {
  
assert(this instanceof Glob)

  var 
cb = function cb (erres) {
    
assert(this instanceof Glob)
    if (
this.paused) {
      if (!
this._processQueue) {
        
this._processQueue = []
        
this.once("resume", function () {
          var 
this._processQueue
          this
._processQueue null
          q
.forEach(function (cb) { cb() })
        })
      }
      
this._processQueue.push(cb_.bind(thiserres))
    } else {
      
cb_.call(thiserres)
    }
  }.
bind(this)

  if (
this.aborted) return cb()

  if (
depth this.maxDepth) return cb()

  
// Get the first [n] parts of pattern that are all strings.
  
var 0
  
while (typeof pattern[n] === "string") {
    
++
  }
  
// now n is the index of the first one that is *not* a string.

  // see if there's anything else
  
var prefix
  
switch (n) {
    
// if not, then this is rather simple
    
case pattern.length:
      
prefix pattern.join("/")
      
this._stat(prefix, function (existsisDir) {
        
// either it's there, or it isn't.
        // nothing more to do, either way.
        
if (exists) {
          if (
prefix && isAbsolute(prefix) && !this.nomount) {
            if (
prefix.charAt(0) === "/") {
              
prefix path.join(this.rootprefix)
            } else {
              
prefix path.resolve(this.rootprefix)
            }
          }

          if (
process.platform === "win32")
            
prefix prefix.replace(/\/g"/")

          
this.matches[index] = this.matches[index] || {}
          
this.matches[index][prefix] = true
          this
.emitMatch(prefix)
        }
        return 
cb()
      })
      return

    case 
0:
      
// pattern *starts* with some non-trivial item.
      // going to readdir(cwd), but not include the prefix in matches.
      
prefix null
      
break

    default:
      
// pattern has some string bits in the front.
      // whatever it starts with, whether that's "absolute" like /foo/bar,
      // or "relative" like "../baz"
      
prefix pattern.slice(0n)
      
prefix prefix.join("/")
      break
  }

  
// get the list of entries.
  
var read
  
if (prefix === nullread "."
  
else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) {
    if (!
prefix || !isAbsolute(prefix)) {
      
prefix path.join("/"prefix)
    }
    
read prefix path.resolve(prefix)

    
// if (process.platform === "win32")
    //   read = prefix = prefix.replace(/^[a-zA-Z]:|\/g, "/")

    
this.log('absolute: 'prefixthis.rootpatternread)
  } else {
    
read prefix
  
}

  
this.log('readdir(%j)'readthis.cwdthis.root)

  return 
this._readdir(read, function (erentries) {
    if (
er) {
      
// not a directory!
      // this means that, whatever else comes after this, it can never match
      
return cb()
    }

    
// globstar is special
    
if (pattern[n] === minimatch.GLOBSTAR) {
      
// test without the globstar, and with every child both below
      // and replacing the globstar.
      
var = [ pattern.slice(0n).concat(pattern.slice(1)) ]
      
entries.forEach(function (e) {
        if (
e.charAt(0) === "." && !this.dot) return
        
// instead of the globstar
        
s.push(pattern.slice(0n).concat(e).concat(pattern.slice(1)))
        
// below the globstar
        
s.push(pattern.slice(0n).concat(e).concat(pattern.slice(n)))
      }, 
this)

      
s.filter(function (pattern) {
        var 
key gsKey(pattern)
        var 
seen = !this._globstars[key]
        
this._globstars[key] = true
        
return seen
      
}, this)

      if (!
s.length)
        return 
cb()

      
// now asyncForEach over this
      
var s.length
      
errState null
      s
.forEach(function (gsPattern) {
        
this._process(gsPatterndepth 1index, function (er) {
          if (
errState) return
          if (
er) return cb(errState er)
          if (--
<= 0) return cb()
        })
      }, 
this)

      return
    }

    
// not a globstar
    // It will only match dot entries if it starts with a dot, or if
    // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
    
var pn pattern[n]
    var 
rawGlob pattern[n]._glob
    
dotOk this.dot || rawGlob.charAt(0) === "."

    
entries entries.filter(function (e) {
      return (
e.charAt(0) !== "." || dotOk) &&
             
e.match(pattern[n])
    })

    
// If n === pattern.length - 1, then there's no need for the extra stat
    // *unless* the user has specified "mark" or "stat" explicitly.
    // We know that they exist, since the readdir returned them.
    
if (=== pattern.length &&
        !
this.mark &&
        !
this.stat) {
      
entries.forEach(function (e) {
        if (
prefix) {
          if (
prefix !== "/"prefix "/" e
          
else prefix e
        
}
        if (
e.charAt(0) === "/" && !this.nomount) {
          
path.join(this.roote)
        }

        if (
process.platform === "win32")
          
e.replace(/\/g"/")

        
this.matches[index] = this.matches[index] || {}
        
this.matches[index][e] = true
        this
.emitMatch(e)
      }, 
this)
      return 
cb.call(this)
    }


    
// now test all the remaining entries as stand-ins for that part
    // of the pattern.
    
var entries.length
    
errState null
    
if (=== 0) return cb() // no matches possible
    
entries.forEach(function (e) {
      var 
pattern.slice(0n).concat(e).concat(pattern.slice(1))
      
this._process(pdepth 1index, function (er) {
        if (
errState) return
        if (
er) return cb(errState er)
        if (--
=== 0) return cb.call(this)
      })
    }, 
this)
  })

}

function 
gsKey (pattern) {
  return 
'**' pattern.map(function (p) {
    return (
=== minimatch.GLOBSTAR) ? '**' : (''+p)
  }).
join('/')
}

Glob.prototype._stat = function (fcb) {
  
assert(this instanceof Glob)
  var 
abs f
  
if (f.charAt(0) === "/") {
    
abs path.join(this.rootf)
  } else if (
this.changedCwd) {
    
abs path.resolve(this.cwdf)
  }

  if (
f.length this.maxLength) {
    var 
er = new Error("Path name too long")
    
er.code "ENAMETOOLONG"
    
er.path f
    
return this._afterStat(fabscber)
  }

  
this.log('stat', [this.cwdf'='abs])

  if (!
this.stat && this.cache.hasOwnProperty(f)) {
    var 
exists this.cache[f]
    , 
isDir exists && (Array.isArray(exists) || exists === 2)
    if (
this.sync) return cb.call(this, !!existsisDir)
    return 
process.nextTick(cb.bind(this, !!existsisDir))
  }

  var 
stat this.statCache[abs]
  if (
this.sync || stat) {
    var 
er
    
try {
      
stat fs.statSync(abs)
    } catch (
e) {
      
er e
    
}
    
this._afterStat(fabscberstat)
  } else {
    
fs.stat(absthis._afterStat.bind(thisfabscb))
  }
}

Glob.prototype._afterStat = function (fabscberstat) {
  var 
exists
  assert
(this instanceof Glob)

  if (
abs.slice(-1) === "/" && stat && !stat.isDirectory()) {
    
this.log("should be ENOTDIR, fake it")

    
er = new Error("ENOTDIR, not a directory '" abs "'")
    
er.path abs
    er
.code "ENOTDIR"
    
stat null
  
}

  var 
emit = !this.statCache[abs]
  
this.statCache[abs] = stat

  
if (er || !stat) {
    
exists false
  
} else {
    
exists stat.isDirectory() ? 1
    
if (emit)
      
this.emit('stat'fstat)
  }
  
this.cache[f] = this.cache[f] || exists
  cb
.call(this, !!existsexists === 2)
}

Glob.prototype._readdir = function (fcb) {
  
assert(this instanceof Glob)
  var 
abs f
  
if (f.charAt(0) === "/") {
    
abs path.join(this.rootf)
  } else if (
isAbsolute(f)) {
    
abs f
  
} else if (this.changedCwd) {
    
abs path.resolve(this.cwdf)
  }

  if (
f.length this.maxLength) {
    var 
er = new Error("Path name too long")
    
er.code "ENAMETOOLONG"
    
er.path f
    
return this._afterReaddir(fabscber)
  }

  
this.log('readdir', [this.cwdfabs])
  if (
this.cache.hasOwnProperty(f)) {
    var 
this.cache[f]
    if (Array.
isArray(c)) {
      if (
this.sync) return cb.call(thisnullc)
      return 
process.nextTick(cb.bind(thisnullc))
    }

    if (!
|| === 1) {
      
// either ENOENT or ENOTDIR
      
var code "ENOTDIR" "ENOENT"
      
er = new Error(("Not a directory" "Not found") + ": " f)
      
er.path f
      er
.code code
      this
.log(fer)
      if (
this.sync) return cb.call(thiser)
      return 
process.nextTick(cb.bind(thiser))
    }

    
// at this point, c === 2, meaning it's a dir, but we haven't
    // had to read it yet, or c === true, meaning it's *something*
    // but we don't have any idea what.  Need to read it, either way.
  
}

  if (
this.sync) {
    var 
erentries
    
try {
      
entries fs.readdirSync(abs)
    } catch (
e) {
      
er e
    
}
    return 
this._afterReaddir(fabscberentries)
  }

  
fs.readdir(absthis._afterReaddir.bind(thisfabscb))
}

Glob.prototype._afterReaddir = function (fabscberentries) {
  
assert(this instanceof Glob)
  if (
entries && !er) {
    
this.cache[f] = entries
    
// if we haven't asked to stat everything for suresies, then just
    // assume that everything in there exists, so we can avoid
    // having to stat it a second time.  This also gets us one step
    // further into ELOOP territory.
    
if (!this.mark && !this.stat) {
      
entries.forEach(function (e) {
        if (
=== "/"e
        
else "/" e
        this
.cache[e] = true
      
}, this)
    }

    return 
cb.call(thiserentries)
  }

  
// now handle errors, and cache the information
  
if (er) switch (er.code) {
    case 
"ENOTDIR"// totally normal. means it *does* exist.
      
this.cache[f] = 1
      
return cb.call(thiser)
    case 
"ENOENT"// not terribly unusual
    
case "ELOOP":
    case 
"ENAMETOOLONG":
    case 
"UNKNOWN":
      
this.cache[f] = false
      
return cb.call(thiser)
    default: 
// some unusual error.  Treat as failure.
      
this.cache[f] = false
      
if (this.strictthis.emit("error"er)
      if (!
this.silentconsole.error("glob error"er)
      return 
cb.call(thiser)
  }
}

var 
isAbsolute process.platform === "win32" absWin absUnix

function absWin (p) {
  if (
absUnix(p)) return true
  
// pull off the device/UNC bit from a windows path.
  // from node's lib/path.js
  
var splitDeviceRe =
      /^([
a-zA-Z]:|[\/]{2}[^\/]+[\/]+[^\/]+)?([\/])?([sS]*?)$/
    , 
result splitDeviceRe.exec(p)
    , 
device result[1] || ''
    
isUnc device && device.charAt(1) !== ':'
    
isAbsolute = !!result[2] || isUnc // UNC paths are always absolute

  
return isAbsolute
}

function 
absUnix (p) {
  return 
p.charAt(0) === "/" || === ""
}
?>
Онлайн: 1
Реклама