mirror of
https://github.com/electron/node-gyp.git
synced 2025-09-16 22:13:39 +02:00
Update bundled node-glob.
This commit is contained in:
parent
a29d3f7d5f
commit
a35dd339c6
28 changed files with 2538 additions and 329 deletions
173
node_modules/glob/README.md
generated
vendored
173
node_modules/glob/README.md
generated
vendored
|
@ -47,27 +47,56 @@ See:
|
||||||
* `man 5 gitignore`
|
* `man 5 gitignore`
|
||||||
* [minimatch documentation](https://github.com/isaacs/minimatch)
|
* [minimatch documentation](https://github.com/isaacs/minimatch)
|
||||||
|
|
||||||
## Glob Class
|
## glob(pattern, [options], cb)
|
||||||
|
|
||||||
Create a glob object by instanting the `glob.Glob` class.
|
* `pattern` {String} Pattern to be matched
|
||||||
|
* `options` {Object}
|
||||||
|
* `cb` {Function}
|
||||||
|
* `err` {Error | null}
|
||||||
|
* `matches` {Array<String>} filenames found matching the pattern
|
||||||
|
|
||||||
|
Perform an asynchronous glob search.
|
||||||
|
|
||||||
|
## glob.sync(pattern, [options]
|
||||||
|
|
||||||
|
* `pattern` {String} Pattern to be matched
|
||||||
|
* `options` {Object}
|
||||||
|
* return: {Array<String>} filenames found matching the pattern
|
||||||
|
|
||||||
|
Perform a synchronous glob search.
|
||||||
|
|
||||||
|
## Class: glob.Glob
|
||||||
|
|
||||||
|
Create a Glob object by instanting the `glob.Glob` class.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var Glob = require("glob").Glob
|
var Glob = require("glob").Glob
|
||||||
var mg = new Glob(pattern, options)
|
var mg = new Glob(pattern, options, cb)
|
||||||
```
|
```
|
||||||
|
|
||||||
It's an EventEmitter.
|
It's an EventEmitter, and starts walking the filesystem to find matches
|
||||||
|
immediately.
|
||||||
|
|
||||||
|
### new glob.Glob(pattern, [options], [cb])
|
||||||
|
|
||||||
|
* `pattern` {String} pattern to search for
|
||||||
|
* `options` {Object}
|
||||||
|
* `cb` {Function} Called when an error occurs, or matches are found
|
||||||
|
* `err` {Error | null}
|
||||||
|
* `matches` {Array<String>} filenames found matching the pattern
|
||||||
|
|
||||||
|
Note that if the `sync` flag is set in the options, then matches will
|
||||||
|
be immediately available on the `g.found` member.
|
||||||
|
|
||||||
### Properties
|
### Properties
|
||||||
|
|
||||||
* `minimatch` The minimatch object that the glob uses.
|
* `minimatch` The minimatch object that the glob uses.
|
||||||
* `options` The options object passed in.
|
* `options` The options object passed in.
|
||||||
* `matches` A [FastList](https://github.com/isaacs/fast-list) object
|
|
||||||
containing the matches as they are found.
|
|
||||||
* `error` The error encountered. When an error is encountered, the
|
* `error` The error encountered. When an error is encountered, the
|
||||||
glob object is in an undefined state, and should be discarded.
|
glob object is in an undefined state, and should be discarded.
|
||||||
* `aborted` Boolean which is set to true when calling `abort()`. There
|
* `aborted` Boolean which is set to true when calling `abort()`. There
|
||||||
is no way at this time to continue a glob search after aborting.
|
is no way at this time to continue a glob search after aborting, but
|
||||||
|
you can re-use the statCache to avoid having to duplicate syscalls.
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
|
@ -75,10 +104,9 @@ It's an EventEmitter.
|
||||||
matches found. If the `nonull` option is set, and no match was found,
|
matches found. If the `nonull` option is set, and no match was found,
|
||||||
then the `matches` list contains the original pattern. The matches
|
then the `matches` list contains the original pattern. The matches
|
||||||
are sorted, unless the `nosort` flag is set.
|
are sorted, unless the `nosort` flag is set.
|
||||||
* `match` Every time a match is found, this is emitted with the pattern.
|
* `match` Every time a match is found, this is emitted with the matched.
|
||||||
* `partial` Emitted when a directory matches the start of a pattern, and
|
* `error` Emitted when an unexpected error is encountered, or whenever
|
||||||
is then searched for additional matches.
|
any fs error occurs if `options.strict` is set.
|
||||||
* `error` Emitted when an unexpected error is encountered.
|
|
||||||
* `abort` When `abort()` is called, this event is raised.
|
* `abort` When `abort()` is called, this event is raised.
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
@ -88,27 +116,118 @@ It's an EventEmitter.
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
All the options that can be passed to Minimatch can also be passed to
|
All the options that can be passed to Minimatch can also be passed to
|
||||||
Glob to change pattern matching behavior. Additionally, these ones
|
Glob to change pattern matching behavior. Also, some have been added,
|
||||||
are added which are glob-specific, or have glob-specific ramifcations.
|
or have glob-specific ramifications.
|
||||||
|
|
||||||
All options are false by default.
|
All options are false by default, unless otherwise noted.
|
||||||
|
|
||||||
* `cwd` The current working directory in which to search. Since, unlike
|
All options are added to the glob object, as well.
|
||||||
Minimatch, Glob requires a working directory to start in, this
|
|
||||||
defaults to `process.cwd()`.
|
* `cwd` The current working directory in which to search. Defaults
|
||||||
* `root` Since Glob requires a root setting, this defaults to
|
to `process.cwd()`.
|
||||||
`path.resolve(options.cwd, "/")`.
|
* `root` The place where patterns starting with `/` will be mounted
|
||||||
* `mark` Add a `/` character to directory matches.
|
onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
|
||||||
* `follow` Use `stat` instead of `lstat`. This is only relevant if
|
systems, and `C:\` or some such on Windows.)
|
||||||
`stat` or `mark` are true.
|
* `nomount` By default, a pattern starting with a forward-slash will be
|
||||||
|
"mounted" onto the root setting, so that a valid filesystem path is
|
||||||
|
returned. Set this flag to disable that behavior.
|
||||||
|
* `mark` Add a `/` character to directory matches. Note that this
|
||||||
|
requires additional stat calls.
|
||||||
* `nosort` Don't sort the results.
|
* `nosort` Don't sort the results.
|
||||||
* `stat` Set to true to stat/lstat *all* results. This reduces performance
|
* `stat` Set to true to stat *all* results. This reduces performance
|
||||||
somewhat, but guarantees that the results are files that actually
|
somewhat, and is completely unnecessary, unless `readdir` is presumed
|
||||||
exist.
|
to be an untrustworthy indicator of file existence. It will cause
|
||||||
* `silent` When an error other than `ENOENT` or `ENOTDIR` is encountered
|
ELOOP to be triggered one level sooner in the case of cyclical
|
||||||
|
symbolic links.
|
||||||
|
* `silent` When an unusual error is encountered
|
||||||
when attempting to read a directory, a warning will be printed to
|
when attempting to read a directory, a warning will be printed to
|
||||||
stderr. Set the `silent` option to true to suppress these warnings.
|
stderr. Set the `silent` option to true to suppress these warnings.
|
||||||
* `strict` When an error other than `ENOENT` or `ENOTDIR` is encountered
|
* `strict` When an unusual error is encountered
|
||||||
when attempting to read a directory, the process will just continue on
|
when attempting to read a directory, the process will just continue on
|
||||||
in search of other matches. Set the `strict` option to raise an error
|
in search of other matches. Set the `strict` option to raise an error
|
||||||
in these cases.
|
in these cases.
|
||||||
|
* `statCache` A cache of results of filesystem information, to prevent
|
||||||
|
unnecessary stat calls. While it should not normally be necessary to
|
||||||
|
set this, you may pass the statCache from one glob() call to the
|
||||||
|
options object of another, if you know that the filesystem will not
|
||||||
|
change between calls. (See "Race Conditions" below.)
|
||||||
|
* `sync` Perform a synchronous glob search.
|
||||||
|
* `nounique` In some cases, brace-expanded patterns can result in the
|
||||||
|
same file showing up multiple times in the result set. By default,
|
||||||
|
this implementation prevents duplicates in the result set.
|
||||||
|
Set this flag to disable that behavior.
|
||||||
|
* `nonull` Set to never return an empty set, instead returning a set
|
||||||
|
containing the pattern itself. This is the default in glob(3).
|
||||||
|
* `nocase` Perform a case-insensitive match. Note that case-insensitive
|
||||||
|
filesystems will sometimes result in glob returning results that are
|
||||||
|
case-insensitively matched anyway, since readdir and stat will not
|
||||||
|
raise an error.
|
||||||
|
* `debug` Set to enable debug logging in minimatch and glob.
|
||||||
|
* `globDebug` Set to enable debug logging in glob, but not minimatch.
|
||||||
|
|
||||||
|
## Comparisons to other fnmatch/glob implementations
|
||||||
|
|
||||||
|
While strict compliance with the existing standards is a worthwhile
|
||||||
|
goal, some discrepancies exist between node-glob and other
|
||||||
|
implementations, and are intentional.
|
||||||
|
|
||||||
|
If the pattern starts with a `!` character, then it is negated. Set the
|
||||||
|
`nonegate` flag to suppress this behavior, and treat leading `!`
|
||||||
|
characters normally. This is perhaps relevant if you wish to start the
|
||||||
|
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
|
||||||
|
characters at the start of a pattern will negate the pattern multiple
|
||||||
|
times.
|
||||||
|
|
||||||
|
If a pattern starts with `#`, then it is treated as a comment, and
|
||||||
|
will not match anything. Use `\#` to match a literal `#` at the
|
||||||
|
start of a line, or set the `nocomment` flag to suppress this behavior.
|
||||||
|
|
||||||
|
The double-star character `**` is supported by default, unless the
|
||||||
|
`noglobstar` flag is set. This is supported in the manner of bsdglob
|
||||||
|
and bash 4.1, where `**` only has special significance if it is the only
|
||||||
|
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
|
||||||
|
`a/**b` will not. **Note that this is different from the way that `**` is
|
||||||
|
handled by ruby's `Dir` class.**
|
||||||
|
|
||||||
|
If an escaped pattern has no matches, and the `nonull` flag is set,
|
||||||
|
then glob returns the pattern as-provided, rather than
|
||||||
|
interpreting the character escapes. For example,
|
||||||
|
`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
|
||||||
|
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
|
||||||
|
that it does not resolve escaped pattern characters.
|
||||||
|
|
||||||
|
If brace expansion is not disabled, then it is performed before any
|
||||||
|
other interpretation of the glob pattern. Thus, a pattern like
|
||||||
|
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
|
||||||
|
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
|
||||||
|
checked for validity. Since those two are valid, matching proceeds.
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
**Please only use forward-slashes in glob expressions.**
|
||||||
|
|
||||||
|
Though windows uses either `/` or `\` as its path separator, only `/`
|
||||||
|
characters are used by this glob implementation. You must use
|
||||||
|
forward-slashes **only** in glob expressions. Back-slashes will always
|
||||||
|
be interpreted as escape characters, not path separators.
|
||||||
|
|
||||||
|
Results from absolute patterns such as `/foo/*` are mounted onto the
|
||||||
|
root setting using `path.join`. On windows, this will by default result
|
||||||
|
in `/foo/*` matching `C:\foo\bar.txt`.
|
||||||
|
|
||||||
|
## Race Conditions
|
||||||
|
|
||||||
|
Glob searching, by its very nature, is susceptible to race conditions,
|
||||||
|
since it relies on directory walking and such.
|
||||||
|
|
||||||
|
As a result, it is possible that a file that exists when glob looks for
|
||||||
|
it may have been deleted or modified by the time it returns the result.
|
||||||
|
|
||||||
|
As part of its internal implementation, this program caches all stat
|
||||||
|
and readdir calls that it makes, in order to cut down on system
|
||||||
|
overhead. However, this also makes it even more susceptible to races,
|
||||||
|
especially if the statCache object is reused between glob calls.
|
||||||
|
|
||||||
|
Users are thus advised not to use a glob result as a
|
||||||
|
guarantee of filesystem state in the face of rapid changes.
|
||||||
|
For the vast majority of operations, this is never a problem.
|
||||||
|
|
732
node_modules/glob/glob.js
generated
vendored
732
node_modules/glob/glob.js
generated
vendored
|
@ -1,3 +1,39 @@
|
||||||
|
// 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+1]
|
||||||
|
// 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
|
module.exports = glob
|
||||||
|
|
||||||
var fs = require("graceful-fs")
|
var fs = require("graceful-fs")
|
||||||
|
@ -5,27 +41,9 @@ var fs = require("graceful-fs")
|
||||||
, Minimatch = minimatch.Minimatch
|
, Minimatch = minimatch.Minimatch
|
||||||
, inherits = require("inherits")
|
, inherits = require("inherits")
|
||||||
, EE = require("events").EventEmitter
|
, EE = require("events").EventEmitter
|
||||||
, FastList = require("fast-list")
|
|
||||||
, path = require("path")
|
, path = require("path")
|
||||||
, isDir = {}
|
, isDir = {}
|
||||||
|
, assert = require("assert")
|
||||||
// Globbing is a *little* bit different than just matching, in some
|
|
||||||
// key ways.
|
|
||||||
//
|
|
||||||
// First, and importantly, it matters a great deal whether a pattern
|
|
||||||
// is "absolute" or "relative". Absolute patterns are patterns that
|
|
||||||
// start with / on unix, or a full device/unc path on windows.
|
|
||||||
//
|
|
||||||
// Second, globs interact with the actual filesystem, so being able
|
|
||||||
// to stop searching as soon as a match is no longer possible is of
|
|
||||||
// the utmost importance. It would not do to traverse a large file
|
|
||||||
// tree, and then eliminate all but one of the options, if it could
|
|
||||||
// be possible to skip the traversal early.
|
|
||||||
|
|
||||||
// Get a Minimatch object from the pattern and options. Then, starting
|
|
||||||
// from the options.root or the cwd, read the dir, and do a partial
|
|
||||||
// match on all the files if it's a dir, or a regular match if it's not.
|
|
||||||
|
|
||||||
|
|
||||||
function glob (pattern, options, cb) {
|
function glob (pattern, options, cb) {
|
||||||
if (typeof options === "function") cb = options, options = {}
|
if (typeof options === "function") cb = options, options = {}
|
||||||
|
@ -36,13 +54,8 @@ function glob (pattern, options, cb) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var m = new Glob(pattern, options, cb)
|
var g = new Glob(pattern, options, cb)
|
||||||
|
return g.sync ? g.found : g
|
||||||
if (options.sync) {
|
|
||||||
return m.found
|
|
||||||
} else {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glob.fnmatch = deprecated
|
glob.fnmatch = deprecated
|
||||||
|
@ -73,330 +86,457 @@ function Glob (pattern, options, cb) {
|
||||||
|
|
||||||
if (typeof cb === "function") {
|
if (typeof cb === "function") {
|
||||||
this.on("error", cb)
|
this.on("error", cb)
|
||||||
this.on("end", function (matches) { cb(null, matches) })
|
this.on("end", function (matches) {
|
||||||
|
// console.error("cb with matches", matches)
|
||||||
|
cb(null, matches)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
options = options || {}
|
options = options || {}
|
||||||
|
|
||||||
if (!options.hasOwnProperty("maxDepth")) options.maxDepth = 1000
|
this.maxDepth = options.maxDepth || 1000
|
||||||
if (!options.hasOwnProperty("maxLength")) options.maxLength = 4096
|
this.maxLength = options.maxLength || Infinity
|
||||||
|
this.statCache = options.statCache || {}
|
||||||
|
|
||||||
var cwd = this.cwd = options.cwd =
|
this.changedCwd = false
|
||||||
options.cwd || process.cwd()
|
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 =
|
this.root = options.root || path.resolve(this.cwd, "/")
|
||||||
options.root || path.resolve(cwd, "/")
|
this.root = path.resolve(this.root)
|
||||||
|
|
||||||
|
this.nomount = !!options.nomount
|
||||||
|
|
||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
throw new Error("must provide pattern")
|
throw new Error("must provide pattern")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// base-matching: just use globstar for that.
|
||||||
|
if (options.matchBase && -1 === pattern.indexOf("/")) {
|
||||||
|
if (options.noglobstar) {
|
||||||
|
throw new Error("base matching requires globstar")
|
||||||
|
}
|
||||||
|
pattern = "**/" + pattern
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
this.silent = !!options.silent
|
||||||
|
|
||||||
var mm = this.minimatch = new Minimatch(pattern, options)
|
var mm = this.minimatch = new Minimatch(pattern, options)
|
||||||
options = this.options = mm.options
|
this.options = mm.options
|
||||||
pattern = this.pattern = mm.pattern
|
pattern = this.pattern = mm.pattern
|
||||||
|
|
||||||
this.error = null
|
this.error = null
|
||||||
this.aborted = false
|
this.aborted = false
|
||||||
|
|
||||||
this.matches = new FastList()
|
|
||||||
EE.call(this)
|
EE.call(this)
|
||||||
var me = this
|
|
||||||
|
|
||||||
this._checkedRoot = false
|
// process each pattern in the minimatch set
|
||||||
|
var n = this.minimatch.set.length
|
||||||
|
|
||||||
// if we have any patterns starting with /, then we need to
|
// The matches are stored as {<filename>: true,...} so that
|
||||||
// start at the root. If we don't, then we can take a short
|
// duplicates are automagically pruned.
|
||||||
// cut and just start at the cwd.
|
// Later, we do an Object.keys() on these.
|
||||||
var start = this.cwd
|
// Keep them as a list so we can fill in when nonull is set.
|
||||||
for (var i = 0, l = this.minimatch.set.length; i < l; i ++) {
|
this.matches = new Array(n)
|
||||||
if (this.minimatch.set[i].absolute) {
|
|
||||||
start = this.root
|
this.minimatch.set.forEach(iterator.bind(this))
|
||||||
break
|
function iterator (pattern, i, set) {
|
||||||
}
|
this._process(pattern, 0, i, function (er) {
|
||||||
|
if (er) this.emit("error", er)
|
||||||
|
if (-- n <= 0) this._finish()
|
||||||
|
}.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error("start =", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
this._process(start, 1, this._finish.bind(this))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Glob.prototype._finish = _finish
|
Glob.prototype._finish = function () {
|
||||||
function _finish () {
|
assert(this instanceof Glob)
|
||||||
var me = this
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error("!!! GLOB top level cb", me)
|
|
||||||
}
|
|
||||||
if (me.options.nonull && me.matches.length === 0) {
|
|
||||||
return me.emit("end", [pattern])
|
|
||||||
}
|
|
||||||
|
|
||||||
var found = me.found = me.matches.slice()
|
var nou = this.nounique
|
||||||
|
, all = nou ? [] : {}
|
||||||
|
|
||||||
found = me.found = found.map(function (m) {
|
for (var i = 0, l = this.matches.length; i < l; i ++) {
|
||||||
if (m.indexOf(me.options.cwd) === 0) {
|
var matches = this.matches[i]
|
||||||
m = m.substr(me.options.cwd.length + 1)
|
if (this.debug) console.error("matches[%d] =", i, matches)
|
||||||
}
|
// do like the shell, and spit out the literal glob
|
||||||
return m
|
if (!matches) {
|
||||||
})
|
if (this.nonull) {
|
||||||
|
var literal = this.minimatch.globSet[i]
|
||||||
if (!me.options.mark) return next()
|
if (nou) all.push(literal)
|
||||||
|
else nou[literal] = true
|
||||||
// mark all directories with a /.
|
|
||||||
// This may involve some stat calls for things that are unknown.
|
|
||||||
var needStat = []
|
|
||||||
found = me.found = found.map(function (f) {
|
|
||||||
if (isDir[f] === undefined) needStat.push(f)
|
|
||||||
else if (isDir[f] && f.slice(-1) !== "/") f += "/"
|
|
||||||
return f
|
|
||||||
})
|
|
||||||
var c = needStat.length
|
|
||||||
if (c === 0) return next()
|
|
||||||
|
|
||||||
var stat = me.options.follow ? "stat" : "lstat"
|
|
||||||
needStat.forEach(function (f) {
|
|
||||||
if (me.options.sync) {
|
|
||||||
try {
|
|
||||||
afterStat(f)(null, fs[stat + "Sync"](f))
|
|
||||||
} catch (er) {
|
|
||||||
afterStat(f)(er)
|
|
||||||
}
|
|
||||||
} else fs[stat](f, afterStat(f))
|
|
||||||
})
|
|
||||||
|
|
||||||
function afterStat (f) { return function (er, st) {
|
|
||||||
// ignore errors. if the user only wants to show
|
|
||||||
// existing files, then set options.stat to exclude anything
|
|
||||||
// that doesn't exist.
|
|
||||||
if (st && st.isDirectory() && f.substr(-1) !== "/") {
|
|
||||||
var i = found.indexOf(f)
|
|
||||||
if (i !== -1) {
|
|
||||||
found.splice(i, 1, f + "/")
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// had matches
|
||||||
|
var m = Object.keys(matches)
|
||||||
|
if (nou) all.push.apply(all, m)
|
||||||
|
else m.forEach(function (m) {
|
||||||
|
all[m] = true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if (-- c <= 0) return next()
|
|
||||||
}}
|
|
||||||
|
|
||||||
function next () {
|
|
||||||
if (!me.options.nosort) {
|
|
||||||
found = found.sort(alphasort)
|
|
||||||
}
|
|
||||||
me.emit("end", found)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nou) all = 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.statCache[m]
|
||||||
|
if (!sc) return m
|
||||||
|
if (m.slice(-1) !== "/" && (Array.isArray(sc) || sc === 2)) {
|
||||||
|
return m + "/"
|
||||||
|
}
|
||||||
|
if (m.slice(-1) === "/") {
|
||||||
|
return m.replace(/\/$/, "")
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.debug) console.error("emitting end", all)
|
||||||
|
|
||||||
|
this.found = all
|
||||||
|
this.emit("end", all)
|
||||||
|
}
|
||||||
|
|
||||||
|
function alphasorti (a, b) {
|
||||||
|
a = a.toLowerCase()
|
||||||
|
b = b.toLowerCase()
|
||||||
|
return alphasort(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
function alphasort (a, b) {
|
function alphasort (a, b) {
|
||||||
a = a.toLowerCase()
|
|
||||||
b = b.toLowerCase()
|
|
||||||
return a > b ? 1 : a < b ? -1 : 0
|
return a > b ? 1 : a < b ? -1 : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Glob.prototype.abort = abort
|
Glob.prototype.abort = function () {
|
||||||
function abort () {
|
|
||||||
this.aborted = true
|
this.aborted = true
|
||||||
this.emit("abort")
|
this.emit("abort")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Glob.prototype._process = _process
|
Glob.prototype._process = function (pattern, depth, index, cb) {
|
||||||
function _process (f, depth, cb) {
|
assert(this instanceof Glob)
|
||||||
|
cb = cb.bind(this)
|
||||||
if (this.aborted) return cb()
|
if (this.aborted) return cb()
|
||||||
|
|
||||||
var me = this
|
if (depth > this.maxDepth) return cb()
|
||||||
|
|
||||||
// if f matches, then it's a match. emit it, move on.
|
// Get the first [n] parts of pattern that are all strings.
|
||||||
// if it *partially* matches, then it might be a dir.
|
var n = 0
|
||||||
//
|
while (typeof pattern[n] === "string") {
|
||||||
// possible optimization: don't just minimatch everything
|
n ++
|
||||||
// against the full pattern. if a bit of the pattern is
|
|
||||||
// not magical, it'd be good to reduce the number of stats
|
|
||||||
// that had to be made. so, in the pattern: "a/*/b", we could
|
|
||||||
// readdir a, then stat a/<child>/b in all of them.
|
|
||||||
//
|
|
||||||
// however, that'll require a lot of muddying between minimatch
|
|
||||||
// and glob, and at least for the time being, it's kind of nice to
|
|
||||||
// keep them a little bit separate.
|
|
||||||
|
|
||||||
// if this thing is a match, then add to the matches list.
|
|
||||||
var match = me.minimatch.match(f)
|
|
||||||
if (!match) {
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error("not a match", f)
|
|
||||||
}
|
|
||||||
return me._processPartial(f, depth, cb)
|
|
||||||
}
|
}
|
||||||
|
// now n is the index of the first one that is *not* a string.
|
||||||
|
|
||||||
if (match) {
|
// see if there's anything else
|
||||||
if (me.options.debug) {
|
var prefix
|
||||||
console.error(" %s matches %s", f, me.pattern)
|
switch (n) {
|
||||||
}
|
// if not, then this is rather simple
|
||||||
// make sure it exists if asked.
|
case pattern.length:
|
||||||
if (me.options.stat) {
|
prefix = pattern.join("/")
|
||||||
var stat = me.options.follow ? "stat" : "lstat"
|
this._stat(prefix, function (exists, isDir) {
|
||||||
if (me.options.sync) {
|
// either it's there, or it isn't.
|
||||||
try {
|
// nothing more to do, either way.
|
||||||
afterStat(f)(null, fs[stat + "Sync"](f))
|
if (exists) {
|
||||||
} catch (ex) {
|
if (prefix.charAt(0) === "/" && !this.nomount) {
|
||||||
afterStat(f)(ex)
|
prefix = path.join(this.root, prefix)
|
||||||
|
}
|
||||||
|
this.matches[index] = this.matches[index] || {}
|
||||||
|
this.matches[index][prefix] = true
|
||||||
|
this.emit("match", prefix)
|
||||||
}
|
}
|
||||||
} else fs[stat](f, afterStat(f))
|
return cb()
|
||||||
} else if (me.options.sync) {
|
})
|
||||||
emitMatch()
|
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(0, n)
|
||||||
|
prefix = prefix.join("/")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the list of entries.
|
||||||
|
var read
|
||||||
|
if (prefix === null) read = "."
|
||||||
|
else if (isAbsolute(prefix)) {
|
||||||
|
read = prefix = path.join("/", prefix)
|
||||||
|
if (this.debug) console.error('absolute: ', prefix, this.root, pattern)
|
||||||
|
} else read = prefix
|
||||||
|
|
||||||
|
if (this.debug) console.error('readdir(%j)', read, this.cwd, this.root)
|
||||||
|
return this._readdir(read, function (er, entries) {
|
||||||
|
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 s = [ pattern.slice(0, n).concat(pattern.slice(n + 1)) ]
|
||||||
|
entries.forEach(function (e) {
|
||||||
|
if (e.charAt(0) === "." && !this.dot) return
|
||||||
|
// instead of the globstar
|
||||||
|
s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1)))
|
||||||
|
// below the globstar
|
||||||
|
s.push(pattern.slice(0, n).concat(e).concat(pattern.slice(n)))
|
||||||
|
}, this)
|
||||||
|
|
||||||
|
// now asyncForEach over this
|
||||||
|
var l = s.length
|
||||||
|
, errState = null
|
||||||
|
s.forEach(function (gsPattern) {
|
||||||
|
this._process(gsPattern, depth + 1, index, function (er) {
|
||||||
|
if (errState) return
|
||||||
|
if (er) return cb(errState = er)
|
||||||
|
if (--l <= 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]
|
||||||
|
if (typeof pn === "string") {
|
||||||
|
var found = entries.indexOf(pn) !== -1
|
||||||
|
entries = found ? entries[pn] : []
|
||||||
} else {
|
} else {
|
||||||
process.nextTick(emitMatch)
|
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]))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
// 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 (n === pattern.length - 1 &&
|
||||||
|
!this.mark &&
|
||||||
|
!this.stat) {
|
||||||
|
entries.forEach(function (e) {
|
||||||
|
if (prefix) {
|
||||||
|
if (prefix !== "/") e = prefix + "/" + e
|
||||||
|
else e = prefix + e
|
||||||
|
}
|
||||||
|
if (e.charAt(0) === "/" && !this.nomount) {
|
||||||
|
e = path.join(this.root, e)
|
||||||
|
}
|
||||||
|
|
||||||
function afterStat (f) { return function (er, st) {
|
this.matches[index] = this.matches[index] || {}
|
||||||
if (er) return cb()
|
this.matches[index][e] = true
|
||||||
isDir[f] = st.isDirectory()
|
this.emit("match", e)
|
||||||
emitMatch()
|
}, this)
|
||||||
}}
|
return cb.call(this)
|
||||||
|
|
||||||
function emitMatch () {
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error("emitting match", f)
|
|
||||||
}
|
|
||||||
me.matches.push(f)
|
|
||||||
me.emit("match", f)
|
|
||||||
// move on, since it might also be a partial match
|
|
||||||
// eg, a/**/c matches both a/c and a/c/d/c
|
|
||||||
me._processPartial(f, depth, cb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Glob.prototype._processPartial = _processPartial
|
|
||||||
function _processPartial (f, depth, cb) {
|
|
||||||
if (this.aborted) return cb()
|
|
||||||
|
|
||||||
var me = this
|
|
||||||
|
|
||||||
var partial = me.minimatch.match(f, true)
|
|
||||||
if (!partial) {
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error("not a partial", f)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if not a match or partial match, just move on.
|
|
||||||
return cb()
|
|
||||||
}
|
|
||||||
|
|
||||||
// partial match
|
// now test all the remaining entries as stand-ins for that part
|
||||||
// however, this only matters if it's a dir.
|
// of the pattern.
|
||||||
//if (me.options.debug)
|
var l = entries.length
|
||||||
if (me.options.debug) {
|
, errState = null
|
||||||
console.error("got a partial", f)
|
if (l === 0) return cb() // no matches possible
|
||||||
}
|
entries.forEach(function (e) {
|
||||||
me.emit("partial", f)
|
var p = pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1))
|
||||||
|
this._process(p, depth + 1, index, function (er) {
|
||||||
me._processDir(f, depth, cb)
|
if (errState) return
|
||||||
}
|
if (er) return cb(errState = er)
|
||||||
|
if (--l === 0) return cb.call(this)
|
||||||
Glob.prototype._processDir = _processDir
|
}.bind(this))
|
||||||
function _processDir (f, depth, cb) {
|
}, this)
|
||||||
if (this.aborted) return cb()
|
|
||||||
|
|
||||||
// If we're already at the maximum depth, then don't read the dir.
|
|
||||||
if (depth >= this.options.maxDepth) return cb()
|
|
||||||
|
|
||||||
// if the path is at the maximum length, then don't proceed, either.
|
|
||||||
if (f.length >= this.options.maxLength) return cb()
|
|
||||||
|
|
||||||
// now the fun stuff.
|
|
||||||
// if it's a dir, then we'll read all the children, and process them.
|
|
||||||
// if it's not a dir, or we can't access it, then it'll fail.
|
|
||||||
// We log a warning for EACCES and EPERM, but ENOTDIR and ENOENT are
|
|
||||||
// expected and fine.
|
|
||||||
cb = this._afterReaddir(f, depth, cb)
|
|
||||||
if (this.options.sync) return this._processDirSync(f, depth, cb)
|
|
||||||
fs.readdir(f, cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
Glob.prototype._processDirSync = _processDirSync
|
|
||||||
function _processDirSync (f, depth, cb) {
|
|
||||||
try {
|
|
||||||
cb(null, fs.readdirSync(f))
|
|
||||||
} catch (ex) {
|
|
||||||
cb(ex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Glob.prototype._afterReaddir = _afterReaddir
|
|
||||||
function _afterReaddir (f, depth, cb) {
|
|
||||||
var me = this
|
|
||||||
return function afterReaddir (er, children) {
|
|
||||||
if (er) switch (er.code) {
|
|
||||||
case "UNKNOWN": // probably too deep
|
|
||||||
case "ENOTDIR": // completely expected and normal.
|
|
||||||
isDir[f] = false
|
|
||||||
return cb()
|
|
||||||
case "ENOENT": // should never happen.
|
|
||||||
default: // some other kind of problem.
|
|
||||||
if (!me.options.silent) console.error("glob error", er)
|
|
||||||
if (me.options.strict) return cb(er)
|
|
||||||
return cb()
|
|
||||||
}
|
|
||||||
|
|
||||||
// at this point, we know it's a dir, so save a stat later if
|
|
||||||
// mark is set.
|
|
||||||
isDir[f] = true
|
|
||||||
|
|
||||||
me._processChildren(f, depth, children, cb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Glob.prototype._processChildren = _processChildren
|
|
||||||
function _processChildren (f, depth, children, cb) {
|
|
||||||
var me = this
|
|
||||||
|
|
||||||
// note: the file ending with / might match, but only if
|
|
||||||
// it's a directory, which we know it is at this point.
|
|
||||||
// For example, /a/b/ or /a/b/** would match /a/b/ but not
|
|
||||||
// /a/b. Note: it'll get the trailing "/" strictly based
|
|
||||||
// on the "mark" param, but that happens later.
|
|
||||||
// This is slightly different from bash's glob.
|
|
||||||
if (!me.minimatch.match(f) && me.minimatch.match(f + "/")) {
|
|
||||||
me.matches.push(f)
|
|
||||||
me.emit("match", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-1 === children.indexOf(".")) children.push(".")
|
|
||||||
if (-1 === children.indexOf("..")) children.push("..")
|
|
||||||
|
|
||||||
var count = children.length
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error("count=%d %s", count, f, children)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count === 0) {
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error("no children?", children, f)
|
|
||||||
}
|
|
||||||
return then()
|
|
||||||
}
|
|
||||||
|
|
||||||
children.forEach(function (c) {
|
|
||||||
if (f === "/") c = f + c
|
|
||||||
else c = f + "/" + c
|
|
||||||
|
|
||||||
if (me.options.debug) {
|
|
||||||
console.error(" processing", c)
|
|
||||||
}
|
|
||||||
me._process(c, depth + 1, then)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function then (er) {
|
}
|
||||||
count --
|
|
||||||
if (me.options.debug) {
|
Glob.prototype._stat = function (f, cb) {
|
||||||
console.error("%s THEN %s", f, count, count <= 0 ? "done" : "not done")
|
assert(this instanceof Glob)
|
||||||
|
var abs = f
|
||||||
|
if (f.charAt(0) === "/") {
|
||||||
|
abs = path.join(this.root, f)
|
||||||
|
} else if (this.changedCwd) {
|
||||||
|
abs = path.resolve(this.cwd, f)
|
||||||
|
}
|
||||||
|
if (this.debug) console.error('stat', [this.cwd, f, '=', abs])
|
||||||
|
if (f.length > this.maxLength) {
|
||||||
|
var er = new Error("Path name too long")
|
||||||
|
er.code = "ENAMETOOLONG"
|
||||||
|
er.path = f
|
||||||
|
return this._afterStat(f, abs, cb, er)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.statCache.hasOwnProperty(f)) {
|
||||||
|
var exists = this.statCache[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
|
||||||
|
try {
|
||||||
|
stat = fs.statSync(abs)
|
||||||
|
} catch (e) {
|
||||||
|
er = e
|
||||||
}
|
}
|
||||||
if (me.error) return
|
this._afterStat(f, abs, cb, er, stat)
|
||||||
if (er) return me.emit("error", me.error = er)
|
} else {
|
||||||
if (count <= 0) cb()
|
fs.stat(abs, this._afterStat.bind(this, f, abs, cb))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Glob.prototype._afterStat = function (f, abs, cb, er, stat) {
|
||||||
|
assert(this instanceof Glob)
|
||||||
|
if (er || !stat) {
|
||||||
|
exists = false
|
||||||
|
} else {
|
||||||
|
exists = stat.isDirectory() ? 2 : 1
|
||||||
|
}
|
||||||
|
this.statCache[f] = this.statCache[f] || exists
|
||||||
|
cb.call(this, !!exists, exists === 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
Glob.prototype._readdir = function (f, cb) {
|
||||||
|
assert(this instanceof Glob)
|
||||||
|
var abs = f
|
||||||
|
if (f.charAt(0) === "/") {
|
||||||
|
abs = path.join(this.root, f)
|
||||||
|
} else if (isAbsolute(f)) {
|
||||||
|
abs = f
|
||||||
|
} else if (this.changedCwd) {
|
||||||
|
abs = path.resolve(this.cwd, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.debug) console.error('readdir', [this.cwd, f, abs])
|
||||||
|
if (f.length > this.maxLength) {
|
||||||
|
var er = new Error("Path name too long")
|
||||||
|
er.code = "ENAMETOOLONG"
|
||||||
|
er.path = f
|
||||||
|
return this._afterReaddir(f, abs, cb, er)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.statCache.hasOwnProperty(f)) {
|
||||||
|
var c = this.statCache[f]
|
||||||
|
if (Array.isArray(c)) {
|
||||||
|
if (this.sync) return cb.call(this, null, c)
|
||||||
|
return process.nextTick(cb.bind(this, null, c))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c || c === 1) {
|
||||||
|
// either ENOENT or ENOTDIR
|
||||||
|
var code = c ? "ENOTDIR" : "ENOENT"
|
||||||
|
, er = new Error((c ? "Not a directory" : "Not found") + ": " + f)
|
||||||
|
er.path = f
|
||||||
|
er.code = code
|
||||||
|
if (this.debug) console.error(f, er)
|
||||||
|
if (this.sync) return cb.call(this, er)
|
||||||
|
return process.nextTick(cb.bind(this, er))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 er, entries
|
||||||
|
try {
|
||||||
|
entries = fs.readdirSync(abs)
|
||||||
|
} catch (e) {
|
||||||
|
er = e
|
||||||
|
}
|
||||||
|
return this._afterReaddir(f, abs, cb, er, entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.readdir(abs, this._afterReaddir.bind(this, f, abs, cb))
|
||||||
|
}
|
||||||
|
|
||||||
|
Glob.prototype._afterReaddir = function (f, abs, cb, er, entries) {
|
||||||
|
assert(this instanceof Glob)
|
||||||
|
if (entries && !er) {
|
||||||
|
this.statCache[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 (f === "/") e = f + e
|
||||||
|
else e = f + "/" + e
|
||||||
|
this.statCache[e] = true
|
||||||
|
}, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb.call(this, 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
|
||||||
|
return cb.call(this, er)
|
||||||
|
case "ENOENT": // not terribly unusual
|
||||||
|
case "ELOOP":
|
||||||
|
case "ENAMETOOLONG":
|
||||||
|
case "UNKNOWN":
|
||||||
|
this.statCache[f] = false
|
||||||
|
return cb.call(this, er)
|
||||||
|
default: // some unusual error. Treat as failure.
|
||||||
|
this.statCache[f] = false
|
||||||
|
if (this.strict) this.emit("error", er)
|
||||||
|
if (!this.silent) console.error("glob error", er)
|
||||||
|
return cb.call(this, er)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
|
||||||
|
, 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) === "/" || p === ""
|
||||||
|
}
|
||||||
|
|
4
node_modules/glob/node_modules/minimatch/.travis.yml
generated
vendored
Normal file
4
node_modules/glob/node_modules/minimatch/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 0.4
|
||||||
|
- 0.6
|
23
node_modules/glob/node_modules/minimatch/LICENSE
generated
vendored
Normal file
23
node_modules/glob/node_modules/minimatch/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
212
node_modules/glob/node_modules/minimatch/README.md
generated
vendored
Normal file
212
node_modules/glob/node_modules/minimatch/README.md
generated
vendored
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
# minimatch
|
||||||
|
|
||||||
|
A minimal matching utility.
|
||||||
|
|
||||||
|
[](http://travis-ci.org/isaacs/minimatch)
|
||||||
|
|
||||||
|
|
||||||
|
This is the matching library used internally by npm.
|
||||||
|
|
||||||
|
Eventually, it will replace the C binding in node-glob.
|
||||||
|
|
||||||
|
It works by converting glob expressions into JavaScript `RegExp`
|
||||||
|
objects.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var minimatch = require("minimatch")
|
||||||
|
|
||||||
|
minimatch("bar.foo", "*.foo") // true!
|
||||||
|
minimatch("bar.foo", "*.bar") // false!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Supports these glob features:
|
||||||
|
|
||||||
|
* Brace Expansion
|
||||||
|
* Extended glob matching
|
||||||
|
* "Globstar" `**` matching
|
||||||
|
|
||||||
|
See:
|
||||||
|
|
||||||
|
* `man sh`
|
||||||
|
* `man bash`
|
||||||
|
* `man 3 fnmatch`
|
||||||
|
* `man 5 gitignore`
|
||||||
|
|
||||||
|
### Comparisons to other fnmatch/glob implementations
|
||||||
|
|
||||||
|
While strict compliance with the existing standards is a worthwhile
|
||||||
|
goal, some discrepancies exist between minimatch and other
|
||||||
|
implementations, and are intentional.
|
||||||
|
|
||||||
|
If the pattern starts with a `!` character, then it is negated. Set the
|
||||||
|
`nonegate` flag to suppress this behavior, and treat leading `!`
|
||||||
|
characters normally. This is perhaps relevant if you wish to start the
|
||||||
|
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
|
||||||
|
characters at the start of a pattern will negate the pattern multiple
|
||||||
|
times.
|
||||||
|
|
||||||
|
If a pattern starts with `#`, then it is treated as a comment, and
|
||||||
|
will not match anything. Use `\#` to match a literal `#` at the
|
||||||
|
start of a line, or set the `nocomment` flag to suppress this behavior.
|
||||||
|
|
||||||
|
The double-star character `**` is supported by default, unless the
|
||||||
|
`noglobstar` flag is set. This is supported in the manner of bsdglob
|
||||||
|
and bash 4.1, where `**` only has special significance if it is the only
|
||||||
|
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
|
||||||
|
`a/**b` will not. **Note that this is different from the way that `**` is
|
||||||
|
handled by ruby's `Dir` class.**
|
||||||
|
|
||||||
|
If an escaped pattern has no matches, and the `null` flag is not set,
|
||||||
|
then minimatch.match returns the pattern as-provided, rather than
|
||||||
|
interpreting the character escapes. For example,
|
||||||
|
`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
|
||||||
|
`"*a?"`.
|
||||||
|
|
||||||
|
If brace expansion is not disabled, then it is performed before any
|
||||||
|
other interpretation of the glob pattern. Thus, a pattern like
|
||||||
|
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
|
||||||
|
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
|
||||||
|
checked for validity. Since those two are valid, matching proceeds.
|
||||||
|
|
||||||
|
|
||||||
|
## Minimatch Class
|
||||||
|
|
||||||
|
Create a minimatch object by instanting the `minimatch.Minimatch` class.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var Minimatch = require("minimatch").Minimatch
|
||||||
|
var mm = new Minimatch(pattern, options)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
* `pattern` The original pattern the minimatch object represents.
|
||||||
|
* `options` The options supplied to the constructor.
|
||||||
|
* `set` A 2-dimensional array of regexp or string expressions.
|
||||||
|
Each row in the
|
||||||
|
array corresponds to a brace-expanded pattern. Each item in the row
|
||||||
|
corresponds to a single path-part. For example, the pattern
|
||||||
|
`{a,b/c}/d` would expand to a set of patterns like:
|
||||||
|
|
||||||
|
[ [ a, d ]
|
||||||
|
, [ b, c, d ] ]
|
||||||
|
|
||||||
|
If a portion of the pattern doesn't have any "magic" in it
|
||||||
|
(that is, it's something like `"foo"` rather than `fo*o?`), then it
|
||||||
|
will be left as a string rather than converted to a regular
|
||||||
|
expression.
|
||||||
|
|
||||||
|
* `regexp` Created by the `makeRe` method. A single regular expression
|
||||||
|
expressing the entire pattern. This is useful in cases where you wish
|
||||||
|
to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
|
||||||
|
* `negate` True if the pattern is negated.
|
||||||
|
* `comment` True if the pattern is a comment.
|
||||||
|
* `empty` True if the pattern is `""`.
|
||||||
|
|
||||||
|
### Methods
|
||||||
|
|
||||||
|
* `makeRe` Generate the `regexp` member if necessary, and return it.
|
||||||
|
Will return `false` if the pattern is invalid.
|
||||||
|
* `match(fname)` Return true if the filename matches the pattern, or
|
||||||
|
false otherwise.
|
||||||
|
* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
|
||||||
|
filename, and match it against a single row in the `regExpSet`. This
|
||||||
|
method is mainly for internal use, but is exposed so that it can be
|
||||||
|
used by a glob-walker that needs to avoid excessive filesystem calls.
|
||||||
|
|
||||||
|
All other methods are internal, and will be called as necessary.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
The top-level exported function has a `cache` property, which is an LRU
|
||||||
|
cache set to store 100 items. So, calling these methods repeatedly
|
||||||
|
with the same pattern and options will use the same Minimatch object,
|
||||||
|
saving the cost of parsing it multiple times.
|
||||||
|
|
||||||
|
### minimatch(path, pattern, options)
|
||||||
|
|
||||||
|
Main export. Tests a path against the pattern using the options.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var isJS = minimatch(file, "*.js", { matchBase: true })
|
||||||
|
```
|
||||||
|
|
||||||
|
### minimatch.filter(pattern, options)
|
||||||
|
|
||||||
|
Returns a function that tests its
|
||||||
|
supplied argument, suitable for use with `Array.filter`. Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
|
||||||
|
```
|
||||||
|
|
||||||
|
### minimatch.match(list, pattern, options)
|
||||||
|
|
||||||
|
Match against the list of
|
||||||
|
files, in the style of fnmatch or glob. If nothing is matched, then
|
||||||
|
return the pattern (unless `{ null: true }` in the options.)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var javascripts = minimatch.match(fileList, "*.js", {matchBase: true}))
|
||||||
|
```
|
||||||
|
|
||||||
|
### minimatch.makeRe(pattern, options)
|
||||||
|
|
||||||
|
Make a regular expression object from the pattern.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
All options are `false` by default.
|
||||||
|
|
||||||
|
### debug
|
||||||
|
|
||||||
|
Dump a ton of stuff to stderr.
|
||||||
|
|
||||||
|
### nobrace
|
||||||
|
|
||||||
|
Do not expand `{a,b}` and `{1..3}` brace sets.
|
||||||
|
|
||||||
|
### noglobstar
|
||||||
|
|
||||||
|
Disable `**` matching against multiple folder names.
|
||||||
|
|
||||||
|
### dot
|
||||||
|
|
||||||
|
Allow patterns to match filenames starting with a period, even if
|
||||||
|
the pattern does not explicitly have a period in that spot.
|
||||||
|
|
||||||
|
Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
|
||||||
|
is set.
|
||||||
|
|
||||||
|
### noext
|
||||||
|
|
||||||
|
Disable "extglob" style patterns like `+(a|b)`.
|
||||||
|
|
||||||
|
### nocase
|
||||||
|
|
||||||
|
Perform a case-insensitive match.
|
||||||
|
|
||||||
|
### nonull
|
||||||
|
|
||||||
|
When a match is not found by `minimatch.match`, return a list containing
|
||||||
|
the pattern itself. When set, an empty list is returned if there are
|
||||||
|
no matches.
|
||||||
|
|
||||||
|
### matchBase
|
||||||
|
|
||||||
|
If set, then patterns without slashes will be matched
|
||||||
|
against the basename of the path if it contains slashes. For example,
|
||||||
|
`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
|
||||||
|
|
||||||
|
### nocomment
|
||||||
|
|
||||||
|
Suppress the behavior of treating `#` at the start of a pattern as a
|
||||||
|
comment.
|
||||||
|
|
||||||
|
### nonegate
|
||||||
|
|
||||||
|
Suppress the behavior of treating a leading `!` character as negation.
|
980
node_modules/glob/node_modules/minimatch/minimatch.js
generated
vendored
Normal file
980
node_modules/glob/node_modules/minimatch/minimatch.js
generated
vendored
Normal file
|
@ -0,0 +1,980 @@
|
||||||
|
module.exports = minimatch
|
||||||
|
minimatch.Minimatch = Minimatch
|
||||||
|
|
||||||
|
var LRU = require("lru-cache")
|
||||||
|
, cache = minimatch.cache = new LRU(100)
|
||||||
|
, GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
|
||||||
|
, pathSplit = process.platform === "win32" ? /\\|\// : "/"
|
||||||
|
|
||||||
|
var path = require("path")
|
||||||
|
// any single thing other than /
|
||||||
|
// don't need to escape / when using new RegExp()
|
||||||
|
, qmark = "[^/]"
|
||||||
|
|
||||||
|
// * => any number of characters
|
||||||
|
, star = qmark + "*?"
|
||||||
|
|
||||||
|
// ** when dots are allowed. Anything goes, except .. and .
|
||||||
|
// not (^ or / followed by one or two dots followed by $ or /),
|
||||||
|
// followed by anything, any number of times.
|
||||||
|
, twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?"
|
||||||
|
|
||||||
|
// not a ^ or / followed by a dot,
|
||||||
|
// followed by anything, any number of times.
|
||||||
|
, twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?"
|
||||||
|
|
||||||
|
// characters that need to be escaped in RegExp.
|
||||||
|
, reSpecials = charSet("().*{}+?[]^$\\!")
|
||||||
|
|
||||||
|
// "abc" -> { a:true, b:true, c:true }
|
||||||
|
function charSet (s) {
|
||||||
|
return s.split("").reduce(function (set, c) {
|
||||||
|
set[c] = true
|
||||||
|
return set
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizes slashes.
|
||||||
|
var slashSplit = /\/+/
|
||||||
|
|
||||||
|
minimatch.monkeyPatch = monkeyPatch
|
||||||
|
function monkeyPatch () {
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(String.prototype, "match")
|
||||||
|
var orig = desc.value
|
||||||
|
desc.value = function (p) {
|
||||||
|
if (p instanceof Minimatch) return p.match(this)
|
||||||
|
return orig.call(this, p)
|
||||||
|
}
|
||||||
|
Object.defineProperty(String.prototype, desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
minimatch.filter = filter
|
||||||
|
function filter (pattern, options) {
|
||||||
|
options = options || {}
|
||||||
|
return function (p, i, list) {
|
||||||
|
return minimatch(p, pattern, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function minimatch (p, pattern, options) {
|
||||||
|
if (typeof pattern !== "string") {
|
||||||
|
throw new TypeError("glob pattern string required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options) options = {}
|
||||||
|
|
||||||
|
// shortcut: comments match nothing.
|
||||||
|
if (!options.nocomment && pattern.charAt(0) === "#") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// "" only matches ""
|
||||||
|
if (pattern.trim() === "") return p === ""
|
||||||
|
|
||||||
|
return new Minimatch(pattern, options).match(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Minimatch (pattern, options) {
|
||||||
|
if (!(this instanceof Minimatch)) {
|
||||||
|
return new Minimatch(pattern, options, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof pattern !== "string") {
|
||||||
|
throw new TypeError("glob pattern string required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options) options = {}
|
||||||
|
pattern = pattern.trim()
|
||||||
|
|
||||||
|
// lru storage.
|
||||||
|
// these things aren't particularly big, but walking down the string
|
||||||
|
// and turning it into a regexp can get pretty costly.
|
||||||
|
var cacheKey = pattern + "\n" + Object.keys(options).filter(function (k) {
|
||||||
|
return options[k]
|
||||||
|
}).join(":")
|
||||||
|
var cached = minimatch.cache.get(cacheKey)
|
||||||
|
if (cached) return cached
|
||||||
|
minimatch.cache.set(cacheKey, this)
|
||||||
|
|
||||||
|
this.options = options
|
||||||
|
this.set = []
|
||||||
|
this.pattern = pattern
|
||||||
|
this.regexp = null
|
||||||
|
this.negate = false
|
||||||
|
this.comment = false
|
||||||
|
this.empty = false
|
||||||
|
|
||||||
|
// make the set of regexps etc.
|
||||||
|
this.make()
|
||||||
|
}
|
||||||
|
|
||||||
|
Minimatch.prototype.make = make
|
||||||
|
function make () {
|
||||||
|
// don't do it more than once.
|
||||||
|
if (this._made) return
|
||||||
|
|
||||||
|
var pattern = this.pattern
|
||||||
|
var options = this.options
|
||||||
|
|
||||||
|
// empty patterns and comments match nothing.
|
||||||
|
if (!options.nocomment && pattern.charAt(0) === "#") {
|
||||||
|
this.comment = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!pattern) {
|
||||||
|
this.empty = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 1: figure out negation, etc.
|
||||||
|
this.parseNegate()
|
||||||
|
|
||||||
|
// step 2: expand braces
|
||||||
|
var set = this.globSet = this.braceExpand()
|
||||||
|
|
||||||
|
if (options.debug) console.error(this.pattern, set)
|
||||||
|
|
||||||
|
// step 3: now we have a set, so turn each one into a series of path-portion
|
||||||
|
// matching patterns.
|
||||||
|
// These will be regexps, except in the case of "**", which is
|
||||||
|
// set to the GLOBSTAR object for globstar behavior,
|
||||||
|
// and will not contain any / characters
|
||||||
|
set = this.globParts = set.map(function (s) {
|
||||||
|
return s.split(slashSplit)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (options.debug) console.error(this.pattern, set)
|
||||||
|
|
||||||
|
// glob --> regexps
|
||||||
|
set = set.map(function (s, si, set) {
|
||||||
|
return s.map(this.parse, this)
|
||||||
|
}, this)
|
||||||
|
|
||||||
|
if (options.debug) console.error(this.pattern, set)
|
||||||
|
|
||||||
|
// filter out everything that didn't compile properly.
|
||||||
|
set = set.filter(function (s) {
|
||||||
|
return -1 === s.indexOf(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (options.debug) console.error(this.pattern, set)
|
||||||
|
|
||||||
|
this.set = set
|
||||||
|
}
|
||||||
|
|
||||||
|
Minimatch.prototype.parseNegate = parseNegate
|
||||||
|
function parseNegate () {
|
||||||
|
var pattern = this.pattern
|
||||||
|
, negate = false
|
||||||
|
, options = this.options
|
||||||
|
, negateOffset = 0
|
||||||
|
|
||||||
|
if (options.nonegate) return
|
||||||
|
|
||||||
|
for ( var i = 0, l = pattern.length
|
||||||
|
; i < l && pattern.charAt(i) === "!"
|
||||||
|
; i ++) {
|
||||||
|
negate = !negate
|
||||||
|
negateOffset ++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
||||||
|
this.negate = negate
|
||||||
|
}
|
||||||
|
|
||||||
|
// Brace expansion:
|
||||||
|
// a{b,c}d -> abd acd
|
||||||
|
// a{b,}c -> abc ac
|
||||||
|
// a{0..3}d -> a0d a1d a2d a3d
|
||||||
|
// a{b,c{d,e}f}g -> abg acdfg acefg
|
||||||
|
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
||||||
|
//
|
||||||
|
// Invalid sets are not expanded.
|
||||||
|
// a{2..}b -> a{2..}b
|
||||||
|
// a{b}c -> a{b}c
|
||||||
|
minimatch.braceExpand = function (pattern, options) {
|
||||||
|
return new Minimatch(pattern, options).braceExpand()
|
||||||
|
}
|
||||||
|
|
||||||
|
Minimatch.prototype.braceExpand = braceExpand
|
||||||
|
function braceExpand (pattern, options) {
|
||||||
|
options = options || this.options
|
||||||
|
pattern = typeof pattern === "undefined"
|
||||||
|
? this.pattern : pattern
|
||||||
|
|
||||||
|
if (typeof pattern === "undefined") {
|
||||||
|
throw new Error("undefined pattern")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.nobrace ||
|
||||||
|
!pattern.match(/\{.*\}/)) {
|
||||||
|
// shortcut. no need to expand.
|
||||||
|
return [pattern]
|
||||||
|
}
|
||||||
|
|
||||||
|
var escaping = false
|
||||||
|
|
||||||
|
// examples and comments refer to this crazy pattern:
|
||||||
|
// a{b,c{d,e},{f,g}h}x{y,z}
|
||||||
|
// expected:
|
||||||
|
// abxy
|
||||||
|
// abxz
|
||||||
|
// acdxy
|
||||||
|
// acdxz
|
||||||
|
// acexy
|
||||||
|
// acexz
|
||||||
|
// afhxy
|
||||||
|
// afhxz
|
||||||
|
// aghxy
|
||||||
|
// aghxz
|
||||||
|
|
||||||
|
// everything before the first \{ is just a prefix.
|
||||||
|
// So, we pluck that off, and work with the rest,
|
||||||
|
// and then prepend it to everything we find.
|
||||||
|
if (pattern.charAt(0) !== "{") {
|
||||||
|
// console.error(pattern)
|
||||||
|
var prefix = null
|
||||||
|
for (var i = 0, l = pattern.length; i < l; i ++) {
|
||||||
|
var c = pattern.charAt(i)
|
||||||
|
// console.error(i, c)
|
||||||
|
if (c === "\\") {
|
||||||
|
escaping = !escaping
|
||||||
|
} else if (c === "{" && !escaping) {
|
||||||
|
prefix = pattern.substr(0, i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// actually no sets, all { were escaped.
|
||||||
|
if (prefix === null) {
|
||||||
|
// console.error("no sets")
|
||||||
|
return [pattern]
|
||||||
|
}
|
||||||
|
|
||||||
|
var tail = braceExpand(pattern.substr(i), options)
|
||||||
|
return tail.map(function (t) {
|
||||||
|
return prefix + t
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we have something like:
|
||||||
|
// {b,c{d,e},{f,g}h}x{y,z}
|
||||||
|
// walk through the set, expanding each part, until
|
||||||
|
// the set ends. then, we'll expand the suffix.
|
||||||
|
// If the set only has a single member, then'll put the {} back
|
||||||
|
|
||||||
|
// first, handle numeric sets, since they're easier
|
||||||
|
var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/)
|
||||||
|
if (numset) {
|
||||||
|
// console.error("numset", numset[1], numset[2])
|
||||||
|
var suf = braceExpand(pattern.substr(numset[0].length), options)
|
||||||
|
, start = +numset[1]
|
||||||
|
, end = +numset[2]
|
||||||
|
, inc = start > end ? -1 : 1
|
||||||
|
, set = []
|
||||||
|
for (var i = start; i != (end + inc); i += inc) {
|
||||||
|
// append all the suffixes
|
||||||
|
for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
|
||||||
|
set.push(i + suf[ii])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok, walk through the set
|
||||||
|
// We hope, somewhat optimistically, that there
|
||||||
|
// will be a } at the end.
|
||||||
|
// If the closing brace isn't found, then the pattern is
|
||||||
|
// interpreted as braceExpand("\\" + pattern) so that
|
||||||
|
// the leading \{ will be interpreted literally.
|
||||||
|
var i = 1 // skip the \{
|
||||||
|
, depth = 1
|
||||||
|
, set = []
|
||||||
|
, member = ""
|
||||||
|
, sawEnd = false
|
||||||
|
, escaping = false
|
||||||
|
|
||||||
|
function addMember () {
|
||||||
|
set.push(member)
|
||||||
|
member = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.error("Entering for")
|
||||||
|
FOR: for (i = 1, l = pattern.length; i < l; i ++) {
|
||||||
|
var c = pattern.charAt(i)
|
||||||
|
// console.error("", i, c)
|
||||||
|
|
||||||
|
if (escaping) {
|
||||||
|
escaping = false
|
||||||
|
member += "\\" + c
|
||||||
|
} else {
|
||||||
|
switch (c) {
|
||||||
|
case "\\":
|
||||||
|
escaping = true
|
||||||
|
continue
|
||||||
|
|
||||||
|
case "{":
|
||||||
|
depth ++
|
||||||
|
member += "{"
|
||||||
|
continue
|
||||||
|
|
||||||
|
case "}":
|
||||||
|
depth --
|
||||||
|
// if this closes the actual set, then we're done
|
||||||
|
if (depth === 0) {
|
||||||
|
addMember()
|
||||||
|
// pluck off the close-brace
|
||||||
|
i ++
|
||||||
|
break FOR
|
||||||
|
} else {
|
||||||
|
member += c
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
case ",":
|
||||||
|
if (depth === 1) {
|
||||||
|
addMember()
|
||||||
|
} else {
|
||||||
|
member += c
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
|
default:
|
||||||
|
member += c
|
||||||
|
continue
|
||||||
|
} // switch
|
||||||
|
} // else
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// now we've either finished the set, and the suffix is
|
||||||
|
// pattern.substr(i), or we have *not* closed the set,
|
||||||
|
// and need to escape the leading brace
|
||||||
|
if (depth !== 0) {
|
||||||
|
// console.error("didn't close", pattern)
|
||||||
|
return braceExpand("\\" + pattern, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// x{y,z} -> ["xy", "xz"]
|
||||||
|
// console.error("set", set)
|
||||||
|
// console.error("suffix", pattern.substr(i))
|
||||||
|
var suf = braceExpand(pattern.substr(i), options)
|
||||||
|
// ["b", "c{d,e}","{f,g}h"] ->
|
||||||
|
// [["b"], ["cd", "ce"], ["fh", "gh"]]
|
||||||
|
var addBraces = set.length === 1
|
||||||
|
// console.error("set pre-expanded", set)
|
||||||
|
set = set.map(function (p) {
|
||||||
|
return braceExpand(p, options)
|
||||||
|
})
|
||||||
|
// console.error("set expanded", set)
|
||||||
|
|
||||||
|
|
||||||
|
// [["b"], ["cd", "ce"], ["fh", "gh"]] ->
|
||||||
|
// ["b", "cd", "ce", "fh", "gh"]
|
||||||
|
set = set.reduce(function (l, r) {
|
||||||
|
return l.concat(r)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (addBraces) {
|
||||||
|
set = set.map(function (s) {
|
||||||
|
return "{" + s + "}"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// now attach the suffixes.
|
||||||
|
var ret = []
|
||||||
|
for (var i = 0, l = set.length; i < l; i ++) {
|
||||||
|
for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
|
||||||
|
ret.push(set[i] + suf[ii])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse a component of the expanded set.
|
||||||
|
// At this point, no pattern may contain "/" in it
|
||||||
|
// so we're going to return a 2d array, where each entry is the full
|
||||||
|
// pattern, split on '/', and then turned into a regular expression.
|
||||||
|
// A regexp is made at the end which joins each array with an
|
||||||
|
// escaped /, and another full one which joins each regexp with |.
|
||||||
|
//
|
||||||
|
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
||||||
|
// when it is the *only* thing in a path portion. Otherwise, any series
|
||||||
|
// of * is equivalent to a single *. Globstar behavior is enabled by
|
||||||
|
// default, and can be disabled by setting options.noglobstar.
|
||||||
|
Minimatch.prototype.parse = parse
|
||||||
|
var SUBPARSE = {}
|
||||||
|
function parse (pattern, isSub) {
|
||||||
|
var options = this.options
|
||||||
|
|
||||||
|
// shortcuts
|
||||||
|
if (!options.noglobstar && pattern === "**") return GLOBSTAR
|
||||||
|
if (pattern === "") return ""
|
||||||
|
|
||||||
|
var re = ""
|
||||||
|
, hasMagic = false
|
||||||
|
, escaping = false
|
||||||
|
// ? => one single character
|
||||||
|
, patternListStack = []
|
||||||
|
, plType
|
||||||
|
, stateChar
|
||||||
|
, inClass = false
|
||||||
|
, reClassStart = -1
|
||||||
|
, classStart = -1
|
||||||
|
// . and .. never match anything that doesn't start with .,
|
||||||
|
// even when options.dot is set.
|
||||||
|
, patternStart = pattern.charAt(0) === "." ? "" // anything
|
||||||
|
// not (start or / followed by . or .. followed by / or end)
|
||||||
|
: options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))"
|
||||||
|
: "(?!\\.)"
|
||||||
|
|
||||||
|
function clearStateChar () {
|
||||||
|
if (stateChar) {
|
||||||
|
// we had some state-tracking character
|
||||||
|
// that wasn't consumed by this pass.
|
||||||
|
switch (stateChar) {
|
||||||
|
case "*":
|
||||||
|
re += star
|
||||||
|
hasMagic = true
|
||||||
|
break
|
||||||
|
case "?":
|
||||||
|
re += qmark
|
||||||
|
hasMagic = true
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
re += "\\"+stateChar
|
||||||
|
break
|
||||||
|
}
|
||||||
|
stateChar = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( var i = 0, len = pattern.length, c
|
||||||
|
; (i < len) && (c = pattern.charAt(i))
|
||||||
|
; i ++ ) {
|
||||||
|
|
||||||
|
if (options.debug) {
|
||||||
|
console.error("%s\t%s %s %j", pattern, i, re, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip over any that are escaped.
|
||||||
|
if (escaping && reSpecials[c]) {
|
||||||
|
re += "\\" + c
|
||||||
|
escaping = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH: switch (c) {
|
||||||
|
case "/":
|
||||||
|
// completely not allowed, even escaped.
|
||||||
|
// Should already be path-split by now.
|
||||||
|
return false
|
||||||
|
|
||||||
|
case "\\":
|
||||||
|
clearStateChar()
|
||||||
|
escaping = true
|
||||||
|
continue
|
||||||
|
|
||||||
|
// the various stateChar values
|
||||||
|
// for the "extglob" stuff.
|
||||||
|
case "?":
|
||||||
|
case "*":
|
||||||
|
case "+":
|
||||||
|
case "@":
|
||||||
|
case "!":
|
||||||
|
if (options.debug) {
|
||||||
|
console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// all of those are literals inside a class, except that
|
||||||
|
// the glob [!a] means [^a] in regexp
|
||||||
|
if (inClass) {
|
||||||
|
if (c === "!" && i === classStart + 1) c = "^"
|
||||||
|
re += c
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we already have a stateChar, then it means
|
||||||
|
// that there was something like ** or +? in there.
|
||||||
|
// Handle the stateChar, then proceed with this one.
|
||||||
|
clearStateChar()
|
||||||
|
stateChar = c
|
||||||
|
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
||||||
|
// just clear the statechar *now*, rather than even diving into
|
||||||
|
// the patternList stuff.
|
||||||
|
if (options.noext) clearStateChar()
|
||||||
|
continue
|
||||||
|
|
||||||
|
case "(":
|
||||||
|
if (inClass) {
|
||||||
|
re += "("
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stateChar) {
|
||||||
|
re += "\\("
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plType = stateChar
|
||||||
|
patternListStack.push({ type: plType
|
||||||
|
, start: i - 1
|
||||||
|
, reStart: re.length })
|
||||||
|
re += stateChar === "!" ? "(?!" : "(?:"
|
||||||
|
stateChar = false
|
||||||
|
continue
|
||||||
|
|
||||||
|
case ")":
|
||||||
|
if (inClass || !patternListStack.length) {
|
||||||
|
re += "\\)"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMagic = true
|
||||||
|
re += ")"
|
||||||
|
plType = patternListStack.pop().type
|
||||||
|
switch (plType) {
|
||||||
|
case "?":
|
||||||
|
case "+":
|
||||||
|
case "*": re += plType
|
||||||
|
case "!": // already handled by the start
|
||||||
|
case "@": break // the default anyway
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
|
case "|":
|
||||||
|
if (inClass || !patternListStack.length || escaping) {
|
||||||
|
re += "\\|"
|
||||||
|
escaping = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
re += "|"
|
||||||
|
continue
|
||||||
|
|
||||||
|
// these are mostly the same in regexp and glob
|
||||||
|
case "[":
|
||||||
|
// swallow any state-tracking char before the [
|
||||||
|
clearStateChar()
|
||||||
|
|
||||||
|
if (inClass) {
|
||||||
|
re += "\\" + c
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
inClass = true
|
||||||
|
classStart = i
|
||||||
|
reClassStart = re.length
|
||||||
|
re += c
|
||||||
|
continue
|
||||||
|
|
||||||
|
case "]":
|
||||||
|
// a right bracket shall lose its special
|
||||||
|
// meaning and represent itself in
|
||||||
|
// a bracket expression if it occurs
|
||||||
|
// first in the list. -- POSIX.2 2.8.3.2
|
||||||
|
if (i === classStart + 1 || !inClass) {
|
||||||
|
re += "\\" + c
|
||||||
|
escaping = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish up the class.
|
||||||
|
hasMagic = true
|
||||||
|
inClass = false
|
||||||
|
re += c
|
||||||
|
continue
|
||||||
|
|
||||||
|
default:
|
||||||
|
// swallow any state char that wasn't consumed
|
||||||
|
clearStateChar()
|
||||||
|
|
||||||
|
if (escaping) {
|
||||||
|
// no need
|
||||||
|
escaping = false
|
||||||
|
} else if (reSpecials[c]
|
||||||
|
&& !(c === "^" && inClass)) {
|
||||||
|
re += "\\"
|
||||||
|
}
|
||||||
|
|
||||||
|
re += c
|
||||||
|
|
||||||
|
} // switch
|
||||||
|
} // for
|
||||||
|
|
||||||
|
|
||||||
|
// handle the case where we left a class open.
|
||||||
|
// "[abc" is valid, equivalent to "\[abc"
|
||||||
|
if (inClass) {
|
||||||
|
// split where the last [ was, and escape it
|
||||||
|
// this is a huge pita. We now have to re-walk
|
||||||
|
// the contents of the would-be class to re-translate
|
||||||
|
// any characters that were passed through as-is
|
||||||
|
var cs = pattern.substr(classStart + 1)
|
||||||
|
, sp = this.parse(cs, SUBPARSE)
|
||||||
|
re = re.substr(0, reClassStart) + "\\[" + sp[0]
|
||||||
|
hasMagic = hasMagic || sp[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle the case where we had a +( thing at the *end*
|
||||||
|
// of the pattern.
|
||||||
|
// each pattern list stack adds 3 chars, and we need to go through
|
||||||
|
// and escape any | chars that were passed through as-is for the regexp.
|
||||||
|
// Go through and escape them, taking care not to double-escape any
|
||||||
|
// | chars that were already escaped.
|
||||||
|
var pl
|
||||||
|
while (pl = patternListStack.pop()) {
|
||||||
|
var tail = re.slice(pl.reStart + 3)
|
||||||
|
// maybe some even number of \, then maybe 1 \, followed by a |
|
||||||
|
tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
|
||||||
|
if (!$2) {
|
||||||
|
// the | isn't already escaped, so escape it.
|
||||||
|
$2 = "\\"
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to escape all those slashes *again*, without escaping the
|
||||||
|
// one that we need for escaping the | character. As it works out,
|
||||||
|
// escaping an even number of slashes can be done by simply repeating
|
||||||
|
// it exactly after itself. That's why this trick works.
|
||||||
|
//
|
||||||
|
// I am sorry that you have to see this.
|
||||||
|
return $1 + $1 + $2 + "|"
|
||||||
|
})
|
||||||
|
|
||||||
|
// console.error("tail=%j\n %s", tail, tail)
|
||||||
|
var t = pl.type === "*" ? star
|
||||||
|
: pl.type === "?" ? qmark
|
||||||
|
: "\\" + pl.type
|
||||||
|
|
||||||
|
hasMagic = true
|
||||||
|
re = re.slice(0, pl.reStart)
|
||||||
|
+ t + "\\("
|
||||||
|
+ tail
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle trailing things that only matter at the very end.
|
||||||
|
clearStateChar()
|
||||||
|
if (escaping) {
|
||||||
|
// trailing \\
|
||||||
|
re += "\\\\"
|
||||||
|
}
|
||||||
|
|
||||||
|
// only need to apply the nodot start if the re starts with
|
||||||
|
// something that could conceivably capture a dot
|
||||||
|
var addPatternStart = false
|
||||||
|
switch (re.charAt(0)) {
|
||||||
|
case ".":
|
||||||
|
case "[":
|
||||||
|
case "(": addPatternStart = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the re is not "" at this point, then we need to make sure
|
||||||
|
// it doesn't match against an empty path part.
|
||||||
|
// Otherwise a/* will match a/, which it should not.
|
||||||
|
if (re !== "" && hasMagic) re = "(?=.)" + re
|
||||||
|
|
||||||
|
if (addPatternStart) re = patternStart + re
|
||||||
|
|
||||||
|
// parsing just a piece of a larger pattern.
|
||||||
|
if (isSub === SUBPARSE) {
|
||||||
|
return [ re, hasMagic ]
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip the regexp for non-magical patterns
|
||||||
|
// unescape anything in it, though, so that it'll be
|
||||||
|
// an exact match against a file etc.
|
||||||
|
if (!hasMagic) {
|
||||||
|
return globUnescape(pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags = options.nocase ? "i" : ""
|
||||||
|
, regExp = new RegExp("^" + re + "$", flags)
|
||||||
|
|
||||||
|
regExp._glob = pattern
|
||||||
|
regExp._src = re
|
||||||
|
|
||||||
|
return regExp
|
||||||
|
}
|
||||||
|
|
||||||
|
minimatch.makeRe = function (pattern, options) {
|
||||||
|
return new Minimatch(pattern, options || {}).makeRe()
|
||||||
|
}
|
||||||
|
|
||||||
|
Minimatch.prototype.makeRe = makeRe
|
||||||
|
function makeRe () {
|
||||||
|
if (this.regexp || this.regexp === false) return this.regexp
|
||||||
|
|
||||||
|
// at this point, this.set is a 2d array of partial
|
||||||
|
// pattern strings, or "**".
|
||||||
|
//
|
||||||
|
// It's better to use .match(). This function shouldn't
|
||||||
|
// be used, really, but it's pretty convenient sometimes,
|
||||||
|
// when you just want to work with a regex.
|
||||||
|
var set = this.set
|
||||||
|
|
||||||
|
if (!set.length) return this.regexp = false
|
||||||
|
var options = this.options
|
||||||
|
|
||||||
|
var twoStar = options.noglobstar ? star
|
||||||
|
: options.dot ? twoStarDot
|
||||||
|
: twoStarNoDot
|
||||||
|
, flags = options.nocase ? "i" : ""
|
||||||
|
|
||||||
|
var re = set.map(function (pattern) {
|
||||||
|
return pattern.map(function (p) {
|
||||||
|
return (p === GLOBSTAR) ? twoStar
|
||||||
|
: (typeof p === "string") ? regExpEscape(p)
|
||||||
|
: p._src
|
||||||
|
}).join("\\\/")
|
||||||
|
}).join("|")
|
||||||
|
|
||||||
|
// must match entire pattern
|
||||||
|
// ending in a * or ** will make it less strict.
|
||||||
|
re = "^" + re + "$"
|
||||||
|
|
||||||
|
// can match anything, as long as it's not this.
|
||||||
|
if (this.negate) re = "^(?!" + re + ").*$"
|
||||||
|
|
||||||
|
try {
|
||||||
|
return this.regexp = new RegExp(re, flags)
|
||||||
|
} catch (ex) {
|
||||||
|
return this.regexp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minimatch.match = function (list, pattern, options) {
|
||||||
|
var mm = new Minimatch(pattern, options)
|
||||||
|
list = list.filter(function (f) {
|
||||||
|
return mm.match(f)
|
||||||
|
})
|
||||||
|
if (options.nonull && !list.length) {
|
||||||
|
list.push(pattern)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
Minimatch.prototype.match = match
|
||||||
|
function match (f, partial) {
|
||||||
|
// console.error("match", f, this.pattern)
|
||||||
|
// short-circuit in the case of busted things.
|
||||||
|
// comments, etc.
|
||||||
|
if (this.comment) return false
|
||||||
|
if (this.empty) return f === ""
|
||||||
|
|
||||||
|
if (f === "/" && partial) return true
|
||||||
|
|
||||||
|
var options = this.options
|
||||||
|
|
||||||
|
// first, normalize any slash-separated path parts.
|
||||||
|
// f = path.normalize(f)
|
||||||
|
|
||||||
|
// windows: need to use /, not \
|
||||||
|
// On other platforms, \ is a valid (albeit bad) filename char.
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
f = f.split("\\").join("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
// treat the test path as a set of pathparts.
|
||||||
|
f = f.split(slashSplit)
|
||||||
|
if (options.debug) {
|
||||||
|
console.error(this.pattern, "split", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// just ONE of the pattern sets in this.set needs to match
|
||||||
|
// in order for it to be valid. If negating, then just one
|
||||||
|
// match means that we have failed.
|
||||||
|
// Either way, return on the first hit.
|
||||||
|
|
||||||
|
var set = this.set
|
||||||
|
// console.error(this.pattern, "set", set)
|
||||||
|
|
||||||
|
for (var i = 0, l = set.length; i < l; i ++) {
|
||||||
|
var pattern = set[i]
|
||||||
|
var hit = this.matchOne(f, pattern, partial)
|
||||||
|
if (hit) {
|
||||||
|
return !this.negate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// didn't get any hits. this is success if it's a negative
|
||||||
|
// pattern, failure otherwise.
|
||||||
|
return this.negate
|
||||||
|
}
|
||||||
|
|
||||||
|
// set partial to true to test if, for example,
|
||||||
|
// "/a/b" matches the start of "/*/b/*/d"
|
||||||
|
// Partial means, if you run out of file before you run
|
||||||
|
// out of pattern, then that's fine, as long as all
|
||||||
|
// the parts match.
|
||||||
|
Minimatch.prototype.matchOne = function (file, pattern, partial) {
|
||||||
|
var options = this.options
|
||||||
|
|
||||||
|
if (options.debug) {
|
||||||
|
console.error("matchOne",
|
||||||
|
{ "this": this
|
||||||
|
, file: file
|
||||||
|
, pattern: pattern })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.matchBase && pattern.length === 1) {
|
||||||
|
file = path.basename(file.join("/")).split("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.debug) {
|
||||||
|
console.error("matchOne", file.length, pattern.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( var fi = 0
|
||||||
|
, pi = 0
|
||||||
|
, fl = file.length
|
||||||
|
, pl = pattern.length
|
||||||
|
; (fi < fl) && (pi < pl)
|
||||||
|
; fi ++, pi ++ ) {
|
||||||
|
|
||||||
|
if (options.debug) {
|
||||||
|
console.error("matchOne loop")
|
||||||
|
}
|
||||||
|
var p = pattern[pi]
|
||||||
|
, f = file[fi]
|
||||||
|
|
||||||
|
if (options.debug) {
|
||||||
|
console.error(pattern, p, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be impossible.
|
||||||
|
// some invalid regexp stuff in the set.
|
||||||
|
if (p === false) return false
|
||||||
|
|
||||||
|
if (p === GLOBSTAR) {
|
||||||
|
// "**"
|
||||||
|
// a/**/b/**/c would match the following:
|
||||||
|
// a/b/x/y/z/c
|
||||||
|
// a/x/y/z/b/c
|
||||||
|
// a/b/x/b/x/c
|
||||||
|
// a/b/c
|
||||||
|
// To do this, take the rest of the pattern after
|
||||||
|
// the **, and see if it would match the file remainder.
|
||||||
|
// If so, return success.
|
||||||
|
// If not, the ** "swallows" a segment, and try again.
|
||||||
|
// This is recursively awful.
|
||||||
|
// a/b/x/y/z/c
|
||||||
|
// - a matches a
|
||||||
|
// - doublestar
|
||||||
|
// - matchOne(b/x/y/z/c, b/**/c)
|
||||||
|
// - b matches b
|
||||||
|
// - doublestar
|
||||||
|
// - matchOne(x/y/z/c, c) -> no
|
||||||
|
// - matchOne(y/z/c, c) -> no
|
||||||
|
// - matchOne(z/c, c) -> no
|
||||||
|
// - matchOne(c, c) yes, hit
|
||||||
|
var fr = fi
|
||||||
|
, pr = pi + 1
|
||||||
|
if (pr === pl) {
|
||||||
|
// a ** at the end will just swallow the rest.
|
||||||
|
// We have found a match.
|
||||||
|
// however, it will not swallow /.x, unless
|
||||||
|
// options.dot is set.
|
||||||
|
// . and .. are *never* matched by **, for explosively
|
||||||
|
// exponential reasons.
|
||||||
|
for ( ; fi < fl; fi ++) {
|
||||||
|
if (file[fi] === "." || file[fi] === ".." ||
|
||||||
|
(!options.dot && file[fi].charAt(0) === ".")) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok, let's see if we can swallow whatever we can.
|
||||||
|
WHILE: while (fr < fl) {
|
||||||
|
var swallowee = file[fr]
|
||||||
|
if (swallowee === "." || swallowee === ".." ||
|
||||||
|
(!options.dot && swallowee.charAt(0) === ".")) {
|
||||||
|
// console.error("dot detected!")
|
||||||
|
break WHILE
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX remove this slice. Just pass the start index.
|
||||||
|
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
||||||
|
// found a match.
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
// ** swallows a segment, and continue.
|
||||||
|
fr ++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no match was found.
|
||||||
|
// However, in partial mode, we can't say this is necessarily over.
|
||||||
|
// If there's more *pattern* left, then
|
||||||
|
if (partial) {
|
||||||
|
// ran out of file
|
||||||
|
// console.error("\n>>> no match, partial?", file, fr, pattern, pr)
|
||||||
|
if (fr === fl) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// something other than **
|
||||||
|
// non-magic patterns just have to match exactly
|
||||||
|
// patterns with magic have been turned into regexps.
|
||||||
|
var hit
|
||||||
|
if (typeof p === "string") {
|
||||||
|
if (options.nocase) {
|
||||||
|
hit = f.toLowerCase() === p.toLowerCase()
|
||||||
|
} else {
|
||||||
|
hit = f === p
|
||||||
|
}
|
||||||
|
if (options.debug) {
|
||||||
|
console.error("string match", p, f, hit)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hit = f.match(p)
|
||||||
|
if (options.debug) {
|
||||||
|
console.error("pattern match", p, f, hit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hit) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: ending in / means that we'll get a final ""
|
||||||
|
// at the end of the pattern. This can only match a
|
||||||
|
// corresponding "" at the end of the file.
|
||||||
|
// If the file ends in /, then it can only match a
|
||||||
|
// a pattern that ends in /, unless the pattern just
|
||||||
|
// doesn't have any more for it. But, a/b/ should *not*
|
||||||
|
// match "a/b/*", even though "" matches against the
|
||||||
|
// [^/]*? pattern, except in partial mode, where it might
|
||||||
|
// simply not be reached yet.
|
||||||
|
// However, a/b/ should still satisfy a/*
|
||||||
|
|
||||||
|
// now either we fell off the end of the pattern, or we're done.
|
||||||
|
if (fi === fl && pi === pl) {
|
||||||
|
// ran out of pattern and filename at the same time.
|
||||||
|
// an exact hit!
|
||||||
|
return true
|
||||||
|
} else if (fi === fl) {
|
||||||
|
// ran out of file, but still had pattern left.
|
||||||
|
// this is ok if we're doing the match as part of
|
||||||
|
// a glob fs traversal.
|
||||||
|
return partial
|
||||||
|
} else if (pi === pl) {
|
||||||
|
// ran out of pattern, still have file left.
|
||||||
|
// this is only acceptable if we're on the very last
|
||||||
|
// empty segment of a file with a trailing slash.
|
||||||
|
// a/* should match a/b/
|
||||||
|
var emptyFileEnd = (fi === fl - 1) && (file[fi] === "")
|
||||||
|
return emptyFileEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be unreachable.
|
||||||
|
throw new Error("wtf?")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// replace stuff like \* with *
|
||||||
|
function globUnescape (s) {
|
||||||
|
return s.replace(/\\(.)/g, "$1")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function regExpEscape (s) {
|
||||||
|
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
|
||||||
|
}
|
1
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/.npmignore
generated
vendored
Normal file
1
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/.npmignore
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/node_modules
|
23
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/LICENSE
generated
vendored
Normal file
23
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
12
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/README.md
generated
vendored
Normal file
12
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/README.md
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# lru cache
|
||||||
|
|
||||||
|
A cache object that deletes the least-recently-used items.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
var LRU = require("lru-cache")
|
||||||
|
, cache = LRU(10) // max 10 items. default = Infinity
|
||||||
|
cache.set("key", "value")
|
||||||
|
cache.get("key") // "value"
|
||||||
|
|
||||||
|
RTFS for more info.
|
100
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js
generated
vendored
Normal file
100
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js
generated
vendored
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
;(function () { // closure for web browsers
|
||||||
|
|
||||||
|
if (module) {
|
||||||
|
module.exports = LRUCache
|
||||||
|
} else {
|
||||||
|
// just set the global for non-node platforms.
|
||||||
|
;(function () { return this })().LRUCache = LRUCache
|
||||||
|
}
|
||||||
|
|
||||||
|
function hOP (obj, key) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(obj, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
function LRUCache (maxLength) {
|
||||||
|
if (!(this instanceof LRUCache)) {
|
||||||
|
return new LRUCache(maxLength)
|
||||||
|
}
|
||||||
|
var cache = {} // hash of items by key
|
||||||
|
, lruList = {} // list of items in order of use recency
|
||||||
|
, lru = 0 // least recently used
|
||||||
|
, mru = 0 // most recently used
|
||||||
|
, length = 0 // number of items in the list
|
||||||
|
|
||||||
|
// resize the cache when the maxLength changes.
|
||||||
|
Object.defineProperty(this, "maxLength",
|
||||||
|
{ set : function (mL) {
|
||||||
|
if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity
|
||||||
|
maxLength = mL
|
||||||
|
// if it gets above double maxLength, trim right away.
|
||||||
|
// otherwise, do it whenever it's convenient.
|
||||||
|
if (length > maxLength) trim()
|
||||||
|
}
|
||||||
|
, get : function () { return maxLength }
|
||||||
|
, enumerable : true
|
||||||
|
})
|
||||||
|
|
||||||
|
this.maxLength = maxLength
|
||||||
|
|
||||||
|
Object.defineProperty(this, "length",
|
||||||
|
{ get : function () { return length }
|
||||||
|
, enumerable : true
|
||||||
|
})
|
||||||
|
|
||||||
|
this.reset = function () {
|
||||||
|
cache = {}
|
||||||
|
lruList = {}
|
||||||
|
lru = 0
|
||||||
|
mru = 0
|
||||||
|
length = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set = function (key, value) {
|
||||||
|
if (hOP(cache, key)) {
|
||||||
|
this.get(key)
|
||||||
|
cache[key].value = value
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
var hit = {key:key, value:value, lu:mru++}
|
||||||
|
lruList[hit.lu] = cache[key] = hit
|
||||||
|
length ++
|
||||||
|
if (length > maxLength) trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get = function (key) {
|
||||||
|
if (!hOP(cache, key)) return undefined
|
||||||
|
var hit = cache[key]
|
||||||
|
delete lruList[hit.lu]
|
||||||
|
if (hit.lu === lru) lruWalk()
|
||||||
|
hit.lu = mru ++
|
||||||
|
lruList[hit.lu] = hit
|
||||||
|
return hit.value
|
||||||
|
}
|
||||||
|
|
||||||
|
this.del = function (key) {
|
||||||
|
if (!hOP(cache, key)) return undefined
|
||||||
|
var hit = cache[key]
|
||||||
|
delete cache[key]
|
||||||
|
delete lruList[hit.lu]
|
||||||
|
if (hit.lu === lru) lruWalk()
|
||||||
|
length --
|
||||||
|
}
|
||||||
|
|
||||||
|
function lruWalk () {
|
||||||
|
// lru has been deleted, hop up to the next hit.
|
||||||
|
lru = Object.keys(lruList).shift()
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim () {
|
||||||
|
if (length <= maxLength) return undefined
|
||||||
|
var prune = Object.keys(lruList).slice(0, length - maxLength)
|
||||||
|
for (var i = 0, l = (length - maxLength); i < l; i ++) {
|
||||||
|
delete cache[ lruList[prune[i]].key ]
|
||||||
|
delete lruList[prune[i]]
|
||||||
|
}
|
||||||
|
length = maxLength
|
||||||
|
lruWalk()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})()
|
13
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/package.json
generated
vendored
Normal file
13
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/package.json
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{ "name": "lru-cache"
|
||||||
|
, "description": "A cache object that deletes the least-recently-used items."
|
||||||
|
, "version": "1.0.5"
|
||||||
|
, "author": "Isaac Z. Schlueter <i@izs.me>"
|
||||||
|
, "scripts": { "test": "tap test" }
|
||||||
|
, "main": "lib/lru-cache.js"
|
||||||
|
, "repository": "git://github.com/isaacs/node-lru-cache.git"
|
||||||
|
, "devDependencies": { "tap": "0.1" }
|
||||||
|
, "license":
|
||||||
|
{ "type": "MIT"
|
||||||
|
, "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE"
|
||||||
|
}
|
||||||
|
}
|
93
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/test/basic.js
generated
vendored
Normal file
93
node_modules/glob/node_modules/minimatch/node_modules/lru-cache/test/basic.js
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
var test = require('tap').test
|
||||||
|
, LRU = require('../')
|
||||||
|
|
||||||
|
test('basic', function (t) {
|
||||||
|
var cache = new LRU(10)
|
||||||
|
cache.set("key", "value")
|
||||||
|
t.equal(cache.get("key"), "value")
|
||||||
|
t.equal(cache.get("nada"), undefined)
|
||||||
|
t.equal(cache.length, 1)
|
||||||
|
t.equal(cache.maxLength, 10)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('least recently set', function (t) {
|
||||||
|
var cache = new LRU(2)
|
||||||
|
cache.set("a", "A")
|
||||||
|
cache.set("b", "B")
|
||||||
|
cache.set("c", "C")
|
||||||
|
t.equal(cache.get("c"), "C")
|
||||||
|
t.equal(cache.get("b"), "B")
|
||||||
|
t.equal(cache.get("a"), undefined)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('lru recently gotten', function (t) {
|
||||||
|
var cache = new LRU(2)
|
||||||
|
cache.set("a", "A")
|
||||||
|
cache.set("b", "B")
|
||||||
|
cache.get("a")
|
||||||
|
cache.set("c", "C")
|
||||||
|
t.equal(cache.get("c"), "C")
|
||||||
|
t.equal(cache.get("b"), undefined)
|
||||||
|
t.equal(cache.get("a"), "A")
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('del', function (t) {
|
||||||
|
var cache = new LRU(2)
|
||||||
|
cache.set("a", "A")
|
||||||
|
cache.del("a")
|
||||||
|
t.equal(cache.get("a"), undefined)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('maxLength', function (t) {
|
||||||
|
var cache = new LRU(3)
|
||||||
|
|
||||||
|
// test changing the maxLength, verify that the LRU items get dropped.
|
||||||
|
cache.maxLength = 100
|
||||||
|
for (var i = 0; i < 100; i ++) cache.set(i, i)
|
||||||
|
t.equal(cache.length, 100)
|
||||||
|
for (var i = 0; i < 100; i ++) {
|
||||||
|
t.equal(cache.get(i), i)
|
||||||
|
}
|
||||||
|
cache.maxLength = 3
|
||||||
|
t.equal(cache.length, 3)
|
||||||
|
for (var i = 0; i < 97; i ++) {
|
||||||
|
t.equal(cache.get(i), undefined)
|
||||||
|
}
|
||||||
|
for (var i = 98; i < 100; i ++) {
|
||||||
|
t.equal(cache.get(i), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now remove the maxLength restriction, and try again.
|
||||||
|
cache.maxLength = "hello"
|
||||||
|
for (var i = 0; i < 100; i ++) cache.set(i, i)
|
||||||
|
t.equal(cache.length, 100)
|
||||||
|
for (var i = 0; i < 100; i ++) {
|
||||||
|
t.equal(cache.get(i), i)
|
||||||
|
}
|
||||||
|
// should trigger an immediate resize
|
||||||
|
cache.maxLength = 3
|
||||||
|
t.equal(cache.length, 3)
|
||||||
|
for (var i = 0; i < 97; i ++) {
|
||||||
|
t.equal(cache.get(i), undefined)
|
||||||
|
}
|
||||||
|
for (var i = 98; i < 100; i ++) {
|
||||||
|
t.equal(cache.get(i), i)
|
||||||
|
}
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('reset', function (t) {
|
||||||
|
var cache = new LRU(10)
|
||||||
|
cache.set("a", "A")
|
||||||
|
cache.set("b", "B")
|
||||||
|
cache.reset()
|
||||||
|
t.equal(cache.length, 0)
|
||||||
|
t.equal(cache.maxLength, 10)
|
||||||
|
t.equal(cache.get("a"), undefined)
|
||||||
|
t.equal(cache.get("b"), undefined)
|
||||||
|
t.end()
|
||||||
|
})
|
29
node_modules/glob/node_modules/minimatch/package.json
generated
vendored
Normal file
29
node_modules/glob/node_modules/minimatch/package.json
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||||
|
"name": "minimatch",
|
||||||
|
"description": "a glob matcher in javascript",
|
||||||
|
"version": "0.2.0",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/isaacs/minimatch.git"
|
||||||
|
},
|
||||||
|
"main": "minimatch.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "tap test"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "~1.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"tap": "~0.1.3"
|
||||||
|
},
|
||||||
|
"licenses" : [
|
||||||
|
{
|
||||||
|
"type" : "MIT",
|
||||||
|
"url" : "http://github.com/isaacs/minimatch/raw/master/LICENSE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
261
node_modules/glob/node_modules/minimatch/test/basic.js
generated
vendored
Normal file
261
node_modules/glob/node_modules/minimatch/test/basic.js
generated
vendored
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test
|
||||||
|
//
|
||||||
|
// TODO: Some of these tests do very bad things with backslashes, and will
|
||||||
|
// most likely fail badly on windows. They should probably be skipped.
|
||||||
|
|
||||||
|
var tap = require("tap")
|
||||||
|
, globalBefore = Object.keys(global)
|
||||||
|
, mm = require("../")
|
||||||
|
, files = [ "a", "b", "c", "d", "abc"
|
||||||
|
, "abd", "abe", "bb", "bcd"
|
||||||
|
, "ca", "cb", "dd", "de"
|
||||||
|
, "bdir/", "bdir/cfile"]
|
||||||
|
, next = files.concat([ "a-b", "aXb"
|
||||||
|
, ".x", ".y" ])
|
||||||
|
|
||||||
|
tap.test("basic tests", function (t) {
|
||||||
|
var start = Date.now()
|
||||||
|
|
||||||
|
// [ pattern, [matches], MM opts, files, TAP opts]
|
||||||
|
; [ "http://www.bashcookbook.com/bashinfo" +
|
||||||
|
"/source/bash-1.14.7/tests/glob-test"
|
||||||
|
, ["a*", ["a", "abc", "abd", "abe"]]
|
||||||
|
, ["X*", ["X*"], {nonull: true}]
|
||||||
|
|
||||||
|
// allow null glob expansion
|
||||||
|
, ["X*", []]
|
||||||
|
|
||||||
|
// isaacs: Slightly different than bash/sh/ksh
|
||||||
|
// \\* is not un-escaped to literal "*" in a failed match,
|
||||||
|
// but it does make it get treated as a literal star
|
||||||
|
, ["\\*", ["\\*"], {nonull: true}]
|
||||||
|
, ["\\**", ["\\**"], {nonull: true}]
|
||||||
|
, ["\\*\\*", ["\\*\\*"], {nonull: true}]
|
||||||
|
|
||||||
|
, ["b*/", ["bdir/"]]
|
||||||
|
, ["c*", ["c", "ca", "cb"]]
|
||||||
|
, ["**", files]
|
||||||
|
|
||||||
|
, ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}]
|
||||||
|
, ["s/\\..*//", ["s/\\..*//"], {nonull: true}]
|
||||||
|
|
||||||
|
, "legendary larry crashes bashes"
|
||||||
|
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"
|
||||||
|
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}]
|
||||||
|
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"
|
||||||
|
, ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}]
|
||||||
|
|
||||||
|
, "character classes"
|
||||||
|
, ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]]
|
||||||
|
, ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd",
|
||||||
|
"bdir/", "ca", "cb", "dd", "de"]]
|
||||||
|
, ["a*[^c]", ["abd", "abe"]]
|
||||||
|
, function () { files.push("a-b", "aXb") }
|
||||||
|
, ["a[X-]b", ["a-b", "aXb"]]
|
||||||
|
, function () { files.push(".x", ".y") }
|
||||||
|
, ["[^a-c]*", ["d", "dd", "de"]]
|
||||||
|
, function () { files.push("a*b/", "a*b/ooo") }
|
||||||
|
, ["a\\*b/*", ["a*b/ooo"]]
|
||||||
|
, ["a\\*?/*", ["a*b/ooo"]]
|
||||||
|
, ["*\\\\!*", [], {null: true}, ["echo !7"]]
|
||||||
|
, ["*\\!*", ["echo !7"], null, ["echo !7"]]
|
||||||
|
, ["*.\\*", ["r.*"], null, ["r.*"]]
|
||||||
|
, ["a[b]c", ["abc"]]
|
||||||
|
, ["a[\\b]c", ["abc"]]
|
||||||
|
, ["a?c", ["abc"]]
|
||||||
|
, ["a\\*c", [], {null: true}, ["abc"]]
|
||||||
|
, ["", [""], { null: true }, [""]]
|
||||||
|
|
||||||
|
, "http://www.opensource.apple.com/source/bash/bash-23/" +
|
||||||
|
"bash/tests/glob-test"
|
||||||
|
, function () { files.push("man/", "man/man1/", "man/man1/bash.1") }
|
||||||
|
, ["*/man*/bash.*", ["man/man1/bash.1"]]
|
||||||
|
, ["man/man1/bash.1", ["man/man1/bash.1"]]
|
||||||
|
, ["a***c", ["abc"], null, ["abc"]]
|
||||||
|
, ["a*****?c", ["abc"], null, ["abc"]]
|
||||||
|
, ["?*****??", ["abc"], null, ["abc"]]
|
||||||
|
, ["*****??", ["abc"], null, ["abc"]]
|
||||||
|
, ["?*****?c", ["abc"], null, ["abc"]]
|
||||||
|
, ["?***?****c", ["abc"], null, ["abc"]]
|
||||||
|
, ["?***?****?", ["abc"], null, ["abc"]]
|
||||||
|
, ["?***?****", ["abc"], null, ["abc"]]
|
||||||
|
, ["*******c", ["abc"], null, ["abc"]]
|
||||||
|
, ["*******?", ["abc"], null, ["abc"]]
|
||||||
|
, ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
|
||||||
|
, ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
|
||||||
|
, ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]]
|
||||||
|
, ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
|
||||||
|
, ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]]
|
||||||
|
, ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]]
|
||||||
|
, ["[-abc]", ["-"], null, ["-"]]
|
||||||
|
, ["[abc-]", ["-"], null, ["-"]]
|
||||||
|
, ["\\", ["\\"], null, ["\\"]]
|
||||||
|
, ["[\\\\]", ["\\"], null, ["\\"]]
|
||||||
|
, ["[[]", ["["], null, ["["]]
|
||||||
|
, ["[", ["["], null, ["["]]
|
||||||
|
, ["[*", ["[abc"], null, ["[abc"]]
|
||||||
|
, "a right bracket shall lose its special meaning and\n" +
|
||||||
|
"represent itself in a bracket expression if it occurs\n" +
|
||||||
|
"first in the list. -- POSIX.2 2.8.3.2"
|
||||||
|
, ["[]]", ["]"], null, ["]"]]
|
||||||
|
, ["[]-]", ["]"], null, ["]"]]
|
||||||
|
, ["[a-\z]", ["p"], null, ["p"]]
|
||||||
|
, ["??**********?****?", [], { null: true }, ["abc"]]
|
||||||
|
, ["??**********?****c", [], { null: true }, ["abc"]]
|
||||||
|
, ["?************c****?****", [], { null: true }, ["abc"]]
|
||||||
|
, ["*c*?**", [], { null: true }, ["abc"]]
|
||||||
|
, ["a*****c*?**", [], { null: true }, ["abc"]]
|
||||||
|
, ["a********???*******", [], { null: true }, ["abc"]]
|
||||||
|
, ["[]", [], { null: true }, ["a"]]
|
||||||
|
, ["[abc", [], { null: true }, ["["]]
|
||||||
|
|
||||||
|
, "nocase tests"
|
||||||
|
, ["XYZ", ["xYz"], { nocase: true, null: true }
|
||||||
|
, ["xYz", "ABC", "IjK"]]
|
||||||
|
, ["ab*", ["ABC"], { nocase: true, null: true }
|
||||||
|
, ["xYz", "ABC", "IjK"]]
|
||||||
|
, ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true }
|
||||||
|
, ["xYz", "ABC", "IjK"]]
|
||||||
|
|
||||||
|
// [ pattern, [matches], MM opts, files, TAP opts]
|
||||||
|
, "onestar/twostar"
|
||||||
|
, ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]]
|
||||||
|
, ["{/?,*}", ["/a", "bb"], {null: true}
|
||||||
|
, ["/a", "/b/b", "/a/b/c", "bb"]]
|
||||||
|
|
||||||
|
, "dots should not match unless requested"
|
||||||
|
, ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]]
|
||||||
|
|
||||||
|
// .. and . can only match patterns starting with .,
|
||||||
|
// even when options.dot is set.
|
||||||
|
, function () {
|
||||||
|
files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"]
|
||||||
|
}
|
||||||
|
, ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}]
|
||||||
|
, ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}]
|
||||||
|
, ["a/*/b", ["a/c/b"], {dot:false}]
|
||||||
|
, ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}]
|
||||||
|
|
||||||
|
|
||||||
|
// this also tests that changing the options needs
|
||||||
|
// to change the cache key, even if the pattern is
|
||||||
|
// the same!
|
||||||
|
, ["**", ["a/b","a/.d",".a/.d"], { dot: true }
|
||||||
|
, [ ".a/.d", "a/.d", "a/b"]]
|
||||||
|
|
||||||
|
, "paren sets cannot contain slashes"
|
||||||
|
, ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]]
|
||||||
|
|
||||||
|
// brace sets trump all else.
|
||||||
|
//
|
||||||
|
// invalid glob pattern. fails on bash4 and bsdglob.
|
||||||
|
// however, in this implementation, it's easier just
|
||||||
|
// to do the intuitive thing, and let brace-expansion
|
||||||
|
// actually come before parsing any extglob patterns,
|
||||||
|
// like the documentation seems to say.
|
||||||
|
//
|
||||||
|
// XXX: if anyone complains about this, either fix it
|
||||||
|
// or tell them to grow up and stop complaining.
|
||||||
|
//
|
||||||
|
// bash/bsdglob says this:
|
||||||
|
// , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]]
|
||||||
|
// but we do this instead:
|
||||||
|
, ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]]
|
||||||
|
|
||||||
|
// test partial parsing in the presence of comment/negation chars
|
||||||
|
, ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]]
|
||||||
|
, ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]]
|
||||||
|
|
||||||
|
// like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped.
|
||||||
|
, ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g"
|
||||||
|
, ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"]
|
||||||
|
, {}
|
||||||
|
, ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]]
|
||||||
|
|
||||||
|
|
||||||
|
// crazy nested {,,} and *(||) tests.
|
||||||
|
, function () {
|
||||||
|
files = [ "a", "b", "c", "d"
|
||||||
|
, "ab", "ac", "ad"
|
||||||
|
, "bc", "cb"
|
||||||
|
, "bc,d", "c,db", "c,d"
|
||||||
|
, "d)", "(b|c", "*(b|c"
|
||||||
|
, "b|c", "b|cc", "cb|c"
|
||||||
|
, "x(a|b|c)", "x(a|c)"
|
||||||
|
, "(a|b|c)", "(a|c)"]
|
||||||
|
}
|
||||||
|
, ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]]
|
||||||
|
, ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]]
|
||||||
|
// a
|
||||||
|
// *(b|c)
|
||||||
|
// *(b|d)
|
||||||
|
, ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]]
|
||||||
|
, ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]]
|
||||||
|
|
||||||
|
|
||||||
|
// test various flag settings.
|
||||||
|
, [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"]
|
||||||
|
, { noext: true } ]
|
||||||
|
, ["a?b", ["x/y/acb", "acb/"], {matchBase: true}
|
||||||
|
, ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ]
|
||||||
|
, ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]]
|
||||||
|
|
||||||
|
|
||||||
|
// begin channelling Boole and deMorgan...
|
||||||
|
, "negation tests"
|
||||||
|
, function () {
|
||||||
|
files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// anything that is NOT a* matches.
|
||||||
|
, ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]]
|
||||||
|
|
||||||
|
// anything that IS !a* matches.
|
||||||
|
, ["!a*", ["!ab", "!abc"], {nonegate: true}]
|
||||||
|
|
||||||
|
// anything that IS a* matches
|
||||||
|
, ["!!a*", ["a!b"]]
|
||||||
|
|
||||||
|
// anything that is NOT !a* matches
|
||||||
|
, ["!\\!a*", ["a!b", "d", "e", "\\!a"]]
|
||||||
|
|
||||||
|
].forEach(function (c) {
|
||||||
|
if (typeof c === "function") return c()
|
||||||
|
if (typeof c === "string") return t.comment(c)
|
||||||
|
|
||||||
|
var pattern = c[0]
|
||||||
|
, expect = c[1].sort(alpha)
|
||||||
|
, options = c[2] || {}
|
||||||
|
, f = c[3] || files
|
||||||
|
, tapOpts = c[4] || {}
|
||||||
|
|
||||||
|
// options.debug = true
|
||||||
|
var m = new mm.Minimatch(pattern, options)
|
||||||
|
var r = m.makeRe()
|
||||||
|
tapOpts.re = String(r) || JSON.stringify(r)
|
||||||
|
tapOpts.files = JSON.stringify(f)
|
||||||
|
tapOpts.pattern = pattern
|
||||||
|
tapOpts.set = m.set
|
||||||
|
tapOpts.negated = m.negate
|
||||||
|
|
||||||
|
var actual = mm.match(f, pattern, options)
|
||||||
|
actual.sort(alpha)
|
||||||
|
|
||||||
|
t.equivalent( actual, expect
|
||||||
|
, JSON.stringify(pattern) + " " + JSON.stringify(expect)
|
||||||
|
, tapOpts )
|
||||||
|
})
|
||||||
|
|
||||||
|
t.comment("time=" + (Date.now() - start) + "ms")
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
tap.test("global leak test", function (t) {
|
||||||
|
var globalAfter = Object.keys(global)
|
||||||
|
t.equivalent(globalAfter, globalBefore, "no new globals, please")
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
function alpha (a, b) {
|
||||||
|
return a > b ? 1 : -1
|
||||||
|
}
|
33
node_modules/glob/node_modules/minimatch/test/brace-expand.js
generated
vendored
Normal file
33
node_modules/glob/node_modules/minimatch/test/brace-expand.js
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
var tap = require("tap")
|
||||||
|
, minimatch = require("../")
|
||||||
|
|
||||||
|
tap.test("brace expansion", function (t) {
|
||||||
|
// [ pattern, [expanded] ]
|
||||||
|
; [ [ "a{b,c{d,e},{f,g}h}x{y,z}"
|
||||||
|
, [ "abxy"
|
||||||
|
, "abxz"
|
||||||
|
, "acdxy"
|
||||||
|
, "acdxz"
|
||||||
|
, "acexy"
|
||||||
|
, "acexz"
|
||||||
|
, "afhxy"
|
||||||
|
, "afhxz"
|
||||||
|
, "aghxy"
|
||||||
|
, "aghxz" ] ]
|
||||||
|
, [ "a{1..5}b"
|
||||||
|
, [ "a1b"
|
||||||
|
, "a2b"
|
||||||
|
, "a3b"
|
||||||
|
, "a4b"
|
||||||
|
, "a5b" ] ]
|
||||||
|
, [ "a{b}c", ["a{b}c"] ]
|
||||||
|
].forEach(function (tc) {
|
||||||
|
var p = tc[0]
|
||||||
|
, expect = tc[1]
|
||||||
|
t.equivalent(minimatch.braceExpand(p), expect, p)
|
||||||
|
})
|
||||||
|
console.error("ending")
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
14
node_modules/glob/node_modules/minimatch/test/caching.js
generated
vendored
Normal file
14
node_modules/glob/node_modules/minimatch/test/caching.js
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
var Minimatch = require("../minimatch.js").Minimatch
|
||||||
|
var tap = require("tap")
|
||||||
|
tap.test("cache test", function (t) {
|
||||||
|
var mm1 = new Minimatch("a?b")
|
||||||
|
var mm2 = new Minimatch("a?b")
|
||||||
|
t.equal(mm1, mm2, "should get the same object")
|
||||||
|
// the lru should drop it after 100 entries
|
||||||
|
for (var i = 0; i < 100; i ++) {
|
||||||
|
new Minimatch("a"+i)
|
||||||
|
}
|
||||||
|
mm2 = new Minimatch("a?b")
|
||||||
|
t.notEqual(mm1, mm2, "cache should have dropped")
|
||||||
|
t.end()
|
||||||
|
})
|
5
node_modules/glob/package.json
generated
vendored
5
node_modules/glob/package.json
generated
vendored
|
@ -2,7 +2,7 @@
|
||||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||||
"name": "glob",
|
"name": "glob",
|
||||||
"description": "a little globber",
|
"description": "a little globber",
|
||||||
"version": "3.0.1",
|
"version": "3.1.4",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/isaacs/node-glob.git"
|
"url": "git://github.com/isaacs/node-glob.git"
|
||||||
|
@ -12,8 +12,7 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-list":"1",
|
"minimatch": "0.2",
|
||||||
"minimatch": "0.1",
|
|
||||||
"graceful-fs": "~1.1.2",
|
"graceful-fs": "~1.1.2",
|
||||||
"inherits": "1"
|
"inherits": "1"
|
||||||
},
|
},
|
||||||
|
|
22
node_modules/glob/test/bash-comparison.js
generated
vendored
22
node_modules/glob/test/bash-comparison.js
generated
vendored
|
@ -5,7 +5,8 @@ var tap = require("tap")
|
||||||
|
|
||||||
// put more patterns here.
|
// put more patterns here.
|
||||||
, globs =
|
, globs =
|
||||||
["test/a/*/+(c|g)/./d"
|
[
|
||||||
|
"test/a/*/+(c|g)/./d"
|
||||||
,"test/a/**/[cg]/../[cg]"
|
,"test/a/**/[cg]/../[cg]"
|
||||||
,"test/a/{b,c,d,e,f}/**/g"
|
,"test/a/{b,c,d,e,f}/**/g"
|
||||||
,"test/a/b/**"
|
,"test/a/b/**"
|
||||||
|
@ -64,12 +65,20 @@ globs.forEach(function (pattern) {
|
||||||
}).sort(alphasort).reduce(function (set, f) {
|
}).sort(alphasort).reduce(function (set, f) {
|
||||||
if (f !== set[set.length - 1]) set.push(f)
|
if (f !== set[set.length - 1]) set.push(f)
|
||||||
return set
|
return set
|
||||||
}, [])
|
}, []).sort(alphasort)
|
||||||
}
|
}
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
||||||
glob(pattern, function (er, matches) {
|
glob(pattern, function (er, matches) {
|
||||||
|
// sort and unpark, just to match the shell results
|
||||||
|
matches = matches.map(function (m) {
|
||||||
|
return m.replace(/\/+/g, "/").replace(/\/$/, "")
|
||||||
|
}).sort(alphasort).reduce(function (set, f) {
|
||||||
|
if (f !== set[set.length - 1]) set.push(f)
|
||||||
|
return set
|
||||||
|
}, []).sort(alphasort)
|
||||||
|
|
||||||
t.ifError(er, pattern + " should not error")
|
t.ifError(er, pattern + " should not error")
|
||||||
globResult = matches
|
globResult = matches
|
||||||
next()
|
next()
|
||||||
|
@ -84,7 +93,14 @@ globs.forEach(function (pattern) {
|
||||||
})
|
})
|
||||||
|
|
||||||
tap.test(pattern + " sync", function (t) {
|
tap.test(pattern + " sync", function (t) {
|
||||||
t.deepEqual(glob.sync(pattern), echoOutput, "should match shell")
|
var matches = glob.sync(pattern).map(function (m) {
|
||||||
|
return m.replace(/\/+/g, "/").replace(/\/$/, "")
|
||||||
|
}).sort(alphasort).reduce(function (set, f) {
|
||||||
|
if (f !== set[set.length - 1]) set.push(f)
|
||||||
|
return set
|
||||||
|
}, []).sort(alphasort)
|
||||||
|
|
||||||
|
t.deepEqual(matches, echoOutput, "should match shell")
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
55
node_modules/glob/test/cwd-test.js
generated
vendored
Normal file
55
node_modules/glob/test/cwd-test.js
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
var tap = require("tap")
|
||||||
|
|
||||||
|
var origCwd = process.cwd()
|
||||||
|
process.chdir(__dirname)
|
||||||
|
|
||||||
|
tap.test("changing cwd and searching for **/d", function (t) {
|
||||||
|
var glob = require('glob')
|
||||||
|
var path = require('path')
|
||||||
|
t.test('.', function (t) {
|
||||||
|
glob('**/d', function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('a', function (t) {
|
||||||
|
glob('**/d', {cwd:path.resolve('a')}, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ 'b/c/d', 'c/d' ])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('a/b', function (t) {
|
||||||
|
glob('**/d', {cwd:path.resolve('a/b')}, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ 'c/d' ])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('a/b/', function (t) {
|
||||||
|
glob('**/d', {cwd:path.resolve('a/b/')}, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ 'c/d' ])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('.', function (t) {
|
||||||
|
glob('**/d', {cwd: process.cwd()}, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ 'a/b/c/d', 'a/c/d' ])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('cd -', function (t) {
|
||||||
|
process.chdir(origCwd)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
39
node_modules/glob/test/root-nomount.js
generated
vendored
Normal file
39
node_modules/glob/test/root-nomount.js
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
var tap = require("tap")
|
||||||
|
|
||||||
|
var origCwd = process.cwd()
|
||||||
|
process.chdir(__dirname)
|
||||||
|
|
||||||
|
tap.test("changing root and searching for /b*/**", function (t) {
|
||||||
|
var glob = require('glob')
|
||||||
|
var path = require('path')
|
||||||
|
t.test('.', function (t) {
|
||||||
|
glob('/b*/**', { globDebug: true, root: '.', nomount: true }, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('a', function (t) {
|
||||||
|
glob('/b*/**', { globDebug: true, root: path.resolve('a'), nomount: true }, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('root=a, cwd=a/b', function (t) {
|
||||||
|
glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b'), nomount: true }, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('cd -', function (t) {
|
||||||
|
process.chdir(origCwd)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
43
node_modules/glob/test/root.js
generated
vendored
Normal file
43
node_modules/glob/test/root.js
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
var tap = require("tap")
|
||||||
|
|
||||||
|
var origCwd = process.cwd()
|
||||||
|
process.chdir(__dirname)
|
||||||
|
|
||||||
|
tap.test("changing root and searching for /b*/**", function (t) {
|
||||||
|
var glob = require('glob')
|
||||||
|
var path = require('path')
|
||||||
|
t.test('.', function (t) {
|
||||||
|
glob('/b*/**', { globDebug: true, root: '.' }, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [])
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('a', function (t) {
|
||||||
|
glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
|
||||||
|
return path.join(path.resolve('a'), m)
|
||||||
|
}))
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('root=a, cwd=a/b', function (t) {
|
||||||
|
glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b') }, function (er, matches) {
|
||||||
|
t.ifError(er)
|
||||||
|
t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
|
||||||
|
return path.join(path.resolve('a'), m)
|
||||||
|
}))
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('cd -', function (t) {
|
||||||
|
process.chdir(origCwd)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
Loading…
Add table
Add a link
Reference in a new issue