From cc05907323b88e965d0f95f2389f2f7dcb9e98d2 Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 29 Apr 2013 08:57:26 -0700 Subject: glob@3.2.1 --- node_modules/glob/glob.js | 98 +++++++++++++++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 33 deletions(-) (limited to 'node_modules/glob/glob.js') diff --git a/node_modules/glob/glob.js b/node_modules/glob/glob.js index 891c88360..f0118a4f4 100644 --- a/node_modules/glob/glob.js +++ b/node_modules/glob/glob.js @@ -98,6 +98,7 @@ function Glob (pattern, options, cb) { this.maxDepth = options.maxDepth || 1000 this.maxLength = options.maxLength || Infinity + this.cache = options.cache || {} this.statCache = options.statCache || {} this.changedCwd = false @@ -150,6 +151,10 @@ function Glob (pattern, options, cb) { 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 @@ -207,7 +212,7 @@ Glob.prototype._finish = function () { if (this.mark) { // at *some* point we statted all of these all = all.map(function (m) { - var sc = this.statCache[m] + var sc = this.cache[m] if (!sc) return m var isDir = (Array.isArray(sc) || sc === 2) @@ -261,8 +266,17 @@ Glob.prototype.resume = function () { } Glob.prototype.emitMatch = function (m) { - this._emitQueue.push(m) - this._processEmitQueue() + if (!this.stat || this.statCache[m] || m === this.EOF) { + this._emitQueue.push(m) + this._processEmitQueue() + } else { + this._stat(m, function(exists, isDir) { + if (exists) { + this._emitQueue.push(m) + this._processEmitQueue() + } + }) + } } Glob.prototype._processEmitQueue = function (m) { @@ -324,11 +338,11 @@ Glob.prototype._process = function (pattern, depth, index, cb_) { // nothing more to do, either way. if (exists) { if (prefix && isAbsolute(prefix) && !this.nomount) { - if (prefix.charAt(0) === "/") { + if (prefix.charAt(0) === "/") { prefix = path.join(this.root, prefix) - } else { - prefix = path.resolve(this.root, prefix) - } + } else { + prefix = path.resolve(this.root, prefix) + } } if (process.platform === "win32") @@ -396,6 +410,16 @@ Glob.prototype._process = function (pattern, depth, index, cb_) { s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n))) }, this) + s = 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 l = s.length , errState = null @@ -414,19 +438,13 @@ Glob.prototype._process = function (pattern, depth, index, cb_) { // 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] - if (typeof pn === "string") { - var found = entries.indexOf(pn) !== -1 - entries = found ? entries[pn] : [] - } else { - var rawGlob = pattern[n]._glob - , dotOk = this.dot || rawGlob.charAt(0) === "." + var rawGlob = pattern[n]._glob + , dotOk = this.dot || rawGlob.charAt(0) === "." - entries = entries.filter(function (e) { - return (e.charAt(0) !== "." || dotOk) && - (typeof pattern[n] === "string" && e === pattern[n] || - e.match(pattern[n])) - }) - } + 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. @@ -471,6 +489,12 @@ Glob.prototype._process = function (pattern, depth, index, cb_) { } +function gsKey (pattern) { + return '**' + pattern.map(function (p) { + return (p === minimatch.GLOBSTAR) ? '**' : (''+p) + }).join('/') +} + Glob.prototype._stat = function (f, cb) { assert(this instanceof Glob) var abs = f @@ -479,7 +503,7 @@ Glob.prototype._stat = function (f, cb) { } else if (this.changedCwd) { abs = path.resolve(this.cwd, f) } - this.log('stat', [this.cwd, f, '=', abs]) + if (f.length > this.maxLength) { var er = new Error("Path name too long") er.code = "ENAMETOOLONG" @@ -487,15 +511,18 @@ Glob.prototype._stat = function (f, cb) { return this._afterStat(f, abs, cb, er) } - if (this.statCache.hasOwnProperty(f)) { - var exists = this.statCache[f] + this.log('stat', [this.cwd, f, '=', 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, !!exists, isDir) return process.nextTick(cb.bind(this, !!exists, isDir)) } - if (this.sync) { - var er, stat + var stat = this.statCache[abs] + if (this.sync || stat) { + var er try { stat = fs.statSync(abs) } catch (e) { @@ -520,12 +547,17 @@ Glob.prototype._afterStat = function (f, abs, cb, er, stat) { stat = null } + var emit = !this.statCache[abs] + this.statCache[abs] = stat + if (er || !stat) { exists = false } else { exists = stat.isDirectory() ? 2 : 1 + if (emit) + this.emit('stat', f, stat) } - this.statCache[f] = this.statCache[f] || exists + this.cache[f] = this.cache[f] || exists cb.call(this, !!exists, exists === 2) } @@ -540,7 +572,6 @@ Glob.prototype._readdir = function (f, cb) { abs = path.resolve(this.cwd, f) } - this.log('readdir', [this.cwd, f, abs]) if (f.length > this.maxLength) { var er = new Error("Path name too long") er.code = "ENAMETOOLONG" @@ -548,8 +579,9 @@ Glob.prototype._readdir = function (f, cb) { return this._afterReaddir(f, abs, cb, er) } - if (this.statCache.hasOwnProperty(f)) { - var c = this.statCache[f] + this.log('readdir', [this.cwd, f, abs]) + if (this.cache.hasOwnProperty(f)) { + var c = this.cache[f] if (Array.isArray(c)) { if (this.sync) return cb.call(this, null, c) return process.nextTick(cb.bind(this, null, c)) @@ -587,7 +619,7 @@ Glob.prototype._readdir = function (f, cb) { Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) { assert(this instanceof Glob) if (entries && !er) { - this.statCache[f] = entries + 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 @@ -596,7 +628,7 @@ Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) { entries.forEach(function (e) { if (f === "/") e = f + e else e = f + "/" + e - this.statCache[e] = true + this.cache[e] = true }, this) } @@ -606,16 +638,16 @@ Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) { // now handle errors, and cache the information if (er) switch (er.code) { case "ENOTDIR": // totally normal. means it *does* exist. - this.statCache[f] = 1 + this.cache[f] = 1 return cb.call(this, er) case "ENOENT": // not terribly unusual case "ELOOP": case "ENAMETOOLONG": case "UNKNOWN": - this.statCache[f] = false + this.cache[f] = false return cb.call(this, er) default: // some unusual error. Treat as failure. - this.statCache[f] = false + this.cache[f] = false if (this.strict) this.emit("error", er) if (!this.silent) console.error("glob error", er) return cb.call(this, er) -- cgit v1.2.3