first commit

This commit is contained in:
s.golasch
2023-08-01 13:49:46 +02:00
commit 1fc239fd54
20238 changed files with 3112246 additions and 0 deletions

15
build/node_modules/globule/.jshintrc generated vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"unused": true,
"boss": true,
"eqnull": true,
"node": true,
"es5": true
}

1
build/node_modules/globule/.npmignore generated vendored Normal file
View File

@@ -0,0 +1 @@
/node_modules/

6
build/node_modules/globule/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.8"
- "0.10"
before_script:
- npm install -g grunt-cli

48
build/node_modules/globule/Gruntfile.js generated vendored Normal file
View File

@@ -0,0 +1,48 @@
'use strict';
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
nodeunit: {
files: ['test/**/*_test.js'],
},
jshint: {
options: {
jshintrc: '.jshintrc'
},
gruntfile: {
src: 'Gruntfile.js'
},
lib: {
src: ['lib/**/*.js']
},
test: {
src: ['test/*.js']
},
},
watch: {
gruntfile: {
files: '<%= jshint.gruntfile.src %>',
tasks: ['jshint:gruntfile']
},
lib: {
files: '<%= jshint.lib.src %>',
tasks: ['jshint:lib', 'nodeunit']
},
test: {
files: '<%= jshint.test.src %>',
tasks: ['jshint:test', 'nodeunit']
},
},
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task.
grunt.registerTask('default', ['jshint', 'nodeunit']);
};

22
build/node_modules/globule/LICENSE-MIT generated vendored Normal file
View File

@@ -0,0 +1,22 @@
Copyright (c) 2013 "Cowboy" Ben Alman
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.

117
build/node_modules/globule/README.md generated vendored Normal file
View File

@@ -0,0 +1,117 @@
# globule [![Build Status](https://secure.travis-ci.org/cowboy/node-globule.png?branch=master)](http://travis-ci.org/cowboy/node-globule)
An easy-to-use wildcard globbing library.
## Getting Started
Install the module with: `npm install globule`
```javascript
var globule = require('globule');
var filepaths = globule.find('**/*.js');
```
## Documentation
### globule.find
Returns a unique array of all file or directory paths that match the given globbing pattern(s). This method accepts either comma separated globbing patterns or an array of globbing patterns. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.
```js
globule.find(patterns [, options])
```
The `options` object supports all [glob][] library options, along with a few extras. These are the most commonly used:
* `filter` Either a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats) or a function that will be passed the matched `src` filepath and `options` object as arguments. This function should return a `Boolean` value.
* `nonull` Retain globbing patterns in result set even if they fail to match files.
* `matchBase` Patterns without slashes will match just the basename part. Eg. this makes `*.js` work like `**/*.js`.
* `srcBase` Patterns will be matched relative to the specified path instead of the current working directory. This is a synonym for `cwd`.
* `prefixBase` Any specified `srcBase` will be prefixed to all returned filepaths.
[glob]: https://github.com/isaacs/node-glob
### globule.match
Match one or more globbing patterns against one or more file paths. Returns a uniqued array of all file paths that match any of the specified globbing patterns. Both the `patterns` and `filepaths` arguments can be a single string or array of strings. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.
```js
grunt.file.match(patterns, filepaths [, options])
```
### globule.isMatch
This method contains the same signature and logic as the `globule.match` method, but returns `true` if any files were matched, otherwise `false`.
```js
grunt.file.isMatch(patterns, filepaths [, options])
```
### globule.mapping
Given a set of source file paths, returns an array of src-dest file mapping objects. Both src and dest paths may be renamed, depending on the options specified.
```js
globule.mapping(filepaths [, options])
```
In addition to the options the `globule.find` method supports, the options object also supports these properties:
* `srcBase` The directory from which patterns are matched. Any string specified as `srcBase` is effectively stripped from the beginning of all matched paths.
* `destBase` The specified path is prefixed to all `dest` filepaths.
* `ext` Remove anything after (and including) the first `.` in the destination path, then append this value.
* `extDot` Change the behavior of `ext`, `"first"` and `"last"` will remove anything after the first or last `.` in the destination filename, respectively. Defaults to `"first"`.
* `flatten` Remove the path component from all matched src files. The src file path is still joined to the specified destBase.
* `rename` If specified, this function will be responsible for returning the final `dest` filepath. By default, it flattens paths (if specified), changes extensions (if specified) and joins the matched path to the `destBase`.
### globule.findMapping
This method is a convenience wrapper around the `globule.find` and `globule.mapping` methods.
```js
globule.findMapping(patterns [, options])
```
## Examples
Given the files `foo/a.js` and `foo/b.js`:
### srcBase and destBase
```js
globule.find("foo/*.js")
// ["foo/a.js", "foo/b.js"]
globule.find("*.js", {srcBase: "foo"})
// ["a.js", "b.js"]
globule.find("*.js", {srcBase: "foo", prefixBase: true})
// ["foo/a.js", "foo/b.js"]
```
```js
globule.findMapping("foo/*.js")
// [{src: "foo/a.js", dest: "foo/a.js"}, {src: "foo/b.js", dest: "foo/b.js"}]
globule.findMapping("foo/*.js", {destBase: "bar"})
// [{src: "foo/a.js", dest: "bar/foo/a.js"}, {src: "foo/b.js", dest: "bar/foo/b.js"}]
globule.findMapping("*.js", {srcBase: "foo", destBase: "bar"})
// [{src: "foo/a.js", dest: "bar/a.js"}, {src: "foo/b.js", dest: "bar/b.js"}]
```
```js
globule.mapping(["foo/a.js", "foo/b.js"])
// [{src: "foo/a.js", dest: "foo/a.js"}, {src: "foo/b.js", dest: "foo/b.js"}]
globule.mapping(["foo/a.js", "foo/b.js"], {destBase: "bar"})
// [{src: "foo/a.js", dest: "bar/foo/a.js"}, {src: "foo/b.js", dest: "bar/foo/b.js"}]
globule.mapping(["a.js", "b.js"], {srcBase: "foo", destBase: "bar"})
// [{src: "foo/a.js", dest: "bar/a.js"}, {src: "foo/b.js", dest: "bar/b.js"}]
```
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
## Release History
_(Nothing yet)_
## License
Copyright (c) 2013 "Cowboy" Ben Alman
Licensed under the MIT license.

172
build/node_modules/globule/lib/globule.js generated vendored Normal file
View File

@@ -0,0 +1,172 @@
/*
* globule
* https://github.com/cowboy/node-globule
*
* Copyright (c) 2013 "Cowboy" Ben Alman
* Licensed under the MIT license.
*/
'use strict';
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var glob = require('glob');
var minimatch = require('minimatch');
// The module.
var globule = exports;
// Process specified wildcard glob patterns or filenames against a
// callback, excluding and uniquing files in the result set.
function processPatterns(patterns, fn) {
return _.flatten(patterns).reduce(function(result, pattern) {
if (pattern.indexOf('!') === 0) {
// If the first character is ! all matches via this pattern should be
// removed from the result set.
pattern = pattern.slice(1);
return _.difference(result, fn(pattern));
} else {
// Otherwise, add all matching filepaths to the result set.
return _.union(result, fn(pattern));
}
}, []);
}
// Match a filepath or filepaths against one or more wildcard patterns. Returns
// all matching filepaths. This behaves just like minimatch.match, but supports
// any number of patterns.
globule.match = function(patterns, filepaths, options) {
// Return empty set if either patterns or filepaths was omitted.
if (patterns == null || filepaths == null) { return []; }
// Normalize patterns and filepaths to arrays.
if (!_.isArray(patterns)) { patterns = [patterns]; }
if (!_.isArray(filepaths)) { filepaths = [filepaths]; }
// Return empty set if there are no patterns or filepaths.
if (patterns.length === 0 || filepaths.length === 0) { return []; }
// Return all matching filepaths.
return processPatterns(patterns, function(pattern) {
return minimatch.match(filepaths, pattern, options || {});
});
};
// Match a filepath or filepaths against one or more wildcard patterns. Returns
// true if any of the patterns match.
globule.isMatch = function() {
return globule.match.apply(null, arguments).length > 0;
};
// Return an array of all file paths that match the given wildcard patterns.
globule.find = function() {
var args = _.toArray(arguments);
// If the last argument is an options object, remove it from args.
var options = _.isPlainObject(args[args.length - 1]) ? args.pop() : {};
// Use the first argument if it's an Array, otherwise use all arguments.
var patterns = _.isArray(args[0]) ? args[0] : args;
// Return empty set if there are no patterns or filepaths.
if (patterns.length === 0) { return []; }
var srcBase = options.srcBase || options.cwd;
// Create glob-specific options object.
var globOptions = _.extend({}, options);
if (srcBase) {
globOptions.cwd = srcBase;
}
// Get all matching filepaths.
var matches = processPatterns(patterns, function(pattern) {
return glob.sync(pattern, globOptions);
});
// If srcBase and prefixBase were specified, prefix srcBase to matched paths.
if (srcBase && options.prefixBase) {
matches = matches.map(function(filepath) {
return path.join(srcBase, filepath);
});
}
// Filter result set?
if (options.filter) {
matches = matches.filter(function(filepath) {
// If srcBase was specified but prefixBase was NOT, prefix srcBase
// temporarily, for filtering.
if (srcBase && !options.prefixBase) {
filepath = path.join(srcBase, filepath);
}
try {
if (_.isFunction(options.filter)) {
return options.filter(filepath, options);
} else {
// If the file is of the right type and exists, this should work.
return fs.statSync(filepath)[options.filter]();
}
} catch(err) {
// Otherwise, it's probably not the right type.
return false;
}
});
}
return matches;
};
var pathSeparatorRe = /[\/\\]/g;
var extDotRe = {
first: /(\.[^\/]*)?$/,
last: /(\.[^\/\.]*)?$/,
};
function rename(dest, options) {
// Flatten path?
if (options.flatten) {
dest = path.basename(dest);
}
// Change the extension?
if (options.ext) {
dest = dest.replace(extDotRe[options.extDot], options.ext);
}
// Join dest and destBase?
if (options.destBase) {
dest = path.join(options.destBase, dest);
}
return dest;
}
// Build a mapping of src-dest filepaths from the given set of filepaths.
globule.mapping = function(filepaths, options) {
// Return empty set if filepaths was omitted.
if (filepaths == null) { return []; }
options = _.defaults({}, options, {
extDot: 'first',
rename: rename,
});
var files = [];
var fileByDest = {};
// Find all files matching pattern, using passed-in options.
filepaths.forEach(function(src) {
// Generate destination filename.
var dest = options.rename(src, options);
// Prepend srcBase to all src paths.
if (options.srcBase) {
src = path.join(options.srcBase, src);
}
// Normalize filepaths to be unix-style.
dest = dest.replace(pathSeparatorRe, '/');
src = src.replace(pathSeparatorRe, '/');
// Map correct src path to dest path.
if (fileByDest[dest]) {
// If dest already exists, push this src onto that dest's src array.
fileByDest[dest].src.push(src);
} else {
// Otherwise create a new src-dest file mapping object.
files.push({
src: [src],
dest: dest,
});
// And store a reference for later use.
fileByDest[dest] = files[files.length - 1];
}
});
return files;
};
// Return a mapping of src-dest filepaths from files matching the given
// wildcard patterns.
globule.findMapping = function(patterns, options) {
return globule.mapping(globule.find(patterns, options), options);
};

View File

@@ -0,0 +1,2 @@
.*.swp
test/a/

View File

@@ -0,0 +1,3 @@
language: node_js
node_js:
- 0.8

27
build/node_modules/globule/node_modules/glob/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) Isaac Z. Schlueter ("Author")
All rights reserved.
The BSD License
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

233
build/node_modules/globule/node_modules/glob/README.md generated vendored Normal file
View File

@@ -0,0 +1,233 @@
# Glob
This is a glob implementation in JavaScript. It uses the `minimatch`
library to do its matching.
## Attention: node-glob users!
The API has changed dramatically between 2.x and 3.x. This library is
now 100% JavaScript, and the integer flags have been replaced with an
options object.
Also, there's an event emitter class, proper tests, and all the other
things you've come to expect from node modules.
And best of all, no compilation!
## Usage
```javascript
var glob = require("glob")
// options is optional
glob("**/*.js", options, function (er, files) {
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is ["**/*.js"]
// er is an error object or null.
})
```
## Features
Please see the [minimatch
documentation](https://github.com/isaacs/minimatch) for more details.
Supports these glob features:
* Brace Expansion
* Extended glob matching
* "Globstar" `**` matching
See:
* `man sh`
* `man bash`
* `man 3 fnmatch`
* `man 5 gitignore`
* [minimatch documentation](https://github.com/isaacs/minimatch)
## glob(pattern, [options], cb)
* `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
var Glob = require("glob").Glob
var mg = new Glob(pattern, options, cb)
```
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
* `minimatch` The minimatch object that the glob uses.
* `options` The options object passed in.
* `error` The error encountered. When an error is encountered, the
glob object is in an undefined state, and should be discarded.
* `aborted` Boolean which is set to true when calling `abort()`. There
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
* `end` When the matching is finished, this is emitted with all the
matches found. If the `nonull` option is set, and no match was found,
then the `matches` list contains the original pattern. The matches
are sorted, unless the `nosort` flag is set.
* `match` Every time a match is found, this is emitted with the matched.
* `error` Emitted when an unexpected error is encountered, or whenever
any fs error occurs if `options.strict` is set.
* `abort` When `abort()` is called, this event is raised.
### Methods
* `abort` Stop the search.
### Options
All the options that can be passed to Minimatch can also be passed to
Glob to change pattern matching behavior. Also, some have been added,
or have glob-specific ramifications.
All options are false by default, unless otherwise noted.
All options are added to the glob object, as well.
* `cwd` The current working directory in which to search. Defaults
to `process.cwd()`.
* `root` The place where patterns starting with `/` will be mounted
onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
systems, and `C:\` or some such on Windows.)
* `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.
* `stat` Set to true to stat *all* results. This reduces performance
somewhat, and is completely unnecessary, unless `readdir` is presumed
to be an untrustworthy indicator of file existence. It will cause
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
stderr. Set the `silent` option to true to suppress these warnings.
* `strict` When an unusual error is encountered
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 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.

View File

@@ -0,0 +1,9 @@
var Glob = require("../").Glob
var pattern = "test/a/**/[cg]/../[cg]"
console.log(pattern)
var mg = new Glob(pattern, {mark: true, sync:true}, function (er, matches) {
console.log("matches", matches)
})
console.log("after")

View File

@@ -0,0 +1,9 @@
var Glob = require("../").Glob
var pattern = "{./*/*,/*,/usr/local/*}"
console.log(pattern)
var mg = new Glob(pattern, {mark: true}, function (er, matches) {
console.log("matches", matches)
})
console.log("after")

643
build/node_modules/globule/node_modules/glob/glob.js generated vendored Normal file
View File

@@ -0,0 +1,643 @@
// Approach:
//
// 1. Get the minimatch set
// 2. For each pattern in the set, PROCESS(pattern)
// 3. Store matches per-set, then uniq them
//
// PROCESS(pattern)
// Get the first [n] items from pattern that are all strings
// Join these together. This is PREFIX.
// If there is no more remaining, then stat(PREFIX) and
// add to matches if it succeeds. END.
// readdir(PREFIX) as ENTRIES
// If fails, END
// If pattern[n] is GLOBSTAR
// // handle the case where the globstar match is empty
// // by pruning it out, and testing the resulting pattern
// PROCESS(pattern[0..n] + pattern[n+1 .. $])
// // handle other cases.
// for ENTRY in ENTRIES (not dotfiles)
// // attach globstar + tail onto the entry
// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $])
//
// else // not globstar
// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
// Test ENTRY against pattern[n]
// If fails, continue
// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
//
// Caveat:
// Cache all stats and readdirs results to minimize syscall. Since all
// we ever care about is existence and directory-ness, we can just keep
// `true` for files, and [children,...] for directories, or `false` for
// things that don't exist.
module.exports = glob
var fs = require("graceful-fs")
, minimatch = require("minimatch")
, Minimatch = minimatch.Minimatch
, inherits = require("inherits")
, EE = require("events").EventEmitter
, path = require("path")
, isDir = {}
, assert = require("assert").ok
function glob (pattern, options, cb) {
if (typeof options === "function") cb = options, options = {}
if (!options) options = {}
if (typeof options === "number") {
deprecated()
return
}
var g = new Glob(pattern, options, cb)
return g.sync ? g.found : g
}
glob.fnmatch = deprecated
function deprecated () {
throw new Error("glob's interface has changed. Please see the docs.")
}
glob.sync = globSync
function globSync (pattern, options) {
if (typeof options === "number") {
deprecated()
return
}
options = options || {}
options.sync = true
return glob(pattern, options)
}
glob.Glob = Glob
inherits(Glob, EE)
function Glob (pattern, options, cb) {
if (!(this instanceof Glob)) {
return new Glob(pattern, options, cb)
}
if (typeof cb === "function") {
this.on("error", cb)
this.on("end", function (matches) {
cb(null, matches)
})
}
options = options || {}
this.EOF = {}
this._emitQueue = []
this.maxDepth = options.maxDepth || 1000
this.maxLength = options.maxLength || Infinity
this.statCache = options.statCache || {}
this.changedCwd = false
var cwd = process.cwd()
if (!options.hasOwnProperty("cwd")) this.cwd = cwd
else {
this.cwd = options.cwd
this.changedCwd = path.resolve(options.cwd) !== cwd
}
this.root = options.root || path.resolve(this.cwd, "/")
this.root = path.resolve(this.root)
if (process.platform === "win32")
this.root = this.root.replace(/\\/g, "/")
this.nomount = !!options.nomount
if (!pattern) {
throw new Error("must provide pattern")
}
// base-matching: just use globstar for that.
if (options.matchBase && -1 === pattern.indexOf("/")) {
if (options.noglobstar) {
throw new Error("base matching requires globstar")
}
pattern = "**/" + pattern
}
this.strict = options.strict !== false
this.dot = !!options.dot
this.mark = !!options.mark
this.sync = !!options.sync
this.nounique = !!options.nounique
this.nonull = !!options.nonull
this.nosort = !!options.nosort
this.nocase = !!options.nocase
this.stat = !!options.stat
this.debug = !!options.debug || !!options.globDebug
if (this.debug)
this.log = console.error
this.silent = !!options.silent
var mm = this.minimatch = new Minimatch(pattern, options)
this.options = mm.options
pattern = this.pattern = mm.pattern
this.error = null
this.aborted = false
EE.call(this)
// process each pattern in the minimatch set
var n = this.minimatch.set.length
// The matches are stored as {<filename>: true,...} so that
// duplicates are automagically pruned.
// Later, we do an Object.keys() on these.
// Keep them as a list so we can fill in when nonull is set.
this.matches = new Array(n)
this.minimatch.set.forEach(iterator.bind(this))
function iterator (pattern, i, set) {
this._process(pattern, 0, i, function (er) {
if (er) this.emit("error", er)
if (-- n <= 0) this._finish()
})
}
}
Glob.prototype.log = function () {}
Glob.prototype._finish = function () {
assert(this instanceof Glob)
var nou = this.nounique
, all = nou ? [] : {}
for (var i = 0, l = this.matches.length; i < l; i ++) {
var matches = this.matches[i]
this.log("matches[%d] =", i, matches)
// do like the shell, and spit out the literal glob
if (!matches) {
if (this.nonull) {
var literal = this.minimatch.globSet[i]
if (nou) all.push(literal)
else all[literal] = true
}
} else {
// had matches
var m = Object.keys(matches)
if (nou) all.push.apply(all, m)
else m.forEach(function (m) {
all[m] = true
})
}
}
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
var isDir = (Array.isArray(sc) || sc === 2)
if (isDir && m.slice(-1) !== "/") {
return m + "/"
}
if (!isDir && m.slice(-1) === "/") {
return m.replace(/\/+$/, "")
}
return m
}, this)
}
this.log("emitting end", all)
this.EOF = this.found = all
this.emitMatch(this.EOF)
}
function alphasorti (a, b) {
a = a.toLowerCase()
b = b.toLowerCase()
return alphasort(a, b)
}
function alphasort (a, b) {
return a > b ? 1 : a < b ? -1 : 0
}
Glob.prototype.abort = function () {
this.aborted = true
this.emit("abort")
}
Glob.prototype.pause = function () {
if (this.paused) return
if (this.sync)
this.emit("error", new Error("Can't pause/resume sync glob"))
this.paused = true
this.emit("pause")
}
Glob.prototype.resume = function () {
if (!this.paused) return
if (this.sync)
this.emit("error", new Error("Can't pause/resume sync glob"))
this.paused = false
this.emit("resume")
this._processEmitQueue()
//process.nextTick(this.emit.bind(this, "resume"))
}
Glob.prototype.emitMatch = function (m) {
this._emitQueue.push(m)
this._processEmitQueue()
}
Glob.prototype._processEmitQueue = function (m) {
while (!this._processingEmitQueue &&
!this.paused) {
this._processingEmitQueue = true
var m = this._emitQueue.shift()
if (!m) {
this._processingEmitQueue = false
break
}
this.log('emit!', m === this.EOF ? "end" : "match")
this.emit(m === this.EOF ? "end" : "match", m)
this._processingEmitQueue = false
}
}
Glob.prototype._process = function (pattern, depth, index, cb_) {
assert(this instanceof Glob)
var cb = function cb (er, res) {
assert(this instanceof Glob)
if (this.paused) {
if (!this._processQueue) {
this._processQueue = []
this.once("resume", function () {
var q = this._processQueue
this._processQueue = null
q.forEach(function (cb) { cb() })
})
}
this._processQueue.push(cb_.bind(this, er, res))
} else {
cb_.call(this, er, res)
}
}.bind(this)
if (this.aborted) return cb()
if (depth > this.maxDepth) return cb()
// Get the first [n] parts of pattern that are all strings.
var n = 0
while (typeof pattern[n] === "string") {
n ++
}
// now n is the index of the first one that is *not* a string.
// see if there's anything else
var prefix
switch (n) {
// if not, then this is rather simple
case pattern.length:
prefix = pattern.join("/")
this._stat(prefix, function (exists, isDir) {
// either it's there, or it isn't.
// nothing more to do, either way.
if (exists) {
if (prefix && isAbsolute(prefix) && !this.nomount) {
if (prefix.charAt(0) === "/") {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
}
}
if (process.platform === "win32")
prefix = prefix.replace(/\\/g, "/")
this.matches[index] = this.matches[index] || {}
this.matches[index][prefix] = true
this.emitMatch(prefix)
}
return cb()
})
return
case 0:
// pattern *starts* with some non-trivial item.
// going to readdir(cwd), but not include the prefix in matches.
prefix = null
break
default:
// pattern has some string bits in the front.
// whatever it starts with, whether that's "absolute" like /foo/bar,
// or "relative" like "../baz"
prefix = pattern.slice(0, n)
prefix = prefix.join("/")
break
}
// get the list of entries.
var read
if (prefix === null) read = "."
else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) {
if (!prefix || !isAbsolute(prefix)) {
prefix = path.join("/", prefix)
}
read = prefix = path.resolve(prefix)
// if (process.platform === "win32")
// read = prefix = prefix.replace(/^[a-zA-Z]:|\\/g, "/")
this.log('absolute: ', prefix, this.root, pattern, read)
} else {
read = prefix
}
this.log('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 {
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]))
})
}
// 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)
}
if (process.platform === "win32")
e = e.replace(/\\/g, "/")
this.matches[index] = this.matches[index] || {}
this.matches[index][e] = true
this.emitMatch(e)
}, this)
return cb.call(this)
}
// now test all the remaining entries as stand-ins for that part
// of the pattern.
var l = entries.length
, errState = null
if (l === 0) return cb() // no matches possible
entries.forEach(function (e) {
var p = pattern.slice(0, n).concat(e).concat(pattern.slice(n + 1))
this._process(p, depth + 1, index, function (er) {
if (errState) return
if (er) return cb(errState = er)
if (--l === 0) return cb.call(this)
})
}, this)
})
}
Glob.prototype._stat = function (f, cb) {
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)
}
this.log('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
}
this._afterStat(f, abs, cb, er, stat)
} else {
fs.stat(abs, this._afterStat.bind(this, f, abs, cb))
}
}
Glob.prototype._afterStat = function (f, abs, cb, er, stat) {
var exists
assert(this instanceof Glob)
if (abs.slice(-1) === "/" && stat && !stat.isDirectory()) {
this.log("should be ENOTDIR, fake it")
er = new Error("ENOTDIR, not a directory '" + abs + "'")
er.path = abs
er.code = "ENOTDIR"
stat = null
}
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)
}
this.log('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
this.log(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}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/
, 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 === ""
}

View File

@@ -0,0 +1,61 @@
{
"_from": "glob@~3.1.21",
"_id": "glob@3.1.21",
"_inBundle": false,
"_integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=",
"_location": "/globule/glob",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "glob@~3.1.21",
"name": "glob",
"escapedName": "glob",
"rawSpec": "~3.1.21",
"saveSpec": null,
"fetchSpec": "~3.1.21"
},
"_requiredBy": [
"/globule"
],
"_resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz",
"_shasum": "d29e0a055dea5138f4d07ed40e8982e83c2066cd",
"_spec": "glob@~3.1.21",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/globule",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"bugs": {
"url": "https://github.com/isaacs/node-glob/issues"
},
"bundleDependencies": false,
"dependencies": {
"graceful-fs": "~1.2.0",
"inherits": "1",
"minimatch": "~0.2.11"
},
"deprecated": false,
"description": "a little globber",
"devDependencies": {
"mkdirp": "0",
"rimraf": "1",
"tap": "~0.4.0"
},
"engines": {
"node": "*"
},
"homepage": "https://github.com/isaacs/node-glob#readme",
"license": "BSD",
"main": "glob.js",
"name": "glob",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-glob.git"
},
"scripts": {
"test": "tap test/*.js"
},
"version": "3.1.21"
}

View File

@@ -0,0 +1,176 @@
// just a little pre-run script to set up the fixtures.
// zz-finish cleans it up
var mkdirp = require("mkdirp")
var path = require("path")
var i = 0
var tap = require("tap")
var fs = require("fs")
var rimraf = require("rimraf")
var files =
[ "a/.abcdef/x/y/z/a"
, "a/abcdef/g/h"
, "a/abcfed/g/h"
, "a/b/c/d"
, "a/bc/e/f"
, "a/c/d/c/b"
, "a/cb/e/f"
]
var symlinkTo = path.resolve(__dirname, "a/symlink/a/b/c")
var symlinkFrom = "../.."
files = files.map(function (f) {
return path.resolve(__dirname, f)
})
tap.test("remove fixtures", function (t) {
rimraf(path.resolve(__dirname, "a"), function (er) {
t.ifError(er, "remove fixtures")
t.end()
})
})
files.forEach(function (f) {
tap.test(f, function (t) {
var d = path.dirname(f)
mkdirp(d, 0755, function (er) {
if (er) {
t.fail(er)
return t.bailout()
}
fs.writeFile(f, "i like tests", function (er) {
t.ifError(er, "make file")
t.end()
})
})
})
})
if (process.platform !== "win32") {
tap.test("symlinky", function (t) {
var d = path.dirname(symlinkTo)
console.error("mkdirp", d)
mkdirp(d, 0755, function (er) {
t.ifError(er)
fs.symlink(symlinkFrom, symlinkTo, "dir", function (er) {
t.ifError(er, "make symlink")
t.end()
})
})
})
}
;["foo","bar","baz","asdf","quux","qwer","rewq"].forEach(function (w) {
w = "/tmp/glob-test/" + w
tap.test("create " + w, function (t) {
mkdirp(w, function (er) {
if (er)
throw er
t.pass(w)
t.end()
})
})
})
// generate the bash pattern test-fixtures if possible
if (process.platform === "win32" || !process.env.TEST_REGEN) {
console.error("Windows, or TEST_REGEN unset. Using cached fixtures.")
return
}
var spawn = require("child_process").spawn;
var globs =
// put more patterns here.
// anything that would be directly in / should be in /tmp/glob-test
["test/a/*/+(c|g)/./d"
,"test/a/**/[cg]/../[cg]"
,"test/a/{b,c,d,e,f}/**/g"
,"test/a/b/**"
,"test/**/g"
,"test/a/abc{fed,def}/g/h"
,"test/a/abc{fed/g,def}/**/"
,"test/a/abc{fed/g,def}/**///**/"
,"test/**/a/**/"
,"test/+(a|b|c)/a{/,bc*}/**"
,"test/*/*/*/f"
,"test/**/f"
,"test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**"
,"{./*/*,/tmp/glob-test/*}"
,"{/tmp/glob-test/*,*}" // evil owl face! how you taunt me!
,"test/a/!(symlink)/**"
]
var bashOutput = {}
var fs = require("fs")
globs.forEach(function (pattern) {
tap.test("generate fixture " + pattern, function (t) {
var cmd = "shopt -s globstar && " +
"shopt -s extglob && " +
"shopt -s nullglob && " +
// "shopt >&2; " +
"eval \'for i in " + pattern + "; do echo $i; done\'"
var cp = spawn("bash", ["-c", cmd], { cwd: path.dirname(__dirname) })
var out = []
cp.stdout.on("data", function (c) {
out.push(c)
})
cp.stderr.pipe(process.stderr)
cp.on("close", function (code) {
out = flatten(out)
if (!out)
out = []
else
out = cleanResults(out.split(/\r*\n/))
bashOutput[pattern] = out
t.notOk(code, "bash test should finish nicely")
t.end()
})
})
})
tap.test("save fixtures", function (t) {
var fname = path.resolve(__dirname, "bash-results.json")
var data = JSON.stringify(bashOutput, null, 2) + "\n"
fs.writeFile(fname, data, function (er) {
t.ifError(er)
t.end()
})
})
function cleanResults (m) {
// normalize discrepancies in ordering, duplication,
// and ending slashes.
return m.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).map(function (f) {
// de-windows
return (process.platform !== 'win32') ? f
: f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/')
})
}
function flatten (chunks) {
var s = 0
chunks.forEach(function (c) { s += c.length })
var out = new Buffer(s)
s = 0
chunks.forEach(function (c) {
c.copy(out, s)
s += c.length
})
return out.toString().trim()
}
function alphasort (a, b) {
a = a.toLowerCase()
b = b.toLowerCase()
return a > b ? 1 : a < b ? -1 : 0
}

View File

@@ -0,0 +1,63 @@
// basic test
// show that it does the same thing by default as the shell.
var tap = require("tap")
, child_process = require("child_process")
, bashResults = require("./bash-results.json")
, globs = Object.keys(bashResults)
, glob = require("../")
, path = require("path")
// run from the root of the project
// this is usually where you're at anyway, but be sure.
process.chdir(path.resolve(__dirname, ".."))
function alphasort (a, b) {
a = a.toLowerCase()
b = b.toLowerCase()
return a > b ? 1 : a < b ? -1 : 0
}
globs.forEach(function (pattern) {
var expect = bashResults[pattern]
// anything regarding the symlink thing will fail on windows, so just skip it
if (process.platform === "win32" &&
expect.some(function (m) {
return /\/symlink\//.test(m)
}))
return
tap.test(pattern, function (t) {
glob(pattern, function (er, matches) {
if (er)
throw er
// sort and unmark, just to match the shell results
matches = cleanResults(matches)
t.deepEqual(matches, expect, pattern)
t.end()
})
})
tap.test(pattern + " sync", function (t) {
var matches = cleanResults(glob.sync(pattern))
t.deepEqual(matches, expect, "should match shell")
t.end()
})
})
function cleanResults (m) {
// normalize discrepancies in ordering, duplication,
// and ending slashes.
return m.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).map(function (f) {
// de-windows
return (process.platform !== 'win32') ? f
: f.replace(/^[a-zA-Z]:[\/\\]+/, '/').replace(/[\\\/]+/g, '/')
})
}

View File

@@ -0,0 +1,348 @@
{
"test/a/*/+(c|g)/./d": [
"test/a/b/c/./d"
],
"test/a/**/[cg]/../[cg]": [
"test/a/abcdef/g/../g",
"test/a/abcfed/g/../g",
"test/a/b/c/../c",
"test/a/c/../c",
"test/a/c/d/c/../c",
"test/a/symlink/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c"
],
"test/a/{b,c,d,e,f}/**/g": [],
"test/a/b/**": [
"test/a/b",
"test/a/b/c",
"test/a/b/c/d"
],
"test/**/g": [
"test/a/abcdef/g",
"test/a/abcfed/g"
],
"test/a/abc{fed,def}/g/h": [
"test/a/abcdef/g/h",
"test/a/abcfed/g/h"
],
"test/a/abc{fed/g,def}/**/": [
"test/a/abcdef",
"test/a/abcdef/g",
"test/a/abcfed/g"
],
"test/a/abc{fed/g,def}/**///**/": [
"test/a/abcdef",
"test/a/abcdef/g",
"test/a/abcfed/g"
],
"test/**/a/**/": [
"test/a",
"test/a/abcdef",
"test/a/abcdef/g",
"test/a/abcfed",
"test/a/abcfed/g",
"test/a/b",
"test/a/b/c",
"test/a/bc",
"test/a/bc/e",
"test/a/c",
"test/a/c/d",
"test/a/c/d/c",
"test/a/cb",
"test/a/cb/e",
"test/a/symlink",
"test/a/symlink/a",
"test/a/symlink/a/b",
"test/a/symlink/a/b/c",
"test/a/symlink/a/b/c/a",
"test/a/symlink/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b"
],
"test/+(a|b|c)/a{/,bc*}/**": [
"test/a/abcdef",
"test/a/abcdef/g",
"test/a/abcdef/g/h",
"test/a/abcfed",
"test/a/abcfed/g",
"test/a/abcfed/g/h"
],
"test/*/*/*/f": [
"test/a/bc/e/f",
"test/a/cb/e/f"
],
"test/**/f": [
"test/a/bc/e/f",
"test/a/cb/e/f"
],
"test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**": [
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
"test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c"
],
"{./*/*,/tmp/glob-test/*}": [
"./examples/g.js",
"./examples/usr-local.js",
"./node_modules/graceful-fs",
"./node_modules/inherits",
"./node_modules/minimatch",
"./node_modules/mkdirp",
"./node_modules/rimraf",
"./node_modules/tap",
"./test/00-setup.js",
"./test/a",
"./test/bash-comparison.js",
"./test/bash-results.json",
"./test/cwd-test.js",
"./test/mark.js",
"./test/nocase-nomagic.js",
"./test/pause-resume.js",
"./test/root-nomount.js",
"./test/root.js",
"./test/zz-cleanup.js",
"/tmp/glob-test/asdf",
"/tmp/glob-test/bar",
"/tmp/glob-test/baz",
"/tmp/glob-test/foo",
"/tmp/glob-test/quux",
"/tmp/glob-test/qwer",
"/tmp/glob-test/rewq"
],
"{/tmp/glob-test/*,*}": [
"/tmp/glob-test/asdf",
"/tmp/glob-test/bar",
"/tmp/glob-test/baz",
"/tmp/glob-test/foo",
"/tmp/glob-test/quux",
"/tmp/glob-test/qwer",
"/tmp/glob-test/rewq",
"examples",
"glob.js",
"LICENSE",
"node_modules",
"package.json",
"README.md",
"test"
],
"test/a/!(symlink)/**": [
"test/a/abcdef",
"test/a/abcdef/g",
"test/a/abcdef/g/h",
"test/a/abcfed",
"test/a/abcfed/g",
"test/a/abcfed/g/h",
"test/a/b",
"test/a/b/c",
"test/a/b/c/d",
"test/a/bc",
"test/a/bc/e",
"test/a/bc/e/f",
"test/a/c",
"test/a/c/d",
"test/a/c/d/c",
"test/a/c/d/c/b",
"test/a/cb",
"test/a/cb/e",
"test/a/cb/e/f"
]
}

View 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('../')
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()
})

View File

@@ -0,0 +1,74 @@
var test = require("tap").test
var glob = require('../')
process.chdir(__dirname)
test("mark, no / on pattern", function (t) {
glob("a/*", {mark: true}, function (er, results) {
if (er)
throw er
var expect = [ 'a/abcdef/',
'a/abcfed/',
'a/b/',
'a/bc/',
'a/c/',
'a/cb/' ]
if (process.platform !== "win32")
expect.push('a/symlink/')
t.same(results, expect)
t.end()
})
})
test("mark=false, no / on pattern", function (t) {
glob("a/*", function (er, results) {
if (er)
throw er
var expect = [ 'a/abcdef',
'a/abcfed',
'a/b',
'a/bc',
'a/c',
'a/cb' ]
if (process.platform !== "win32")
expect.push('a/symlink')
t.same(results, expect)
t.end()
})
})
test("mark=true, / on pattern", function (t) {
glob("a/*/", {mark: true}, function (er, results) {
if (er)
throw er
var expect = [ 'a/abcdef/',
'a/abcfed/',
'a/b/',
'a/bc/',
'a/c/',
'a/cb/' ]
if (process.platform !== "win32")
expect.push('a/symlink/')
t.same(results, expect)
t.end()
})
})
test("mark=false, / on pattern", function (t) {
glob("a/*/", function (er, results) {
if (er)
throw er
var expect = [ 'a/abcdef/',
'a/abcfed/',
'a/b/',
'a/bc/',
'a/c/',
'a/cb/' ]
if (process.platform !== "win32")
expect.push('a/symlink/')
t.same(results, expect)
t.end()
})
})

View File

@@ -0,0 +1,113 @@
var fs = require('graceful-fs');
var test = require('tap').test;
var glob = require('../');
test('mock fs', function(t) {
var stat = fs.stat
var statSync = fs.statSync
var readdir = fs.readdir
var readdirSync = fs.readdirSync
function fakeStat(path) {
var ret
switch (path.toLowerCase()) {
case '/tmp': case '/tmp/':
ret = { isDirectory: function() { return true } }
break
case '/tmp/a':
ret = { isDirectory: function() { return false } }
break
}
return ret
}
fs.stat = function(path, cb) {
var f = fakeStat(path);
if (f) {
process.nextTick(function() {
cb(null, f)
})
} else {
stat.call(fs, path, cb)
}
}
fs.statSync = function(path) {
return fakeStat(path) || statSync.call(fs, path)
}
function fakeReaddir(path) {
var ret
switch (path.toLowerCase()) {
case '/tmp': case '/tmp/':
ret = [ 'a', 'A' ]
break
case '/':
ret = ['tmp', 'tMp', 'tMP', 'TMP']
}
return ret
}
fs.readdir = function(path, cb) {
var f = fakeReaddir(path)
if (f)
process.nextTick(function() {
cb(null, f)
})
else
readdir.call(fs, path, cb)
}
fs.readdirSync = function(path) {
return fakeReaddir(path) || readdirSync.call(fs, path)
}
t.pass('mocked')
t.end()
})
test('nocase, nomagic', function(t) {
var n = 2
var want = [ '/TMP/A',
'/TMP/a',
'/tMP/A',
'/tMP/a',
'/tMp/A',
'/tMp/a',
'/tmp/A',
'/tmp/a' ]
glob('/tmp/a', { nocase: true }, function(er, res) {
if (er)
throw er
t.same(res.sort(), want)
if (--n === 0) t.end()
})
glob('/tmp/A', { nocase: true }, function(er, res) {
if (er)
throw er
t.same(res.sort(), want)
if (--n === 0) t.end()
})
})
test('nocase, with some magic', function(t) {
t.plan(2)
var want = [ '/TMP/A',
'/TMP/a',
'/tMP/A',
'/tMP/a',
'/tMp/A',
'/tMp/a',
'/tmp/A',
'/tmp/a' ]
glob('/tmp/*', { nocase: true }, function(er, res) {
if (er)
throw er
t.same(res.sort(), want)
})
glob('/tmp/*', { nocase: true }, function(er, res) {
if (er)
throw er
t.same(res.sort(), want)
})
})

View File

@@ -0,0 +1,73 @@
// show that no match events happen while paused.
var tap = require("tap")
, child_process = require("child_process")
// just some gnarly pattern with lots of matches
, pattern = "test/a/!(symlink)/**"
, bashResults = require("./bash-results.json")
, patterns = Object.keys(bashResults)
, glob = require("../")
, Glob = glob.Glob
, path = require("path")
// run from the root of the project
// this is usually where you're at anyway, but be sure.
process.chdir(path.resolve(__dirname, ".."))
function alphasort (a, b) {
a = a.toLowerCase()
b = b.toLowerCase()
return a > b ? 1 : a < b ? -1 : 0
}
function cleanResults (m) {
// normalize discrepancies in ordering, duplication,
// and ending slashes.
return m.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).map(function (f) {
// de-windows
return (process.platform !== 'win32') ? f
: f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/')
})
}
var globResults = []
tap.test("use a Glob object, and pause/resume it", function (t) {
var g = new Glob(pattern)
, paused = false
, res = []
, expect = bashResults[pattern]
g.on("pause", function () {
console.error("pause")
})
g.on("resume", function () {
console.error("resume")
})
g.on("match", function (m) {
t.notOk(g.paused, "must not be paused")
globResults.push(m)
g.pause()
t.ok(g.paused, "must be paused")
setTimeout(g.resume.bind(g), 10)
})
g.on("end", function (matches) {
t.pass("reached glob end")
globResults = cleanResults(globResults)
matches = cleanResults(matches)
t.deepEqual(matches, globResults,
"end event matches should be the same as match events")
t.deepEqual(matches, expect,
"glob matches should be the same as bash results")
t.end()
})
})

View 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('../')
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()
})

View File

@@ -0,0 +1,46 @@
var t = require("tap")
var origCwd = process.cwd()
process.chdir(__dirname)
var glob = require('../')
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) {
console.error("root=" + path.resolve('a'))
glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) {
t.ifError(er)
var wanted = [
'/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f'
].map(function (m) {
return path.join(path.resolve('a'), m).replace(/\\/g, '/')
})
t.like(matches, wanted)
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).replace(/\\/g, '/')
}))
t.end()
})
})
t.test('cd -', function (t) {
process.chdir(origCwd)
t.end()
})

View File

@@ -0,0 +1,11 @@
// remove the fixtures
var tap = require("tap")
, rimraf = require("rimraf")
, path = require("path")
tap.test("cleanup fixtures", function (t) {
rimraf(path.resolve(__dirname, "a"), function (er) {
t.ifError(er, "removed")
t.end()
})
})

View File

@@ -0,0 +1 @@
node_modules/

View File

@@ -0,0 +1,27 @@
Copyright (c) Isaac Z. Schlueter ("Author")
All rights reserved.
The BSD License
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,33 @@
# graceful-fs
graceful-fs functions as a drop-in replacement for the fs module,
making various improvements.
The improvements are meant to normalize behavior across different
platforms and environments, and to make filesystem access more
resilient to errors.
## Improvements over fs module
graceful-fs:
* keeps track of how many file descriptors are open, and by default
limits this to 1024. Any further requests to open a file are put in a
queue until new slots become available. If 1024 turns out to be too
much, it decreases the limit further.
* fixes `lchmod` for Node versions prior to 0.6.2.
* implements `fs.lutimes` if possible. Otherwise it becomes a noop.
* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or
`lchown` if the user isn't root.
* makes `lchmod` and `lchown` become noops, if not available.
* retries reading a file if `read` results in EAGAIN error.
On Windows, it retries renaming a file for up to one second if `EACCESS`
or `EPERM` error occurs, likely because antivirus software has locked
the directory.
## Configuration
The maximum number of open file descriptors that graceful-fs manages may
be adjusted by setting `fs.MAX_OPEN` to a different number. The default
is 1024.

View File

@@ -0,0 +1,442 @@
// this keeps a queue of opened file descriptors, and will make
// fs operations wait until some have closed before trying to open more.
var fs = exports = module.exports = {}
fs._originalFs = require("fs")
Object.getOwnPropertyNames(fs._originalFs).forEach(function(prop) {
var desc = Object.getOwnPropertyDescriptor(fs._originalFs, prop)
Object.defineProperty(fs, prop, desc)
})
var queue = []
, constants = require("constants")
fs._curOpen = 0
fs.MIN_MAX_OPEN = 64
fs.MAX_OPEN = 1024
// prevent EMFILE errors
function OpenReq (path, flags, mode, cb) {
this.path = path
this.flags = flags
this.mode = mode
this.cb = cb
}
function noop () {}
fs.open = gracefulOpen
function gracefulOpen (path, flags, mode, cb) {
if (typeof mode === "function") cb = mode, mode = null
if (typeof cb !== "function") cb = noop
if (fs._curOpen >= fs.MAX_OPEN) {
queue.push(new OpenReq(path, flags, mode, cb))
setTimeout(flush)
return
}
open(path, flags, mode, function (er, fd) {
if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
// that was too many. reduce max, get back in queue.
// this should only happen once in a great while, and only
// if the ulimit -n is set lower than 1024.
fs.MAX_OPEN = fs._curOpen - 1
return fs.open(path, flags, mode, cb)
}
cb(er, fd)
})
}
function open (path, flags, mode, cb) {
cb = cb || noop
fs._curOpen ++
fs._originalFs.open.call(fs, path, flags, mode, function (er, fd) {
if (er) onclose()
cb(er, fd)
})
}
fs.openSync = function (path, flags, mode) {
var ret
ret = fs._originalFs.openSync.call(fs, path, flags, mode)
fs._curOpen ++
return ret
}
function onclose () {
fs._curOpen --
flush()
}
function flush () {
while (fs._curOpen < fs.MAX_OPEN) {
var req = queue.shift()
if (!req) return
switch (req.constructor.name) {
case 'OpenReq':
open(req.path, req.flags || "r", req.mode || 0777, req.cb)
break
case 'ReaddirReq':
readdir(req.path, req.cb)
break
case 'ReadFileReq':
readFile(req.path, req.options, req.cb)
break
case 'WriteFileReq':
writeFile(req.path, req.data, req.options, req.cb)
break
default:
throw new Error('Unknown req type: ' + req.constructor.name)
}
}
}
fs.close = function (fd, cb) {
cb = cb || noop
fs._originalFs.close.call(fs, fd, function (er) {
onclose()
cb(er)
})
}
fs.closeSync = function (fd) {
try {
return fs._originalFs.closeSync.call(fs, fd)
} finally {
onclose()
}
}
// readdir takes a fd as well.
// however, the sync version closes it right away, so
// there's no need to wrap.
// It would be nice to catch when it throws an EMFILE,
// but that's relatively rare anyway.
fs.readdir = gracefulReaddir
function gracefulReaddir (path, cb) {
if (fs._curOpen >= fs.MAX_OPEN) {
queue.push(new ReaddirReq(path, cb))
setTimeout(flush)
return
}
readdir(path, function (er, files) {
if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
fs.MAX_OPEN = fs._curOpen - 1
return fs.readdir(path, cb)
}
cb(er, files)
})
}
function readdir (path, cb) {
cb = cb || noop
fs._curOpen ++
fs._originalFs.readdir.call(fs, path, function (er, files) {
onclose()
cb(er, files)
})
}
function ReaddirReq (path, cb) {
this.path = path
this.cb = cb
}
fs.readFile = gracefulReadFile
function gracefulReadFile(path, options, cb) {
if (typeof options === "function") cb = options, options = null
if (typeof cb !== "function") cb = noop
if (fs._curOpen >= fs.MAX_OPEN) {
queue.push(new ReadFileReq(path, options, cb))
setTimeout(flush)
return
}
readFile(path, options, function (er, data) {
if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
fs.MAX_OPEN = fs._curOpen - 1
return fs.readFile(path, options, cb)
}
cb(er, data)
})
}
function readFile (path, options, cb) {
cb = cb || noop
fs._curOpen ++
fs._originalFs.readFile.call(fs, path, options, function (er, data) {
onclose()
cb(er, data)
})
}
function ReadFileReq (path, options, cb) {
this.path = path
this.options = options
this.cb = cb
}
fs.writeFile = gracefulWriteFile
function gracefulWriteFile(path, data, options, cb) {
if (typeof options === "function") cb = options, options = null
if (typeof cb !== "function") cb = noop
if (fs._curOpen >= fs.MAX_OPEN) {
queue.push(new WriteFileReq(path, data, options, cb))
setTimeout(flush)
return
}
writeFile(path, data, options, function (er) {
if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
fs.MAX_OPEN = fs._curOpen - 1
return fs.writeFile(path, data, options, cb)
}
cb(er)
})
}
function writeFile (path, data, options, cb) {
cb = cb || noop
fs._curOpen ++
fs._originalFs.writeFile.call(fs, path, data, options, function (er) {
onclose()
cb(er)
})
}
function WriteFileReq (path, data, options, cb) {
this.path = path
this.data = data
this.options = options
this.cb = cb
}
// (re-)implement some things that are known busted or missing.
var constants = require("constants")
// lchmod, broken prior to 0.6.2
// back-port the fix here.
if (constants.hasOwnProperty('O_SYMLINK') &&
process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
fs.lchmod = function (path, mode, callback) {
callback = callback || noop
fs.open( path
, constants.O_WRONLY | constants.O_SYMLINK
, mode
, function (err, fd) {
if (err) {
callback(err)
return
}
// prefer to return the chmod error, if one occurs,
// but still try to close, and report closing errors if they occur.
fs.fchmod(fd, mode, function (err) {
fs.close(fd, function(err2) {
callback(err || err2)
})
})
})
}
fs.lchmodSync = function (path, mode) {
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
// prefer to return the chmod error, if one occurs,
// but still try to close, and report closing errors if they occur.
var err, err2
try {
var ret = fs.fchmodSync(fd, mode)
} catch (er) {
err = er
}
try {
fs.closeSync(fd)
} catch (er) {
err2 = er
}
if (err || err2) throw (err || err2)
return ret
}
}
// lutimes implementation, or no-op
if (!fs.lutimes) {
if (constants.hasOwnProperty("O_SYMLINK")) {
fs.lutimes = function (path, at, mt, cb) {
fs.open(path, constants.O_SYMLINK, function (er, fd) {
cb = cb || noop
if (er) return cb(er)
fs.futimes(fd, at, mt, function (er) {
fs.close(fd, function (er2) {
return cb(er || er2)
})
})
})
}
fs.lutimesSync = function (path, at, mt) {
var fd = fs.openSync(path, constants.O_SYMLINK)
, err
, err2
, ret
try {
var ret = fs.futimesSync(fd, at, mt)
} catch (er) {
err = er
}
try {
fs.closeSync(fd)
} catch (er) {
err2 = er
}
if (err || err2) throw (err || err2)
return ret
}
} else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) {
// maybe utimensat will be bound soonish?
fs.lutimes = function (path, at, mt, cb) {
fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb)
}
fs.lutimesSync = function (path, at, mt) {
return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW)
}
} else {
fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
fs.lutimesSync = function () {}
}
}
// https://github.com/isaacs/node-graceful-fs/issues/4
// Chown should not fail on einval or eperm if non-root.
fs.chown = chownFix(fs.chown)
fs.fchown = chownFix(fs.fchown)
fs.lchown = chownFix(fs.lchown)
fs.chownSync = chownFixSync(fs.chownSync)
fs.fchownSync = chownFixSync(fs.fchownSync)
fs.lchownSync = chownFixSync(fs.lchownSync)
function chownFix (orig) {
if (!orig) return orig
return function (target, uid, gid, cb) {
return orig.call(fs, target, uid, gid, function (er, res) {
if (chownErOk(er)) er = null
cb(er, res)
})
}
}
function chownFixSync (orig) {
if (!orig) return orig
return function (target, uid, gid) {
try {
return orig.call(fs, target, uid, gid)
} catch (er) {
if (!chownErOk(er)) throw er
}
}
}
function chownErOk (er) {
// if there's no getuid, or if getuid() is something other than 0,
// and the error is EINVAL or EPERM, then just ignore it.
// This specific case is a silent failure in cp, install, tar,
// and most other unix tools that manage permissions.
// When running as root, or if other types of errors are encountered,
// then it's strict.
if (!er || (!process.getuid || process.getuid() !== 0)
&& (er.code === "EINVAL" || er.code === "EPERM")) return true
}
// if lchmod/lchown do not exist, then make them no-ops
if (!fs.lchmod) {
fs.lchmod = function (path, mode, cb) {
process.nextTick(cb)
}
fs.lchmodSync = function () {}
}
if (!fs.lchown) {
fs.lchown = function (path, uid, gid, cb) {
process.nextTick(cb)
}
fs.lchownSync = function () {}
}
// on Windows, A/V software can lock the directory, causing this
// to fail with an EACCES or EPERM if the directory contains newly
// created files. Try again on failure, for up to 1 second.
if (process.platform === "win32") {
var rename_ = fs.rename
fs.rename = function rename (from, to, cb) {
var start = Date.now()
rename_(from, to, function CB (er) {
if (er
&& (er.code === "EACCES" || er.code === "EPERM")
&& Date.now() - start < 1000) {
return rename_(from, to, CB)
}
cb(er)
})
}
}
// if read() returns EAGAIN, then just try it again.
var read = fs.read
fs.read = function (fd, buffer, offset, length, position, callback_) {
var callback
if (callback_ && typeof callback_ === 'function') {
var eagCounter = 0
callback = function (er, _, __) {
if (er && er.code === 'EAGAIN' && eagCounter < 10) {
eagCounter ++
return read.call(fs, fd, buffer, offset, length, position, callback)
}
callback_.apply(this, arguments)
}
}
return read.call(fs, fd, buffer, offset, length, position, callback)
}
var readSync = fs.readSync
fs.readSync = function (fd, buffer, offset, length, position) {
var eagCounter = 0
while (true) {
try {
return readSync.call(fs, fd, buffer, offset, length, position)
} catch (er) {
if (er.code === 'EAGAIN' && eagCounter < 10) {
eagCounter ++
continue
}
throw er
}
}
}

View File

@@ -0,0 +1,70 @@
{
"_from": "graceful-fs@~1.2.0",
"_id": "graceful-fs@1.2.3",
"_inBundle": false,
"_integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=",
"_location": "/globule/graceful-fs",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "graceful-fs@~1.2.0",
"name": "graceful-fs",
"escapedName": "graceful-fs",
"rawSpec": "~1.2.0",
"saveSpec": null,
"fetchSpec": "~1.2.0"
},
"_requiredBy": [
"/globule/glob"
],
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz",
"_shasum": "15a4806a57547cb2d2dbf27f42e89a8c3451b364",
"_spec": "graceful-fs@~1.2.0",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/globule/node_modules/glob",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me"
},
"bugs": {
"url": "https://github.com/isaacs/node-graceful-fs/issues"
},
"bundleDependencies": false,
"deprecated": "graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.",
"description": "A drop-in replacement for fs, making various improvements.",
"directories": {
"test": "test"
},
"engines": {
"node": ">=0.4.0"
},
"homepage": "https://github.com/isaacs/node-graceful-fs#readme",
"keywords": [
"fs",
"module",
"reading",
"retry",
"retries",
"queue",
"error",
"errors",
"handling",
"EMFILE",
"EAGAIN",
"EINVAL",
"EPERM",
"EACCESS"
],
"license": "BSD",
"main": "graceful-fs.js",
"name": "graceful-fs",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-graceful-fs.git"
},
"scripts": {
"test": "tap test/*.js"
},
"version": "1.2.3"
}

View File

@@ -0,0 +1,46 @@
var test = require('tap').test
var fs = require('../graceful-fs.js')
test('graceful fs is not fs', function (t) {
t.notEqual(fs, require('fs'))
t.end()
})
test('open an existing file works', function (t) {
var start = fs._curOpen
var fd = fs.openSync(__filename, 'r')
t.equal(fs._curOpen, start + 1)
fs.closeSync(fd)
t.equal(fs._curOpen, start)
fs.open(__filename, 'r', function (er, fd) {
if (er) throw er
t.equal(fs._curOpen, start + 1)
fs.close(fd, function (er) {
if (er) throw er
t.equal(fs._curOpen, start)
t.end()
})
})
})
test('open a non-existing file throws', function (t) {
var start = fs._curOpen
var er
try {
var fd = fs.openSync('this file does not exist', 'r')
} catch (x) {
er = x
}
t.ok(er, 'should throw')
t.notOk(fd, 'should not get an fd')
t.equal(er.code, 'ENOENT')
t.equal(fs._curOpen, start)
fs.open('neither does this file', 'r', function (er, fd) {
t.ok(er, 'should throw')
t.notOk(fd, 'should not get an fd')
t.equal(er.code, 'ENOENT')
t.equal(fs._curOpen, start)
t.end()
})
})

View File

@@ -0,0 +1,158 @@
var test = require('tap').test
// simulated ulimit
// this is like graceful-fs, but in reverse
var fs_ = require('fs')
var fs = require('../graceful-fs.js')
var files = fs.readdirSync(__dirname)
// Ok, no more actual file reading!
var fds = 0
var nextFd = 60
var limit = 8
fs_.open = function (path, flags, mode, cb) {
process.nextTick(function() {
++fds
if (fds >= limit) {
--fds
var er = new Error('EMFILE Curses!')
er.code = 'EMFILE'
er.path = path
return cb(er)
} else {
cb(null, nextFd++)
}
})
}
fs_.openSync = function (path, flags, mode) {
if (fds >= limit) {
var er = new Error('EMFILE Curses!')
er.code = 'EMFILE'
er.path = path
throw er
} else {
++fds
return nextFd++
}
}
fs_.close = function (fd, cb) {
process.nextTick(function () {
--fds
cb()
})
}
fs_.closeSync = function (fd) {
--fds
}
fs_.readdir = function (path, cb) {
process.nextTick(function() {
if (fds >= limit) {
var er = new Error('EMFILE Curses!')
er.code = 'EMFILE'
er.path = path
return cb(er)
} else {
++fds
process.nextTick(function () {
--fds
cb(null, [__filename, "some-other-file.js"])
})
}
})
}
fs_.readdirSync = function (path) {
if (fds >= limit) {
var er = new Error('EMFILE Curses!')
er.code = 'EMFILE'
er.path = path
throw er
} else {
return [__filename, "some-other-file.js"]
}
}
test('open emfile autoreduce', function (t) {
fs.MIN_MAX_OPEN = 4
t.equal(fs.MAX_OPEN, 1024)
var max = 12
for (var i = 0; i < max; i++) {
fs.open(__filename, 'r', next(i))
}
var phase = 0
var expect =
[ [ 0, 60, null, 1024, 4, 12, 1 ],
[ 1, 61, null, 1024, 4, 12, 2 ],
[ 2, 62, null, 1024, 4, 12, 3 ],
[ 3, 63, null, 1024, 4, 12, 4 ],
[ 4, 64, null, 1024, 4, 12, 5 ],
[ 5, 65, null, 1024, 4, 12, 6 ],
[ 6, 66, null, 1024, 4, 12, 7 ],
[ 7, 67, null, 6, 4, 5, 1 ],
[ 8, 68, null, 6, 4, 5, 2 ],
[ 9, 69, null, 6, 4, 5, 3 ],
[ 10, 70, null, 6, 4, 5, 4 ],
[ 11, 71, null, 6, 4, 5, 5 ] ]
var actual = []
function next (i) { return function (er, fd) {
if (er)
throw er
actual.push([i, fd, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds])
if (i === max - 1) {
t.same(actual, expect)
t.ok(fs.MAX_OPEN < limit)
t.end()
}
fs.close(fd)
} }
})
test('readdir emfile autoreduce', function (t) {
fs.MAX_OPEN = 1024
var max = 12
for (var i = 0; i < max; i ++) {
fs.readdir(__dirname, next(i))
}
var expect =
[ [0,[__filename,"some-other-file.js"],null,7,4,7,7],
[1,[__filename,"some-other-file.js"],null,7,4,7,6],
[2,[__filename,"some-other-file.js"],null,7,4,7,5],
[3,[__filename,"some-other-file.js"],null,7,4,7,4],
[4,[__filename,"some-other-file.js"],null,7,4,7,3],
[5,[__filename,"some-other-file.js"],null,7,4,6,2],
[6,[__filename,"some-other-file.js"],null,7,4,5,1],
[7,[__filename,"some-other-file.js"],null,7,4,4,0],
[8,[__filename,"some-other-file.js"],null,7,4,3,3],
[9,[__filename,"some-other-file.js"],null,7,4,2,2],
[10,[__filename,"some-other-file.js"],null,7,4,1,1],
[11,[__filename,"some-other-file.js"],null,7,4,0,0] ]
var actual = []
function next (i) { return function (er, files) {
if (er)
throw er
var line = [i, files, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds ]
actual.push(line)
if (i === max - 1) {
t.ok(fs.MAX_OPEN < limit)
t.same(actual, expect)
t.end()
}
} }
})

View File

@@ -0,0 +1,16 @@
The ISC License
Copyright (c) Isaac Z. Schlueter
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,51 @@
A dead simple way to do inheritance in JS.
var inherits = require("inherits")
function Animal () {
this.alive = true
}
Animal.prototype.say = function (what) {
console.log(what)
}
inherits(Dog, Animal)
function Dog () {
Dog.super.apply(this)
}
Dog.prototype.sniff = function () {
this.say("sniff sniff")
}
Dog.prototype.bark = function () {
this.say("woof woof")
}
inherits(Chihuahua, Dog)
function Chihuahua () {
Chihuahua.super.apply(this)
}
Chihuahua.prototype.bark = function () {
this.say("yip yip")
}
// also works
function Cat () {
Cat.super.apply(this)
}
Cat.prototype.hiss = function () {
this.say("CHSKKSS!!")
}
inherits(Cat, Animal, {
meow: function () { this.say("miao miao") }
})
Cat.prototype.purr = function () {
this.say("purr purr")
}
var c = new Chihuahua
assert(c instanceof Chihuahua)
assert(c instanceof Dog)
assert(c instanceof Animal)
The actual function is laughably small. 10-lines small.

View File

@@ -0,0 +1,29 @@
module.exports = inherits
function inherits (c, p, proto) {
proto = proto || {}
var e = {}
;[c.prototype, proto].forEach(function (s) {
Object.getOwnPropertyNames(s).forEach(function (k) {
e[k] = Object.getOwnPropertyDescriptor(s, k)
})
})
c.prototype = Object.create(p.prototype, e)
c.super = p
}
//function Child () {
// Child.super.call(this)
// console.error([this
// ,this.constructor
// ,this.constructor === Child
// ,this.constructor.super === Parent
// ,Object.getPrototypeOf(this) === Child.prototype
// ,Object.getPrototypeOf(Object.getPrototypeOf(this))
// === Parent.prototype
// ,this instanceof Child
// ,this instanceof Parent])
//}
//function Parent () {}
//inherits(Child, Parent)
//new Child

View File

@@ -0,0 +1,51 @@
{
"_from": "inherits@1",
"_id": "inherits@1.0.2",
"_inBundle": false,
"_integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=",
"_location": "/globule/inherits",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "inherits@1",
"name": "inherits",
"escapedName": "inherits",
"rawSpec": "1",
"saveSpec": null,
"fetchSpec": "1"
},
"_requiredBy": [
"/globule/glob"
],
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz",
"_shasum": "ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b",
"_spec": "inherits@1",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/globule/node_modules/glob",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"bugs": {
"url": "https://github.com/isaacs/inherits/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "A tiny simple way to do classic inheritance in js",
"homepage": "https://github.com/isaacs/inherits#readme",
"keywords": [
"inheritance",
"class",
"klass",
"oop",
"object-oriented"
],
"main": "./inherits.js",
"name": "inherits",
"repository": {
"type": "git",
"url": "git+https://github.com/isaacs/inherits.git"
},
"version": "1.0.2"
}

View File

@@ -0,0 +1,22 @@
Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
Based on Underscore.js 1.4.3, copyright 2009-2013 Jeremy Ashkenas,
DocumentCloud Inc. <http://underscorejs.org/>
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.

View File

@@ -0,0 +1,128 @@
# Lo-Dash v1.0.2
A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features).
## Download
* Lo-Dash builds (for modern environments):<br>
[Development](https://raw.github.com/lodash/lodash/v1.0.2/dist/lodash.js) and
[Production](https://raw.github.com/lodash/lodash/v1.0.2/dist/lodash.min.js)
* Lo-Dash compatibility builds (for legacy and modern environments):<br>
[Development](https://raw.github.com/lodash/lodash/v1.0.2/dist/lodash.compat.js) and
[Production](https://raw.github.com/lodash/lodash/v1.0.2/dist/lodash.compat.min.js)
* Underscore compatibility builds:<br>
[Development](https://raw.github.com/lodash/lodash/v1.0.2/dist/lodash.underscore.js) and
[Production](https://raw.github.com/lodash/lodash/v1.0.2/dist/lodash.underscore.min.js)
* For optimal file size, [create a custom build](http://lodash.com/custom-builds) with only the features you need
## Dive in
Weve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests).
For a list of upcoming features, check out our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap).
The full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog).
## Installation and usage
In browsers:
```html
<script src="lodash.js"></script>
```
Using [`npm`](http://npmjs.org/):
```bash
npm install lodash
npm install -g lodash
npm link lodash
```
To avoid potential issues, update `npm` before installing Lo-Dash:
```bash
npm install npm -g
```
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
```js
var _ = require('lodash');
// or as a drop-in replacement for Underscore
var _ = require('lodash/lodash.underscore');
```
**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projects root directory before requiring it.
In [RingoJS v0.7.0-](http://ringojs.org/):
```js
var _ = require('lodash')._;
```
In [Rhino](http://www.mozilla.org/rhino/):
```js
load('lodash.js');
```
In an AMD loader like [RequireJS](http://requirejs.org/):
```js
require({
'paths': {
'underscore': 'path/to/lodash'
}
},
['underscore'], function(_) {
console.log(_.VERSION);
});
```
## Resources
For more information check out these articles, screencasts, and other videos over Lo-Dash:
* Posts
- [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
* Videos
- [Introducing Lo-Dash](https://vimeo.com/44154599)
- [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
- [Lo-Dashs origin and why its a better utility belt](https://vimeo.com/44154600)
- [Unit testing in Lo-Dash](https://vimeo.com/45865290)
- [Lo-Dashs approach to native method use](https://vimeo.com/48576012)
- [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk)
## Features
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
* [_(…)](http://lodash.com/docs#_) supports intuitive chaining
* [_.at](http://lodash.com/docs#at) for cherry-picking collection values
* [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods
* [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays and objects
* [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an objects own and inherited properties
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an objects own properties
* [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
* [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)
* [_.partial](http://lodash.com/docs#partial) and [_.partialRight](http://lodash.com/docs#partialRight) for partial application without `this` binding
* [_.template](http://lodash.com/docs#template) supports [*“imports”* options](http://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* [_.where](http://lodash.com/docs#where) supports deep object comparisons
* [_.clone](http://lodash.com/docs#clone), [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick),
[and more…](http://lodash.com/docs "_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept `callback` and `thisArg` arguments
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
[and more…](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings
* [_.filter](http://lodash.com/docs#filter), [_.find](http://lodash.com/docs#find), [_.map](http://lodash.com/docs#map),
[and more…](http://lodash.com/docs "_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* and *“_.where”* `callback` shorthands
## Support
Lo-Dash has been tested in at least Chrome 5~24, Firefox 1~18, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.20, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
/**
* @license
* Lo-Dash 1.0.2 (Custom Build) lodash.com/license
* Build: `lodash -o ./dist/lodash.compat.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(n,t){function r(n){return n&&typeof n=="object"&&n.__wrapped__?n:this instanceof r?(this.__wrapped__=n,void 0):new r(n)}function e(n,t,r){t||(t=0);var e=n.length,u=e-t>=(r||at);if(u){var o={};for(r=t-1;++r<e;){var i=n[r]+"";(St.call(o,i)?o[i]:o[i]=[]).push(n[r])}}return function(r){if(u){var e=r+"";return St.call(o,e)&&-1<z(o[e],r)}return-1<z(n,r,t)}}function u(n){return n.charCodeAt(0)}function o(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
}return r<e?-1:1}function i(n,t,r,e){function u(){var a=arguments,c=i?this:t;return o||(n=t[f]),r.length&&(a=a.length?(a=v(a),e?a.concat(r):r.concat(a)):r),this instanceof u?(s.prototype=n.prototype,c=new s,s.prototype=W,a=n.apply(c,a),x(a)?a:c):n.apply(c,a)}var o=w(n),i=!r,f=t;return i&&(r=t),o||(t=n),u}function f(n,t,r){if(n==W)return G;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=vr(n);return function(t){for(var r=u.length,e=X;r--&&(e=j(t[u[r]],n[u[r]],ft)););return e
}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function a(){for(var n,t={e:tt,f:rt,g:Jt,i:Wt,j:Zt,k:jt,b:"l(n)",c:"",h:"",l:"",m:Q},r=0;n=arguments[r];r++)for(var e in n)t[e]=n[e];if(n=t.a,t.d=/^[^,]+/.exec(n)[0],r="var j,n="+t.d+",u=n;if(!n)return u;"+t.l+";",t.b?(r+="var o=n.length;j=-1;if("+t.b+"){",t.j&&(r+="if(m(n)){n=n.split('')}"),r+="while(++j<o){"+t.h+"}}else{"):t.i&&(r+="var o=n.length;j=-1;if(o&&k(n)){while(++j<o){j+='';"+t.h+"}}else{"),t.f&&(r+="var v=typeof n=='function';"),t.g&&t.m?(r+="var s=-1,t=r[typeof n]?p(n):[],o=t.length;while(++s<o){j=t[s];",t.f&&(r+="if(!(v&&j=='prototype')){"),r+=t.h+"",t.f&&(r+="}")):(r+="for(j in n){",(t.f||t.m)&&(r+="if(",t.f&&(r+="!(v&&j=='prototype')"),t.f&&t.m&&(r+="&&"),t.m&&(r+="i.call(n,j)"),r+="){"),r+=t.h+";",(t.f||t.m)&&(r+="}")),r+="}",t.e)for(r+="var g=n.constructor;",e=0;7>e;e++)r+="j='"+t.k[e]+"';if(","constructor"==t.k[e]&&(r+="!(g&&g.prototype===n)&&"),r+="i.call(n,j)){"+t.h+"}";
return(t.b||t.i)&&(r+="}"),r+=t.c+";return u",Function("f,i,k,l,m,r,p","return function("+n+"){"+r+"}")(f,St,y,sr,A,ur,Ft)}function c(n){return"\\"+or[n]}function l(n){return gr[n]}function p(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}function s(){}function v(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function g(n){return yr[n]}function y(n){return kt.call(n)==Bt}function h(n){var t=X;if(!n||typeof n!="object"||y(n))return t;
var r=n.constructor;return!w(r)&&(!nr||!p(n))||r instanceof r?et?(lr(n,function(n,r,e){return t=!St.call(e,r),X}),t===X):(lr(n,function(n,r){t=r}),t===X||St.call(n,t)):t}function m(n){var t=[];return pr(n,function(n,r){t.push(r)}),t}function d(n,r,e,u,o,i){var a=n;if(typeof r=="function"&&(u=e,e=r,r=X),typeof e=="function"){e=typeof u=="undefined"?e:f(e,u,1);var a=e(a),c=typeof a!="undefined";c||(a=n)}if(u=x(a)){var l=kt.call(a);if(!rr[l]||nr&&p(a))return a;var s=sr(a)}if(!u||!r)return u&&!c?s?v(a):hr({},a):a;
switch(u=er[l],l){case Pt:case zt:return c?a:new u(+a);case Ct:case Ut:return c?a:new u(a);case Lt:return c?a:u(a.source,gt.exec(a))}for(o||(o=[]),i||(i=[]),l=o.length;l--;)if(o[l]==n)return i[l];return c||(a=s?u(a.length):{},s&&(St.call(n,"index")&&(a.index=n.index),St.call(n,"input")&&(a.input=n.input))),o.push(n),i.push(a),(s?$:pr)(c?a:n,function(n,u){a[u]=d(n,r,e,t,o,i)}),a}function _(n){var t=[];return lr(n,function(n,r){w(n)&&t.push(r)}),t.sort()}function b(n){for(var t=-1,r=vr(n),e=r.length,u={};++t<e;){var o=r[t];
u[n[o]]=o}return u}function j(n,t,r,e,u,o){var i=r===ft;if(r&&!i){r=typeof e=="undefined"?r:f(r,e,2);var a=r(n,t);if(typeof a!="undefined")return!!a}if(n===t)return 0!==n||1/n==1/t;var c=typeof n,l=typeof t;if(n===n&&(!n||"function"!=c&&"object"!=c)&&(!t||"function"!=l&&"object"!=l))return X;if(n==W||t==W)return n===t;if(l=kt.call(n),c=kt.call(t),l==Bt&&(l=Kt),c==Bt&&(c=Kt),l!=c)return X;switch(l){case Pt:case zt:return+n==+t;case Ct:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Lt:case Ut:return n==t+""
}if(c=l==Mt,!c){if(n.__wrapped__||t.__wrapped__)return j(n.__wrapped__||n,t.__wrapped__||t,r,e,u,o);if(l!=Kt||nr&&(p(n)||p(t)))return X;var l=!Xt&&y(n)?Object:n.constructor,s=!Xt&&y(t)?Object:t.constructor;if(l!=s&&(!w(l)||!(l instanceof l&&w(s)&&s instanceof s)))return X}for(u||(u=[]),o||(o=[]),l=u.length;l--;)if(u[l]==n)return o[l]==t;var v=0,a=Q;if(u.push(n),o.push(t),c){if(l=n.length,v=t.length,a=v==n.length,!a&&!i)return a;for(;v--;)if(c=l,s=t[v],i)for(;c--&&!(a=j(n[c],s,r,e,u,o)););else if(!(a=j(n[v],s,r,e,u,o)))break;
return a}return lr(t,function(t,i,f){return St.call(f,i)?(v++,a=St.call(n,i)&&j(n[i],t,r,e,u,o)):void 0}),a&&!i&&lr(n,function(n,t,r){return St.call(r,t)?a=-1<--v:void 0}),a}function w(n){return typeof n=="function"}function x(n){return n?ur[typeof n]:X}function O(n){return typeof n=="number"||kt.call(n)==Ct}function A(n){return typeof n=="string"||kt.call(n)==Ut}function S(n,t,r){var e=arguments,u=0,o=2;if(!x(n))return n;if(r===ft)var i=e[3],a=e[4],c=e[5];else a=[],c=[],typeof r!="number"&&(o=e.length),3<o&&"function"==typeof e[o-2]?i=f(e[--o-1],e[o--],2):2<o&&"function"==typeof e[o-1]&&(i=e[--o]);
for(;++u<o;)(sr(e[u])?$:pr)(e[u],function(t,r){var e,u,o=t,f=n[r];if(t&&((u=sr(t))||dr(t))){for(o=a.length;o--;)if(e=a[o]==t){f=c[o];break}e||(f=u?sr(f)?f:[]:dr(f)?f:{},i&&(o=i(f,t),typeof o!="undefined"&&(f=o)),a.push(t),c.push(f),i||(f=S(f,t,ft,i,a,c)))}else i&&(o=i(f,t),typeof o=="undefined"&&(o=t)),typeof o!="undefined"&&(f=o);n[r]=f});return n}function E(n){for(var t=-1,r=vr(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function k(n,t,r){var e=-1,u=n?n.length:0,o=X;return r=(0>r?qt(0,u+r):r)||0,typeof u=="number"?o=-1<(A(n)?n.indexOf(t,r):z(n,t,r)):cr(n,function(n){return++e<r?void 0:!(o=n===t)
}),o}function I(n,t,r){var e=Q;if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u&&(e=!!t(n[r],r,n)););}else cr(n,function(n,r,u){return e=!!t(n,r,u)});return e}function N(n,t,r){var e=[];if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u;){var o=n[r];t(o,r,n)&&e.push(o)}}else cr(n,function(n,r,u){t(n,r,u)&&e.push(n)});return e}function R(n,t,r){var e;return t=f(t,r),$(n,function(n,r,u){return t(n,r,u)?(e=n,X):void 0}),e}function $(n,t,r){if(t&&typeof r=="undefined"&&sr(n)){r=-1;for(var e=n.length;++r<e&&t(n[r],r,n)!==X;);}else cr(n,t,r);
return n}function F(n,t,r){var e=-1,u=n?n.length:0,o=Array(typeof u=="number"?u:0);if(t=f(t,r),sr(n))for(;++e<u;)o[e]=t(n[e],e,n);else cr(n,function(n,r,u){o[++e]=t(n,r,u)});return o}function q(n,t,r){var e=-1/0,o=e;if(!t&&sr(n)){r=-1;for(var i=n.length;++r<i;){var a=n[r];a>o&&(o=a)}}else t=!t&&A(n)?u:f(t,r),cr(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function D(n,t,r,e){var u=3>arguments.length;if(t=f(t,e,4),sr(n)){var o=-1,i=n.length;for(u&&(r=n[++o]);++o<i;)r=t(r,n[o],o,n)}else cr(n,function(n,e,o){r=u?(u=X,n):t(r,n,e,o)
});return r}function T(n,t,r,e){var u=n,o=n?n.length:0,i=3>arguments.length;if(typeof o!="number")var a=vr(n),o=a.length;else Zt&&A(n)&&(u=n.split(""));return t=f(t,e,4),$(n,function(n,e,f){e=a?a[--o]:--o,r=i?(i=X,u[e]):t(r,u[e],e,f)}),r}function B(n,t,r){var e;if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u&&!(e=t(n[r],r,n)););}else cr(n,function(n,r,u){return!(e=t(n,r,u))});return!!e}function M(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=-1;for(t=f(t,r);++o<u&&t(n[o],o,n);)e++
}else if(e=t,e==W||r)return n[0];return v(n,0,Dt(qt(0,e),u))}}function P(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];sr(o)?Et.apply(u,t?o:P(o)):u.push(o)}return u}function z(n,t,r){var e=-1,u=n?n.length:0;if(typeof r=="number")e=(0>r?qt(0,u+r):r||0)-1;else if(r)return e=K(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function C(n,t,r){if(typeof t!="number"&&t!=W){var e=0,u=-1,o=n?n.length:0;for(t=f(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==W||r?1:qt(0,t);return v(n,e)}function K(n,t,r,e){var u=0,o=n?n.length:u;
for(r=r?f(r,e,1):G,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function L(n,t,r,e){var u=-1,o=n?n.length:0,i=[],a=i;typeof t=="function"&&(e=r,r=t,t=X);var c=!t&&75<=o;if(c)var l={};for(r&&(a=[],r=f(r,e));++u<o;){e=n[u];var p=r?r(e,u,n):e;if(c)var s=p+"",s=St.call(l,s)?!(a=l[s]):a=l[s]=[];(t?!u||a[a.length-1]!==p:s||0>z(a,p))&&((r||c)&&a.push(p),i.push(e))}return i}function U(n,t){return Ht||It&&2<arguments.length?It.call.apply(It,arguments):i(n,t,v(arguments,2))}function V(n){var r=v(arguments,1);
return setTimeout(function(){n.apply(t,r)},1)}function G(n){return n}function H(n){$(_(n),function(t){var e=r[t]=n[t];r.prototype[t]=function(){var n=[this.__wrapped__];return Et.apply(n,arguments),new r(e.apply(r,n))}})}function J(){return this.__wrapped__}var Q=!0,W=null,X=!1,Y=typeof exports=="object"&&exports,Z=typeof module=="object"&&module&&module.exports==Y&&module,nt=typeof global=="object"&&global;nt.global===nt&&(n=nt);var tt,rt,et,ut=[],ot={},it=0,ft=ot,at=30,ct=n._,lt=/&(?:amp|lt|gt|quot|#39);/g,pt=/\b__p\+='';/g,st=/\b(__p\+=)''\+/g,vt=/(__e\(.*?\)|\b__t\))\+'';/g,gt=/\w*$/,yt=RegExp("^"+(ot.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),ht=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,mt=/<%=([\s\S]+?)%>/g,dt=/($^)/,_t=/[&<>"']/g,bt=/['\n\r\t\u2028\u2029\\]/g,jt="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),wt=Math.ceil,xt=ut.concat,Ot=Math.floor,At=yt.test(At=Object.getPrototypeOf)&&At,St=ot.hasOwnProperty,Et=ut.push,kt=ot.toString,It=yt.test(It=v.bind)&&It,Nt=yt.test(Nt=Array.isArray)&&Nt,Rt=n.isFinite,$t=n.isNaN,Ft=yt.test(Ft=Object.keys)&&Ft,qt=Math.max,Dt=Math.min,Tt=Math.random,Bt="[object Arguments]",Mt="[object Array]",Pt="[object Boolean]",zt="[object Date]",Ct="[object Number]",Kt="[object Object]",Lt="[object RegExp]",Ut="[object String]",Vt=!!n.attachEvent,Gt=It&&!/\n|true/.test(It+Vt),Ht=It&&!Gt,Jt=Ft&&(Vt||Gt),Qt=(Qt={0:1,length:1},ut.splice.call(Qt,0,1),Qt[0]),Wt=Q;
(function(){function n(){this.x=1}var t=[];n.prototype={valueOf:1,y:1};for(var r in new n)t.push(r);for(r in arguments)Wt=!r;tt=!/valueOf/.test(t),rt=n.propertyIsEnumerable("prototype"),et="x"!=t[0]})(1);var Xt=arguments.constructor==Object,Yt=!y(arguments),Zt="xx"!="x"[0]+Object("x")[0];try{var nr=kt.call(document)==Kt&&!({toString:0}+"")}catch(tr){}var rr={"[object Function]":X};rr[Bt]=rr[Mt]=rr[Pt]=rr[zt]=rr[Ct]=rr[Kt]=rr[Lt]=rr[Ut]=Q;var er={};er[Mt]=Array,er[Pt]=Boolean,er[zt]=Date,er[Kt]=Object,er[Ct]=Number,er[Lt]=RegExp,er[Ut]=String;
var ur={"boolean":X,"function":Q,object:Q,number:X,string:X,undefined:X},or={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};r.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:mt,variable:"",imports:{_:r}};var ir={a:"q,w,h",l:"var a=arguments,b=0,c=typeof h=='number'?2:a.length;while(++b<c){n=a[b];if(n&&r[typeof n]){",h:"if(typeof u[j]=='undefined')u[j]=n[j]",c:"}}"},fr={a:"e,d,x",l:"d=d&&typeof x=='undefined'?d:f(d,x)",b:"typeof o=='number'",h:"if(d(n[j],j,e)===false)return u"},ar={l:"if(!r[typeof n])return u;"+fr.l,b:X},cr=a(fr);
Yt&&(y=function(n){return n?St.call(n,"callee"):X});var lr=a(fr,ar,{m:X}),pr=a(fr,ar),sr=Nt||function(n){return Xt&&n instanceof Array||kt.call(n)==Mt},vr=Ft?function(n){return x(n)?rt&&typeof n=="function"||Wt&&n.length&&y(n)?m(n):Ft(n):[]}:m,gr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},yr=b(gr),hr=a(ir,{l:ir.l.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=f(a[--c-1],a[c--],2);}else if(c>2&&typeof a[c-1]=='function'){d=a[--c];}"),h:"u[j]=d?d(u[j],n[j]):n[j]"}),mr=a(ir);
w(/x/)&&(w=function(n){return n instanceof Function||"[object Function]"==kt.call(n)});var dr=At?function(n){if(!n||typeof n!="object")return X;var t=n.valueOf,r=typeof t=="function"&&(r=At(t))&&At(r);return r?n==r||At(n)==r&&!y(n):h(n)}:h,_r=F,br=N;Gt&&Z&&typeof setImmediate=="function"&&(V=U(setImmediate,n)),r.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},r.assign=hr,r.at=function(n){var t=-1,r=xt.apply(ut,v(arguments,1)),e=r.length,u=Array(e);for(Zt&&A(n)&&(n=n.split(""));++t<e;)u[t]=n[r[t]];
return u},r.bind=U,r.bindAll=function(n){for(var t=xt.apply(ut,arguments),r=1<t.length?0:(t=_(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=U(n[u],n)}return n},r.bindKey=function(n,t){return i(n,t,v(arguments,2))},r.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},r.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},r.countBy=function(n,t,r){var e={};return t=f(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",St.call(e,r)?e[r]++:e[r]=1
}),e},r.debounce=function(n,t,r){function e(){f=W,r||(o=n.apply(i,u))}var u,o,i,f;return function(){var a=r&&!f;return u=arguments,i=this,clearTimeout(f),f=setTimeout(e,t),a&&(o=n.apply(i,u)),o}},r.defaults=mr,r.defer=V,r.delay=function(n,r){var e=v(arguments,2);return setTimeout(function(){n.apply(t,e)},r)},r.difference=function(n){for(var t=-1,r=n?n.length:0,u=xt.apply(ut,arguments),u=e(u,r),o=[];++t<r;){var i=n[t];u(i)||o.push(i)}return o},r.filter=N,r.flatten=P,r.forEach=$,r.forIn=lr,r.forOwn=pr,r.functions=_,r.groupBy=function(n,t,r){var e={};
return t=f(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",(St.call(e,r)?e[r]:e[r]=[]).push(n)}),e},r.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=u;for(t=f(t,r);o--&&t(n[o],o,n);)e++}else e=t==W||r?1:t||e;return v(n,0,Dt(qt(0,u-e),u))},r.intersection=function(n){var t=arguments,r=t.length,u={0:{}},o=-1,i=n?n.length:0,f=100<=i,a=[],c=a;n:for(;++o<i;){var l=n[o];if(f)var p=l+"",p=St.call(u[0],p)?!(c=u[0][p]):c=u[0][p]=[];if(p||0>z(c,l)){f&&c.push(l);for(var s=r;--s;)if(!(u[s]||(u[s]=e(t[s],0,100)))(l))continue n;
a.push(l)}}return a},r.invert=b,r.invoke=function(n,t){var r=v(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);return $(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},r.keys=vr,r.map=F,r.max=q,r.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";return St.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},r.merge=S,r.min=function(n,t,r){var e=1/0,o=e;if(!t&&sr(n)){r=-1;for(var i=n.length;++r<i;){var a=n[r];a<o&&(o=a)
}}else t=!t&&A(n)?u:f(t,r),cr(n,function(n,r,u){r=t(n,r,u),r<e&&(e=r,o=n)});return o},r.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]}return u},r.omit=function(n,t,r){var e=typeof t=="function",u={};if(e)t=f(t,r);else var o=xt.apply(ut,arguments);return lr(n,function(n,r,i){(e?!t(n,r,i):0>z(o,r,1))&&(u[r]=n)}),u},r.once=function(n){var t,r;return function(){return t?r:(t=Q,r=n.apply(this,arguments),n=W,r)}},r.pairs=function(n){for(var t=-1,r=vr(n),e=r.length,u=Array(e);++t<e;){var o=r[t];
u[t]=[o,n[o]]}return u},r.partial=function(n){return i(n,v(arguments,1))},r.partialRight=function(n){return i(n,v(arguments,1),W,ft)},r.pick=function(n,t,r){var e={};if(typeof t!="function")for(var u=0,o=xt.apply(ut,arguments),i=x(n)?o.length:0;++u<i;){var a=o[u];a in n&&(e[a]=n[a])}else t=f(t,r),lr(n,function(n,r,u){t(n,r,u)&&(e[r]=n)});return e},r.pluck=_r,r.range=function(n,t,r){n=+n||0,r=+r||1,t==W&&(t=n,n=0);var e=-1;t=qt(0,wt((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},r.reject=function(n,t,r){return t=f(t,r),N(n,function(n,r,e){return!t(n,r,e)
})},r.rest=C,r.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r=Ot(Tt()*(++t+1));e[t]=e[r],e[r]=n}),e},r.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=f(t,r),$(n,function(n,r,u){i[++e]={a:t(n,r,u),b:e,c:n}}),u=i.length,i.sort(o);u--;)i[u]=i[u].c;return i},r.tap=function(n,t){return t(n),n},r.throttle=function(n,t){function r(){f=new Date,i=W,u=n.apply(o,e)}var e,u,o,i,f=0;return function(){var a=new Date,c=t-(a-f);
return e=arguments,o=this,0<c?i||(i=setTimeout(r,c)):(clearTimeout(i),i=W,f=a,u=n.apply(o,e)),u}},r.times=function(n,t,r){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=t.call(r,e);return u},r.toArray=function(n){return n&&typeof n.length=="number"?Zt&&A(n)?n.split(""):v(n):E(n)},r.union=function(){return L(xt.apply(ut,arguments))},r.uniq=L,r.values=E,r.where=br,r.without=function(n){for(var t=-1,r=n?n.length:0,u=e(arguments,1),o=[];++t<r;){var i=n[t];u(i)||o.push(i)}return o},r.wrap=function(n,t){return function(){var r=[n];
return Et.apply(r,arguments),t.apply(this,r)}},r.zip=function(n){for(var t=-1,r=n?q(_r(arguments,"length")):0,e=Array(r);++t<r;)e[t]=_r(arguments,t);return e},r.collect=F,r.drop=C,r.each=$,r.extend=hr,r.methods=_,r.select=N,r.tail=C,r.unique=L,H(r),r.clone=d,r.cloneDeep=function(n,t,r){return d(n,Q,t,r)},r.contains=k,r.escape=function(n){return n==W?"":(n+"").replace(_t,l)},r.every=I,r.find=R,r.has=function(n,t){return n?St.call(n,t):X},r.identity=G,r.indexOf=z,r.isArguments=y,r.isArray=sr,r.isBoolean=function(n){return n===Q||n===X||kt.call(n)==Pt
},r.isDate=function(n){return n instanceof Date||kt.call(n)==zt},r.isElement=function(n){return n?1===n.nodeType:X},r.isEmpty=function(n){var t=Q;if(!n)return t;var r=kt.call(n),e=n.length;return r==Mt||r==Ut||r==Bt||Yt&&y(n)||r==Kt&&typeof e=="number"&&w(n.splice)?!e:(pr(n,function(){return t=X}),t)},r.isEqual=j,r.isFinite=function(n){return Rt(n)&&!$t(parseFloat(n))},r.isFunction=w,r.isNaN=function(n){return O(n)&&n!=+n},r.isNull=function(n){return n===W},r.isNumber=O,r.isObject=x,r.isPlainObject=dr,r.isRegExp=function(n){return n instanceof RegExp||kt.call(n)==Lt
},r.isString=A,r.isUndefined=function(n){return typeof n=="undefined"},r.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?qt(0,e+r):Dt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},r.mixin=H,r.noConflict=function(){return n._=ct,this},r.random=function(n,t){return n==W&&t==W&&(t=1),n=+n||0,t==W&&(t=n,n=0),n+Ot(Tt()*((+t||0)-n+1))},r.reduce=D,r.reduceRight=T,r.result=function(n,r){var e=n?n[r]:t;return w(e)?n[r]():e},r.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:vr(n).length
},r.some=B,r.sortedIndex=K,r.template=function(n,e,u){var o=r.templateSettings;n||(n=""),u=mr({},u,o);var i,f=mr({},u.imports,o.imports),o=vr(f),f=E(f),a=0,l=u.interpolate||dt,p="__p+='";n.replace(RegExp((u.escape||dt).source+"|"+l.source+"|"+(l===mt?ht:dt).source+"|"+(u.evaluate||dt).source+"|$","g"),function(t,r,e,u,o,f){return e||(e=u),p+=n.slice(a,f).replace(bt,c),r&&(p+="'+__e("+r+")+'"),o&&(i=Q,p+="';"+o+";__p+='"),e&&(p+="'+((__t=("+e+"))==null?'':__t)+'"),a=f+t.length,t}),p+="';\n",l=u=u.variable,l||(u="obj",p="with("+u+"){"+p+"}"),p=(i?p.replace(pt,""):p).replace(st,"$1").replace(vt,"$1;"),p="function("+u+"){"+(l?"":u+"||("+u+"={});")+"var __t,__p='',__e=_.escape"+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+p+"return __p}";
try{var s=Function(o,"return "+p).apply(t,f)}catch(v){throw v.source=p,v}return e?s(e):(s.source=p,s)},r.unescape=function(n){return n==W?"":(n+"").replace(lt,g)},r.uniqueId=function(n){var t=++it;return(n==W?"":n+"")+t},r.all=I,r.any=B,r.detect=R,r.foldl=D,r.foldr=T,r.include=k,r.inject=D,pr(r,function(n,t){r.prototype[t]||(r.prototype[t]=function(){var t=[this.__wrapped__];return Et.apply(t,arguments),n.apply(r,t)})}),r.first=M,r.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=u;
for(t=f(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==W||r)return n[u-1];return v(n,qt(0,u-e))}},r.take=M,r.head=M,pr(r,function(n,t){r.prototype[t]||(r.prototype[t]=function(t,e){var u=n(this.__wrapped__,t,e);return t==W||e&&typeof t!="function"?u:new r(u)})}),r.VERSION="1.0.2",r.prototype.toString=function(){return this.__wrapped__+""},r.prototype.value=J,r.prototype.valueOf=J,cr(["join","pop","shift"],function(n){var t=ut[n];r.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)}}),cr(["push","reverse","sort","unshift"],function(n){var t=ut[n];
r.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),cr(["concat","slice","splice"],function(n){var t=ut[n];r.prototype[n]=function(){return new r(t.apply(this.__wrapped__,arguments))}}),Qt&&cr(["pop","shift","splice"],function(n){var t=ut[n],e="splice"==n;r.prototype[n]=function(){var n=this.__wrapped__,u=t.apply(n,arguments);return 0===n.length&&delete n[0],e?new r(u):u}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=r,define(function(){return r
})):Y?Z?(Z.exports=r)._=r:Y._=r:n._=r})(this);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
/**
* @license
* Lo-Dash 1.0.2 (Custom Build) lodash.com/license
* Build: `lodash modern -o ./dist/lodash.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(n,r){function t(n){return n&&"object"==typeof n&&n.__wrapped__?n:this instanceof t?(this.__wrapped__=n,r):new t(n)}function e(n,r,t){r||(r=0);var e=n.length,u=e-r>=(t||ut);if(u)for(var a={},o=r-1;++o<e;){var i=n[o]+"";(wt.call(a,i)?a[i]:a[i]=[]).push(n[o])}return function(t){if(u){var e=t+"";return wt.call(a,e)&&sr(a[e],t)>-1}return sr(n,t,r)>-1}}function u(n){return n.charCodeAt(0)}function a(n,r){var t=n.index,e=r.index;if(n=n.criteria,r=r.criteria,n!==r){if(n>r||"undefined"==typeof n)return 1;
if(n<r||"undefined"==typeof r)return-1}return t<e?-1:1}function o(n,r,t,e){function u(){var f=arguments,l=o?this:r;if(a||(n=r[i]),t.length&&(f=f.length?(f=p(f),e?f.concat(t):t.concat(f)):t),this instanceof u){s.prototype=n.prototype,l=new s,s.prototype=null;var c=n.apply(l,f);return S(c)?c:l}return n.apply(l,f)}var a=E(n),o=!t,i=r;return o&&(t=r),a||(r=n),u}function i(n,r,t){if(null==n)return Br;var e=typeof n;if("function"!=e){if("object"!=e)return function(r){return r[n]};var u=ue(n);return function(r){for(var t=u.length,e=!1;t--&&(e=O(r[u[t]],n[u[t]],et)););return e
}}return"undefined"!=typeof r?1===t?function(t){return n.call(r,t)}:2===t?function(t,e){return n.call(r,t,e)}:4===t?function(t,e,u,a){return n.call(r,t,e,u,a)}:function(t,e,u){return n.call(r,t,e,u)}:n}function f(){for(var n,r={isKeysFast:Ut,arrays:"isArray(iterable)",bottom:"",loop:"",top:"",useHas:!0},t=0;n=arguments[t];t++)for(var e in n)r[e]=n[e];var u=r.args;r.firstArg=/^[^,]+/.exec(u)[0];var a=Function("createCallback, hasOwnProperty, isArguments, isArray, isString, objectTypes, nativeKeys","return function("+u+") {\n"+Wt(r)+"\n}");
return a(i,wt,v,ee,N,Jt,St)}function l(n){return"\\"+Qt[n]}function c(n){return ae[n]}function s(){}function p(n,r,t){r||(r=0),"undefined"==typeof t&&(t=n?n.length:0);for(var e=-1,u=t-r||0,a=Array(u<0?0:u);++e<u;)a[e]=n[r+e];return a}function g(n){return oe[n]}function v(n){return At.call(n)==Ft}function y(n){var r=!1;if(!n||"object"!=typeof n||v(n))return r;var t=n.constructor;return!E(t)||t instanceof t?(re(n,function(n,t){r=t}),r===!1||wt.call(n,r)):r}function h(n){var r=[];return te(n,function(n,t){r.push(t)
}),r}function d(n,t,e,u,a,o){var f=n;if("function"==typeof t&&(u=e,e=t,t=!1),"function"==typeof e){e="undefined"==typeof u?e:i(e,u,1),f=e(f);var l="undefined"!=typeof f;l||(f=n)}var c=S(f);if(c){var s=At.call(f);if(!Vt[s])return f;var g=ee(f)}if(!c||!t)return c&&!l?g?p(f):ie({},f):f;var v=Gt[s];switch(s){case $t:case Pt:return l?f:new v(+f);case qt:case Ct:return l?f:new v(f);case Ht:return l?f:v(f.source,ct.exec(f))}a||(a=[]),o||(o=[]);for(var y=a.length;y--;)if(a[y]==n)return o[y];return l||(f=g?v(f.length):{},g&&(wt.call(n,"index")&&(f.index=n.index),wt.call(n,"input")&&(f.input=n.input))),a.push(n),o.push(f),(g?G:te)(l?f:n,function(n,u){f[u]=d(n,t,e,r,a,o)
}),f}function m(n,r,t){return d(n,!0,r,t)}function b(n){var r=[];return re(n,function(n,t){E(n)&&r.push(t)}),r.sort()}function _(n,r){return n?wt.call(n,r):!1}function x(n){for(var r=-1,t=ue(n),e=t.length,u={};++r<e;){var a=t[r];u[n[a]]=a}return u}function w(n){return n===!0||n===!1||At.call(n)==$t}function j(n){return n instanceof Date||At.call(n)==Pt}function A(n){return n?1===n.nodeType:!1}function k(n){var r=!0;if(!n)return r;var t=At.call(n),e=n.length;return t==Nt||t==Ct||t==Ft||t==Bt&&"number"==typeof e&&E(n.splice)?!e:(te(n,function(){return r=!1
}),r)}function O(n,t,e,u,a,o){var f=e===et;if(e&&!f){e="undefined"==typeof u?e:i(e,u,2);var l=e(n,t);if("undefined"!=typeof l)return!!l}if(n===t)return 0!==n||1/n==1/t;var c=typeof n,s=typeof t;if(n===n&&(!n||"function"!=c&&"object"!=c)&&(!t||"function"!=s&&"object"!=s))return!1;if(null==n||null==t)return n===t;var p=At.call(n),g=At.call(t);if(p==Ft&&(p=Bt),g==Ft&&(g=Bt),p!=g)return!1;switch(p){case $t:case Pt:return+n==+t;case qt:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Ht:case Ct:return n==t+""
}var v=p==Nt;if(!v){if(n.__wrapped__||t.__wrapped__)return O(n.__wrapped__||n,t.__wrapped__||t,e,u,a,o);if(p!=Bt)return!1;var y=n.constructor,h=t.constructor;if(y!=h&&!(E(y)&&y instanceof y&&E(h)&&h instanceof h))return!1}a||(a=[]),o||(o=[]);for(var d=a.length;d--;)if(a[d]==n)return o[d]==t;var m=0;if(l=!0,a.push(n),o.push(t),v){if(d=n.length,m=t.length,l=m==n.length,!l&&!f)return l;for(;m--;){var b=d,_=t[m];if(f)for(;b--&&!(l=O(n[b],_,e,u,a,o)););else if(!(l=O(n[m],_,e,u,a,o)))break}return l}return re(t,function(t,i,f){return wt.call(f,i)?(m++,l=wt.call(n,i)&&O(n[i],t,e,u,a,o)):r
}),l&&!f&&re(n,function(n,t,e){return wt.call(e,t)?l=--m>-1:r}),l}function I(n){return It(n)&&!Et(parseFloat(n))}function E(n){return"function"==typeof n}function S(n){return n?Jt[typeof n]:!1}function L(n){return T(n)&&n!=+n}function R(n){return null===n}function T(n){return"number"==typeof n||At.call(n)==qt}function F(n){return n instanceof RegExp||At.call(n)==Ht}function N(n){return"string"==typeof n||At.call(n)==Ct}function $(n){return"undefined"==typeof n}function P(n,r,t){var e=arguments,u=0,a=2;
if(!S(n))return n;if(t===et)var o=e[3],f=e[4],l=e[5];else f=[],l=[],"number"!=typeof t&&(a=e.length),a>3&&"function"==typeof e[a-2]?o=i(e[--a-1],e[a--],2):a>2&&"function"==typeof e[a-1]&&(o=e[--a]);for(;++u<a;)(ee(e[u])?G:te)(e[u],function(r,t){var e,u,a=r,i=n[t];if(r&&((u=ee(r))||le(r))){for(var c=f.length;c--;)if(e=f[c]==r){i=l[c];break}e||(i=u?ee(i)?i:[]:le(i)?i:{},o&&(a=o(i,r),"undefined"!=typeof a&&(i=a)),f.push(r),l.push(i),o||(i=P(i,r,et,o,f,l)))}else o&&(a=o(i,r),"undefined"==typeof a&&(a=r)),"undefined"!=typeof a&&(i=a);
n[t]=i});return n}function D(n,r,t){var e="function"==typeof r,u={};if(e)r=i(r,t);else var a=bt.apply(nt,arguments);return re(n,function(n,t,o){(e?!r(n,t,o):sr(a,t,1)<0)&&(u[t]=n)}),u}function q(n){for(var r=-1,t=ue(n),e=t.length,u=Array(e);++r<e;){var a=t[r];u[r]=[a,n[a]]}return u}function B(n,r,t){var e={};if("function"!=typeof r)for(var u=0,a=bt.apply(nt,arguments),o=S(n)?a.length:0;++u<o;){var f=a[u];f in n&&(e[f]=n[f])}else r=i(r,t),re(n,function(n,t,u){r(n,t,u)&&(e[t]=n)});return e}function H(n){for(var r=-1,t=ue(n),e=t.length,u=Array(e);++r<e;)u[r]=n[t[r]];
return u}function C(n){for(var r=-1,t=bt.apply(nt,p(arguments,1)),e=t.length,u=Array(e);++r<e;)u[r]=n[t[r]];return u}function K(n,t,e){var u=-1,a=n?n.length:0,o=!1;return e=(e<0?Lt(0,a+e):e)||0,"number"==typeof a?o=(N(n)?n.indexOf(t,e):sr(n,t,e))>-1:ne(n,function(n){return++u<e?r:!(o=n===t)}),o}function M(n,r,t){var e={};return r=i(r,t),G(n,function(n,t,u){t=r(n,t,u)+"",wt.call(e,t)?e[t]++:e[t]=1}),e}function z(n,r,t){var e=!0;if(r=i(r,t),ee(n))for(var u=-1,a=n.length;++u<a&&(e=!!r(n[u],u,n)););else ne(n,function(n,t,u){return e=!!r(n,t,u)
});return e}function U(n,r,t){var e=[];if(r=i(r,t),ee(n))for(var u=-1,a=n.length;++u<a;){var o=n[u];r(o,u,n)&&e.push(o)}else ne(n,function(n,t,u){r(n,t,u)&&e.push(n)});return e}function V(n,t,e){var u;return t=i(t,e),G(n,function(n,e,a){return t(n,e,a)?(u=n,!1):r}),u}function G(n,r,t){if(r&&"undefined"==typeof t&&ee(n))for(var e=-1,u=n.length;++e<u&&r(n[e],e,n)!==!1;);else ne(n,r,t);return n}function J(n,r,t){var e={};return r=i(r,t),G(n,function(n,t,u){t=r(n,t,u)+"",(wt.call(e,t)?e[t]:e[t]=[]).push(n)
}),e}function Q(n,r){var t=p(arguments,2),e=-1,u="function"==typeof r,a=n?n.length:0,o=Array("number"==typeof a?a:0);return G(n,function(n){o[++e]=(u?r:n[r]).apply(n,t)}),o}function W(n,r,t){var e=-1,u=n?n.length:0,a=Array("number"==typeof u?u:0);if(r=i(r,t),ee(n))for(;++e<u;)a[e]=r(n[e],e,n);else ne(n,function(n,t,u){a[++e]=r(n,t,u)});return a}function X(n,r,t){var e=-1/0,a=e;if(!r&&ee(n))for(var o=-1,f=n.length;++o<f;){var l=n[o];l>a&&(a=l)}else r=!r&&N(n)?u:i(r,t),ne(n,function(n,t,u){var o=r(n,t,u);
o>e&&(e=o,a=n)});return a}function Y(n,r,t){var e=1/0,a=e;if(!r&&ee(n))for(var o=-1,f=n.length;++o<f;){var l=n[o];l<a&&(a=l)}else r=!r&&N(n)?u:i(r,t),ne(n,function(n,t,u){var o=r(n,t,u);o<e&&(e=o,a=n)});return a}function Z(n,r,t,e){var u=arguments.length<3;if(r=i(r,e,4),ee(n)){var a=-1,o=n.length;for(u&&(t=n[++a]);++a<o;)t=r(t,n[a],a,n)}else ne(n,function(n,e,a){t=u?(u=!1,n):r(t,n,e,a)});return t}function nr(n,r,t,e){var u=n,a=n?n.length:0,o=arguments.length<3;if("number"!=typeof a){var f=ue(n);a=f.length
}return r=i(r,e,4),G(n,function(n,e,i){e=f?f[--a]:--a,t=o?(o=!1,u[e]):r(t,u[e],e,i)}),t}function rr(n,r,t){return r=i(r,t),U(n,function(n,t,e){return!r(n,t,e)})}function tr(n){var r=-1,t=n?n.length:0,e=Array("number"==typeof t?t:0);return G(n,function(n){var t=_t(Tt()*(++r+1));e[r]=e[t],e[t]=n}),e}function er(n){var r=n?n.length:0;return"number"==typeof r?r:ue(n).length}function ur(n,r,t){var e;if(r=i(r,t),ee(n))for(var u=-1,a=n.length;++u<a&&!(e=r(n[u],u,n)););else ne(n,function(n,t,u){return!(e=r(n,t,u))
});return!!e}function ar(n,r,t){var e=-1,u=n?n.length:0,o=Array("number"==typeof u?u:0);for(r=i(r,t),G(n,function(n,t,u){o[++e]={criteria:r(n,t,u),index:e,value:n}}),u=o.length,o.sort(a);u--;)o[u]=o[u].value;return o}function or(n){return n&&"number"==typeof n.length?p(n):H(n)}function ir(n){for(var r=-1,t=n?n.length:0,e=[];++r<t;){var u=n[r];u&&e.push(u)}return e}function fr(n){for(var r=-1,t=n?n.length:0,u=bt.apply(nt,arguments),a=e(u,t),o=[];++r<t;){var i=n[r];a(i)||o.push(i)}return o}function lr(n,r,t){if(n){var e=0,u=n.length;
if("number"!=typeof r&&null!=r){var a=-1;for(r=i(r,t);++a<u&&r(n[a],a,n);)e++}else if(e=r,null==e||t)return n[0];return p(n,0,Rt(Lt(0,e),u))}}function cr(n,r){for(var t=-1,e=n?n.length:0,u=[];++t<e;){var a=n[t];ee(a)?jt.apply(u,r?a:cr(a)):u.push(a)}return u}function sr(n,r,t){var e=-1,u=n?n.length:0;if("number"==typeof t)e=(t<0?Lt(0,u+t):t||0)-1;else if(t)return e=br(n,r),n[e]===r?e:-1;for(;++e<u;)if(n[e]===r)return e;return-1}function pr(n,r,t){if(!n)return[];var e=0,u=n.length;if("number"!=typeof r&&null!=r){var a=u;
for(r=i(r,t);a--&&r(n[a],a,n);)e++}else e=null==r||t?1:r||e;return p(n,0,Rt(Lt(0,u-e),u))}function gr(n){var r=arguments,t=r.length,u={0:{}},a=-1,o=n?n.length:0,i=o>=100,f=[],l=f;n:for(;++a<o;){var c=n[a];if(i)var s=c+"",p=wt.call(u[0],s)?!(l=u[0][s]):l=u[0][s]=[];if(p||sr(l,c)<0){i&&l.push(c);for(var g=t;--g;)if(!(u[g]||(u[g]=e(r[g],0,100)))(c))continue n;f.push(c)}}return f}function vr(n,r,t){if(n){var e=0,u=n.length;if("number"!=typeof r&&null!=r){var a=u;for(r=i(r,t);a--&&r(n[a],a,n);)e++}else if(e=r,null==e||t)return n[u-1];
return p(n,Lt(0,u-e))}}function yr(n,r,t){var e=n?n.length:0;for("number"==typeof t&&(e=(t<0?Lt(0,e+t):Rt(t,e-1))+1);e--;)if(n[e]===r)return e;return-1}function hr(n,r){for(var t=-1,e=n?n.length:0,u={};++t<e;){var a=n[t];r?u[a]=r[t]:u[a[0]]=a[1]}return u}function dr(n,r,t){n=+n||0,t=+t||1,null==r&&(r=n,n=0);for(var e=-1,u=Lt(0,mt((r-n)/t)),a=Array(u);++e<u;)a[e]=n,n+=t;return a}function mr(n,r,t){if("number"!=typeof r&&null!=r){var e=0,u=-1,a=n?n.length:0;for(r=i(r,t);++u<a&&r(n[u],u,n);)e++}else e=null==r||t?1:Lt(0,r);
return p(n,e)}function br(n,r,t,e){var u=0,a=n?n.length:u;for(t=t?i(t,e,1):Br,r=t(r);u<a;){var o=u+a>>>1;t(n[o])<r?u=o+1:a=o}return u}function _r(){return xr(bt.apply(nt,arguments))}function xr(n,r,t,e){var u=-1,a=n?n.length:0,o=[],f=o;"function"==typeof r&&(e=t,t=r,r=!1);var l=!r&&a>=75;if(l)var c={};for(t&&(f=[],t=i(t,e));++u<a;){var s=n[u],p=t?t(s,u,n):s;if(l)var g=p+"",v=wt.call(c,g)?!(f=c[g]):f=c[g]=[];(r?!u||f[f.length-1]!==p:v||sr(f,p)<0)&&((t||l)&&f.push(p),o.push(s))}return o}function wr(n){for(var r=-1,t=n?n.length:0,u=e(arguments,1),a=[];++r<t;){var o=n[r];
u(o)||a.push(o)}return a}function jr(n){for(var r=-1,t=n?X(ce(arguments,"length")):0,e=Array(t);++r<t;)e[r]=ce(arguments,r);return e}function Ar(n,t){return n<1?t():function(){return--n<1?t.apply(this,arguments):r}}function kr(n,r){return zt||kt&&arguments.length>2?kt.call.apply(kt,arguments):o(n,r,p(arguments,2))}function Or(n){for(var r=bt.apply(nt,arguments),t=r.length>1?0:(r=b(n),-1),e=r.length;++t<e;){var u=r[t];n[u]=kr(n[u],n)}return n}function Ir(n,r){return o(n,r,p(arguments,2))}function Er(){var n=arguments;
return function(){for(var r=arguments,t=n.length;t--;)r=[n[t].apply(this,r)];return r[0]}}function Sr(n,r,t){function e(){i=null,t||(a=n.apply(o,u))}var u,a,o,i;return function(){var f=t&&!i;return u=arguments,o=this,clearTimeout(i),i=setTimeout(e,r),f&&(a=n.apply(o,u)),a}}function Lr(n,t){var e=p(arguments,2);return setTimeout(function(){n.apply(r,e)},t)}function Rr(n){var t=p(arguments,1);return setTimeout(function(){n.apply(r,t)},1)}function Tr(n,r){var t={};return function(){var e=(r?r.apply(this,arguments):arguments[0])+"";
return wt.call(t,e)?t[e]:t[e]=n.apply(this,arguments)}}function Fr(n){var r,t;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}}function Nr(n){return o(n,p(arguments,1))}function $r(n){return o(n,p(arguments,1),null,et)}function Pr(n,r){function t(){i=new Date,o=null,u=n.apply(a,e)}var e,u,a,o,i=0;return function(){var f=new Date,l=r-(f-i);return e=arguments,a=this,l>0?o||(o=setTimeout(t,l)):(clearTimeout(o),o=null,i=f,u=n.apply(a,e)),u}}function Dr(n,r){return function(){var t=[n];
return jt.apply(t,arguments),r.apply(this,t)}}function qr(n){return null==n?"":(n+"").replace(yt,c)}function Br(n){return n}function Hr(n){G(b(n),function(r){var e=t[r]=n[r];t.prototype[r]=function(){var n=[this.__wrapped__];return jt.apply(n,arguments),new t(e.apply(t,n))}})}function Cr(){return n._=at,this}function Kr(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r&&(r=n,n=0),n+_t(Tt()*((+r||0)-n+1))}function Mr(n,t){var e=n?n[t]:r;return E(e)?n[t]():e}function zr(n,e,u){var a=t.templateSettings;
n||(n=""),u=fe({},u,a);var o,i=fe({},u.imports,a.imports),f=ue(i),c=H(i),s=0,p=u.interpolate||vt,g="__p += '",v=RegExp((u.escape||vt).source+"|"+p.source+"|"+(p===gt?pt:vt).source+"|"+(u.evaluate||vt).source+"|$","g");n.replace(v,function(r,t,e,u,a,i){return e||(e=u),g+=n.slice(s,i).replace(ht,l),t&&(g+="' +\n__e("+t+") +\n'"),a&&(o=!0,g+="';\n"+a+";\n__p += '"),e&&(g+="' +\n((__t = ("+e+")) == null ? '' : __t) +\n'"),s=i+r.length,r}),g+="';\n";var y=u.variable,h=y;h||(y="obj",g="with ("+y+") {\n"+g+"\n}\n"),g=(o?g.replace(it,""):g).replace(ft,"$1").replace(lt,"$1;"),g="function("+y+") {\n"+(h?"":y+" || ("+y+" = {});\n")+"var __t, __p = '', __e = _.escape"+(o?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+g+"return __p\n}";
var d="\n/*\n//@ sourceURL="+(u.sourceURL||"/lodash/template/source["+dt++ +"]")+"\n*/";try{var m=Function(f,"return "+g+d).apply(r,c)}catch(b){throw b.source=g,b}return e?m(e):(m.source=g,m)}function Ur(n,r,t){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=r.call(t,e);return u}function Vr(n){return null==n?"":(n+"").replace(ot,g)}function Gr(n){var r=++tt;return(null==n?"":n+"")+r}function Jr(n,r){return r(n),n}function Qr(){return this.__wrapped__+""}function Wr(){return this.__wrapped__}var Xr="object"==typeof exports&&exports,Yr="object"==typeof module&&module&&module.exports==Xr&&module,Zr="object"==typeof global&&global;
Zr.global===Zr&&(n=Zr);var nt=[],rt={},tt=0,et=rt,ut=30,at=n._,ot=/&(?:amp|lt|gt|quot|#39);/g,it=/\b__p \+= '';/g,ft=/\b(__p \+=) '' \+/g,lt=/(__e\(.*?\)|\b__t\)) \+\n'';/g,ct=/\w*$/,st=RegExp("^"+(rt.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),pt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,gt=/<%=([\s\S]+?)%>/g,vt=/($^)/,yt=/[&<>"']/g,ht=/['\n\r\t\u2028\u2029\\]/g,dt=0,mt=Math.ceil,bt=nt.concat,_t=Math.floor,xt=st.test(xt=Object.getPrototypeOf)&&xt,wt=rt.hasOwnProperty,jt=nt.push,At=rt.toString,kt=st.test(kt=p.bind)&&kt,Ot=st.test(Ot=Array.isArray)&&Ot,It=n.isFinite,Et=n.isNaN,St=st.test(St=Object.keys)&&St,Lt=Math.max,Rt=Math.min,Tt=Math.random,Ft="[object Arguments]",Nt="[object Array]",$t="[object Boolean]",Pt="[object Date]",Dt="[object Function]",qt="[object Number]",Bt="[object Object]",Ht="[object RegExp]",Ct="[object String]",Kt=!!n.attachEvent,Mt=kt&&!/\n|true/.test(kt+Kt),zt=kt&&!Mt,Ut=St&&(Kt||Mt),Vt={};
Vt[Dt]=!1,Vt[Ft]=Vt[Nt]=Vt[$t]=Vt[Pt]=Vt[qt]=Vt[Bt]=Vt[Ht]=Vt[Ct]=!0;var Gt={};Gt[Nt]=Array,Gt[$t]=Boolean,Gt[Pt]=Date,Gt[Bt]=Object,Gt[qt]=Number,Gt[Ht]=RegExp,Gt[Ct]=String;var Jt={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},Qt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};t.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:gt,variable:"",imports:{_:t}};var Wt=function(n){var r="var index, iterable = "+n.firstArg+", result = iterable;\nif (!iterable) return result;\n"+n.top+";\n";
return n.arrays&&(r+="var length = iterable.length; index = -1;\nif ("+n.arrays+") {\n while (++index < length) {\n "+n.loop+"\n }\n}\nelse { "),n.isKeysFast&&n.useHas?r+="\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n "+n.loop+"\n } ":(r+="\n for (index in iterable) {",n.useHas&&(r+="\n if (",n.useHas&&(r+="hasOwnProperty.call(iterable, index)"),r+=") { "),r+=n.loop+"; ",n.useHas&&(r+="\n }"),r+="\n } "),n.arrays&&(r+="\n}"),r+=n.bottom+";\nreturn result"
},Xt={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"},Yt={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",arrays:"typeof length == 'number'",loop:"if (callback(iterable[index], index, collection) === false) return result"},Zt={top:"if (!objectTypes[typeof iterable]) return result;\n"+Yt.top,arrays:!1},ne=f(Yt),re=f(Yt,Zt,{useHas:!1}),te=f(Yt,Zt),ee=Ot||function(n){return n instanceof Array||At.call(n)==Nt
},ue=St?function(n){return S(n)?St(n):[]}:h,ae={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},oe=x(ae),ie=f(Xt,{top:Xt.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"}),fe=f(Xt);
E(/x/)&&(E=function(n){return n instanceof Function||At.call(n)==Dt});var le=xt?function(n){if(!n||"object"!=typeof n)return!1;var r=n.valueOf,t="function"==typeof r&&(t=xt(r))&&xt(t);return t?n==t||xt(n)==t&&!v(n):y(n)}:y,ce=W,se=U;Mt&&Yr&&"function"==typeof setImmediate&&(Rr=kr(setImmediate,n)),t.after=Ar,t.assign=ie,t.at=C,t.bind=kr,t.bindAll=Or,t.bindKey=Ir,t.compact=ir,t.compose=Er,t.countBy=M,t.debounce=Sr,t.defaults=fe,t.defer=Rr,t.delay=Lr,t.difference=fr,t.filter=U,t.flatten=cr,t.forEach=G,t.forIn=re,t.forOwn=te,t.functions=b,t.groupBy=J,t.initial=pr,t.intersection=gr,t.invert=x,t.invoke=Q,t.keys=ue,t.map=W,t.max=X,t.memoize=Tr,t.merge=P,t.min=Y,t.object=hr,t.omit=D,t.once=Fr,t.pairs=q,t.partial=Nr,t.partialRight=$r,t.pick=B,t.pluck=ce,t.range=dr,t.reject=rr,t.rest=mr,t.shuffle=tr,t.sortBy=ar,t.tap=Jr,t.throttle=Pr,t.times=Ur,t.toArray=or,t.union=_r,t.uniq=xr,t.values=H,t.where=se,t.without=wr,t.wrap=Dr,t.zip=jr,t.collect=W,t.drop=mr,t.each=G,t.extend=ie,t.methods=b,t.select=U,t.tail=mr,t.unique=xr,Hr(t),t.clone=d,t.cloneDeep=m,t.contains=K,t.escape=qr,t.every=z,t.find=V,t.has=_,t.identity=Br,t.indexOf=sr,t.isArguments=v,t.isArray=ee,t.isBoolean=w,t.isDate=j,t.isElement=A,t.isEmpty=k,t.isEqual=O,t.isFinite=I,t.isFunction=E,t.isNaN=L,t.isNull=R,t.isNumber=T,t.isObject=S,t.isPlainObject=le,t.isRegExp=F,t.isString=N,t.isUndefined=$,t.lastIndexOf=yr,t.mixin=Hr,t.noConflict=Cr,t.random=Kr,t.reduce=Z,t.reduceRight=nr,t.result=Mr,t.size=er,t.some=ur,t.sortedIndex=br,t.template=zr,t.unescape=Vr,t.uniqueId=Gr,t.all=z,t.any=ur,t.detect=V,t.foldl=Z,t.foldr=nr,t.include=K,t.inject=Z,te(t,function(n,r){t.prototype[r]||(t.prototype[r]=function(){var r=[this.__wrapped__];
return jt.apply(r,arguments),n.apply(t,r)})}),t.first=lr,t.last=vr,t.take=lr,t.head=lr,te(t,function(n,r){t.prototype[r]||(t.prototype[r]=function(r,e){var u=n(this.__wrapped__,r,e);return null==r||e&&"function"!=typeof r?u:new t(u)})}),t.VERSION="1.0.2",t.prototype.toString=Qr,t.prototype.value=Wr,t.prototype.valueOf=Wr,ne(["join","pop","shift"],function(n){var r=nt[n];t.prototype[n]=function(){return r.apply(this.__wrapped__,arguments)}}),ne(["push","reverse","sort","unshift"],function(n){var r=nt[n];
t.prototype[n]=function(){return r.apply(this.__wrapped__,arguments),this}}),ne(["concat","slice","splice"],function(n){var r=nt[n];t.prototype[n]=function(){return new t(r.apply(this.__wrapped__,arguments))}}),"function"==typeof define&&"object"==typeof define.amd&&define.amd?(n._=t,define(function(){return t})):Xr?Yr?(Yr.exports=t)._=t:Xr._=t:n._=t})(this);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/**
* @license
* Lo-Dash 1.0.2 (Custom Build) lodash.com/license
* Build: `lodash underscore -o ./dist/lodash.underscore.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(n,t){function r(n,t){var r;if(n&&qt[typeof n])for(r in t||(t=G),n)if(t(n[r],r,n)===tt)break}function e(n,t,r){if(n){t=t&&typeof r=="undefined"?t:a(t,r);var e=n.length;if(r=-1,typeof e=="number")for(;++r<e&&t(n[r],r,n)!==tt;);else for(r in n)if(pt.call(n,r)&&t(n[r],r,n)===tt)break}}function u(n){return n&&typeof n=="object"&&n.__wrapped__?n:this instanceof u?(this.__wrapped__=n,void 0):new u(n)}function o(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
}return r<e?-1:1}function i(n,t,r){function e(){var a=arguments,f=o?this:t;return u||(n=t[i]),r.length&&(a=a.length?(a=p(a),r.concat(a)):r),this instanceof e?(l.prototype=n.prototype,f=new l,l.prototype=K,a=n.apply(f,a),w(a)?a:f):n.apply(f,a)}var u=j(n),o=!r,i=t;return o&&(r=t),u||(t=n),e}function a(n,t,r){if(n==K)return G;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=Dt(n);return function(t){for(var r=u.length,e=L;r--&&(e=t[u[r]]===n[u[r]]););return e}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)
}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function f(n){return"\\"+It[n]}function c(n){return Mt[n]}function l(){}function p(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function s(n){return $t[n]}function v(n){return vt.call(n)==wt}function h(n){var t,r=[],e=function(n,t){r.push(t)};if(n&&qt[typeof n])for(t in e||(e=G),n)if(pt.call(n,t)&&e(n[t],t,n)===tt)break;
return r}function g(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]=e[u]}return n}function y(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]==K&&(n[u]=e[u])}return n}function m(n){var t=[];return r(n,function(n,r){j(n)&&t.push(r)}),t.sort()}function _(n){for(var t=-1,r=Dt(n),e=r.length,u={};++t<e;){var o=r[t];u[n[o]]=o}return u}function d(n){if(!n)return J;if(Bt(n)||x(n))return!n.length;for(var t in n)if(pt.call(n,t))return L;
return J}function b(n,t,e,u){if(n===t)return 0!==n||1/n==1/t;var o=typeof n,i=typeof t;if(n===n&&(!n||"function"!=o&&"object"!=o)&&(!t||"function"!=i&&"object"!=i))return L;if(n==K||t==K)return n===t;if(i=vt.call(n),o=vt.call(t),i!=o)return L;switch(i){case xt:case Et:return+n==+t;case Ot:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Nt:case kt:return n==t+""}if(o=i==At,!o){if(n.__wrapped__||t.__wrapped__)return b(n.__wrapped__||n,t.__wrapped__||t,e,u);if(i!=St)return L;var i=n.constructor,a=t.constructor;
if(i!=a&&(!j(i)||!(i instanceof i&&j(a)&&a instanceof a)))return L}for(e||(e=[]),u||(u=[]),i=e.length;i--;)if(e[i]==n)return u[i]==t;var f=J,c=0;if(e.push(n),u.push(t),o){if(c=t.length,f=c==n.length)for(;c--&&(f=b(n[c],t[c],e,u)););return f}return r(t,function(t,r,o){return pt.call(o,r)?(c++,!(f=pt.call(n,r)&&b(n[r],t,e,u))&&tt):void 0}),f&&r(n,function(n,t,r){return pt.call(r,t)?!(f=-1<--c)&&tt:void 0}),f}function j(n){return typeof n=="function"}function w(n){return n?qt[typeof n]:L}function A(n){return typeof n=="number"||vt.call(n)==Ot
}function x(n){return typeof n=="string"||vt.call(n)==kt}function E(n){for(var t=-1,r=Dt(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function O(n,t){var r=L;return typeof(n?n.length:0)=="number"?r=-1<z(n,t):e(n,function(n){return(r=n===t)&&tt}),r}function S(n,t,r){var u=J;if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o&&(u=!!t(n[r],r,n)););}else e(n,function(n,r,e){return!(u=!!t(n,r,e))&&tt});return u}function N(n,t,r){var u=[];if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o;){var i=n[r];
t(i,r,n)&&u.push(i)}}else e(n,function(n,r,e){t(n,r,e)&&u.push(n)});return u}function k(n,t,r){var e;return t=a(t,r),F(n,function(n,r,u){return t(n,r,u)?(e=n,tt):void 0}),e}function F(n,t,r){if(t&&typeof r=="undefined"&&Bt(n)){r=-1;for(var u=n.length;++r<u&&t(n[r],r,n)!==tt;);}else e(n,t,r)}function R(n,t,r){var u=-1,o=n?n.length:0,i=Array(typeof o=="number"?o:0);if(t=a(t,r),Bt(n))for(;++u<o;)i[u]=t(n[u],u,n);else e(n,function(n,r,e){i[++u]=t(n,r,e)});return i}function T(n,t,r){var u=-1/0,o=u;if(!t&&Bt(n)){r=-1;
for(var i=n.length;++r<i;){var f=n[r];f>o&&(o=f)}}else t=a(t,r),e(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function q(n,t,r,u){var o=3>arguments.length;if(t=a(t,u,4),Bt(n)){var i=-1,f=n.length;for(o&&(r=n[++i]);++i<f;)r=t(r,n[i],i,n)}else e(n,function(n,e,u){r=o?(o=L,n):t(r,n,e,u)});return r}function I(n,t,r,e){var u=n?n.length:0,o=3>arguments.length;if(typeof u!="number")var i=Dt(n),u=i.length;return t=a(t,e,4),F(n,function(e,a,f){a=i?i[--u]:--u,r=o?(o=L,n[a]):t(r,n[a],a,f)}),r}function B(n,t,r){var u;
if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o&&!(u=t(n[r],r,n)););}else e(n,function(n,r,e){return(u=t(n,r,e))&&tt});return!!u}function D(n,t,r){return r&&d(t)?K:(r?k:N)(n,t)}function M(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=-1;for(t=a(t,r);++o<u&&t(n[o],o,n);)e++}else if(e=t,e==K||r)return n[0];return p(n,0,bt(dt(0,e),u))}}function $(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];Bt(o)?st.apply(u,t?o:$(o)):u.push(o)}return u}function z(n,t,r){var e=-1,u=n?n.length:0;
if(typeof r=="number")e=(0>r?dt(0,u+r):r||0)-1;else if(r)return e=P(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function C(n,t,r){if(typeof t!="number"&&t!=K){var e=0,u=-1,o=n?n.length:0;for(t=a(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==K||r?1:dt(0,t);return p(n,e)}function P(n,t,r,e){var u=0,o=n?n.length:u;for(r=r?a(r,e,1):G,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function U(n,t,r,e){var u=-1,o=n?n.length:0,i=[],f=i;for(typeof t=="function"&&(e=r,r=t,t=L),r&&(f=[],r=a(r,e));++u<o;){e=n[u];
var c=r?r(e,u,n):e;(t?!u||f[f.length-1]!==c:0>z(f,c))&&(r&&f.push(c),i.push(e))}return i}function V(n,t){return Ft||ht&&2<arguments.length?ht.call.apply(ht,arguments):i(n,t,p(arguments,2))}function W(n){var r=p(arguments,1);return setTimeout(function(){n.apply(t,r)},1)}function G(n){return n}function H(n){F(m(n),function(t){var r=u[t]=n[t];u.prototype[t]=function(){var n=[this.__wrapped__];return st.apply(n,arguments),n=r.apply(u,n),this.__chain__&&(n=new u(n),n.__chain__=J),n}})}var J=!0,K=null,L=!1,Q=typeof exports=="object"&&exports,X=typeof module=="object"&&module&&module.exports==Q&&module,Y=typeof global=="object"&&global;
Y.global===Y&&(n=Y);var Z=[],Y={},nt=0,tt=Y,rt=n._,et=/&(?:amp|lt|gt|quot|#39);/g,ut=RegExp("^"+(Y.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),ot=/($^)/,it=/[&<>"']/g,at=/['\n\r\t\u2028\u2029\\]/g,ft=Math.ceil,ct=Z.concat,lt=Math.floor,pt=Y.hasOwnProperty,st=Z.push,vt=Y.toString,ht=ut.test(ht=p.bind)&&ht,gt=ut.test(gt=Array.isArray)&&gt,yt=n.isFinite,mt=n.isNaN,_t=ut.test(_t=Object.keys)&&_t,dt=Math.max,bt=Math.min,jt=Math.random,wt="[object Arguments]",At="[object Array]",xt="[object Boolean]",Et="[object Date]",Ot="[object Number]",St="[object Object]",Nt="[object RegExp]",kt="[object String]",Y=!!n.attachEvent,Y=ht&&!/\n|true/.test(ht+Y),Ft=ht&&!Y,Rt=(Rt={0:1,length:1},Z.splice.call(Rt,0,1),Rt[0]),Tt=arguments.constructor==Object,qt={"boolean":L,"function":J,object:J,number:L,string:L,undefined:L},It={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};
u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},v(arguments)||(v=function(n){return n?pt.call(n,"callee"):L});var Bt=gt||function(n){return Tt&&n instanceof Array||vt.call(n)==At},Dt=_t?function(n){return w(n)?_t(n):[]}:h,Mt={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},$t=_(Mt);j(/x/)&&(j=function(n){return n instanceof Function||"[object Function]"==vt.call(n)});var zt=R;Y&&X&&typeof setImmediate=="function"&&(W=V(setImmediate,n)),u.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0
}},u.bind=V,u.bindAll=function(n){for(var t=ct.apply(Z,arguments),r=1<t.length?0:(t=m(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=V(n[u],n)}return n},u.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},u.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},u.countBy=function(n,t,r){var e={};return t=a(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",pt.call(e,r)?e[r]++:e[r]=1}),e},u.debounce=function(n,t,r){function e(){a=K,r||(o=n.apply(i,u))
}var u,o,i,a;return function(){var f=r&&!a;return u=arguments,i=this,clearTimeout(a),a=setTimeout(e,t),f&&(o=n.apply(i,u)),o}},u.defaults=y,u.defer=W,u.delay=function(n,r){var e=p(arguments,2);return setTimeout(function(){n.apply(t,e)},r)},u.difference=function(n){for(var t=-1,r=n.length,e=ct.apply(Z,arguments),u=[];++t<r;){var o=n[t];0>z(e,o,r)&&u.push(o)}return u},u.filter=N,u.flatten=$,u.forEach=F,u.functions=m,u.groupBy=function(n,t,r){var e={};return t=a(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",(pt.call(e,r)?e[r]:e[r]=[]).push(n)
}),e},u.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else e=t==K||r?1:t||e;return p(n,0,bt(dt(0,u-e),u))},u.intersection=function(n){var t=arguments,r=t.length,e=-1,u=n?n.length:0,o=[];n:for(;++e<u;){var i=n[e];if(0>z(o,i)){for(var a=r;--a;)if(0>z(t[a],i))continue n;o.push(i)}}return o},u.invert=_,u.invoke=function(n,t){var r=p(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);
return F(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},u.keys=Dt,u.map=R,u.max=T,u.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";return pt.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},u.min=function(n,t,r){var u=1/0,o=u;if(!t&&Bt(n)){r=-1;for(var i=n.length;++r<i;){var f=n[r];f<o&&(o=f)}}else t=a(t,r),e(n,function(n,r,e){r=t(n,r,e),r<u&&(u=r,o=n)});return o},u.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]
}return u},u.omit=function(n){var t=ct.apply(Z,arguments),e={};return r(n,function(n,r){0>z(t,r,1)&&(e[r]=n)}),e},u.once=function(n){var t,r;return function(){return t?r:(t=J,r=n.apply(this,arguments),n=K,r)}},u.pairs=function(n){for(var t=-1,r=Dt(n),e=r.length,u=Array(e);++t<e;){var o=r[t];u[t]=[o,n[o]]}return u},u.partial=function(n){return i(n,p(arguments,1))},u.pick=function(n){for(var t=0,r=ct.apply(Z,arguments),e=r.length,u={};++t<e;){var o=r[t];o in n&&(u[o]=n[o])}return u},u.pluck=zt,u.range=function(n,t,r){n=+n||0,r=+r||1,t==K&&(t=n,n=0);
var e=-1;t=dt(0,ft((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},u.reject=function(n,t,r){return t=a(t,r),N(n,function(n,r,e){return!t(n,r,e)})},u.rest=C,u.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return F(n,function(n){var r=lt(jt()*(++t+1));e[t]=e[r],e[r]=n}),e},u.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=a(t,r),F(n,function(n,r,u){i[++e]={a:t(n,r,u),b:e,c:n}}),u=i.length,i.sort(o);u--;)i[u]=i[u].c;return i
},u.tap=function(n,t){return t(n),n},u.throttle=function(n,t){function r(){a=new Date,i=K,u=n.apply(o,e)}var e,u,o,i,a=0;return function(){var f=new Date,c=t-(f-a);return e=arguments,o=this,0<c?i||(i=setTimeout(r,c)):(clearTimeout(i),i=K,a=f,u=n.apply(o,e)),u}},u.times=function(n,t,r){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=t.call(r,e);return u},u.toArray=function(n){return n&&typeof n.length=="number"?p(n):E(n)},u.union=function(){return U(ct.apply(Z,arguments))},u.uniq=U,u.values=E,u.where=D,u.without=function(n){for(var t=-1,r=n.length,e=[];++t<r;){var u=n[t];
0>z(arguments,u,1)&&e.push(u)}return e},u.wrap=function(n,t){return function(){var r=[n];return st.apply(r,arguments),t.apply(this,r)}},u.zip=function(n){for(var t=-1,r=n?T(zt(arguments,"length")):0,e=Array(r);++t<r;)e[t]=zt(arguments,t);return e},u.collect=R,u.drop=C,u.each=F,u.extend=g,u.methods=m,u.select=N,u.tail=C,u.unique=U,u.clone=function(n){return w(n)?Bt(n)?p(n):g({},n):n},u.contains=O,u.escape=function(n){return n==K?"":(n+"").replace(it,c)},u.every=S,u.find=k,u.findWhere=function(n,t){return D(n,t,J)
},u.has=function(n,t){return n?pt.call(n,t):L},u.identity=G,u.indexOf=z,u.isArguments=v,u.isArray=Bt,u.isBoolean=function(n){return n===J||n===L||vt.call(n)==xt},u.isDate=function(n){return n instanceof Date||vt.call(n)==Et},u.isElement=function(n){return n?1===n.nodeType:L},u.isEmpty=d,u.isEqual=b,u.isFinite=function(n){return yt(n)&&!mt(parseFloat(n))},u.isFunction=j,u.isNaN=function(n){return A(n)&&n!=+n},u.isNull=function(n){return n===K},u.isNumber=A,u.isObject=w,u.isRegExp=function(n){return n instanceof RegExp||vt.call(n)==Nt
},u.isString=x,u.isUndefined=function(n){return typeof n=="undefined"},u.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?dt(0,e+r):bt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=H,u.noConflict=function(){return n._=rt,this},u.random=function(n,t){return n==K&&t==K&&(t=1),n=+n||0,t==K&&(t=n,n=0),n+lt(jt()*((+t||0)-n+1))},u.reduce=q,u.reduceRight=I,u.result=function(n,t){var r=n?n[t]:K;return j(r)?n[t]():r},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Dt(n).length
},u.some=B,u.sortedIndex=P,u.template=function(n,t,r){n||(n=""),r=y({},r,u.templateSettings);var e=0,o="__p+='",i=r.variable;n.replace(RegExp((r.escape||ot).source+"|"+(r.interpolate||ot).source+"|"+(r.evaluate||ot).source+"|$","g"),function(t,r,u,i,a){return o+=n.slice(e,a).replace(at,f),r&&(o+="'+_['escape']("+r+")+'"),i&&(o+="';"+i+";__p+='"),u&&(o+="'+((__t=("+u+"))==null?'':__t)+'"),e=a+t.length,t}),o+="';\n",i||(i="obj",o="with("+i+"||{}){"+o+"}"),o="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+o+"return __p}";
try{var a=Function("_","return "+o)(u)}catch(c){throw c.source=o,c}return t?a(t):(a.source=o,a)},u.unescape=function(n){return n==K?"":(n+"").replace(et,s)},u.uniqueId=function(n){var t=++nt+"";return n?n+t:t},u.all=S,u.any=B,u.detect=k,u.foldl=q,u.foldr=I,u.include=O,u.inject=q,u.first=M,u.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==K||r)return n[u-1];return p(n,dt(0,u-e))}},u.take=M,u.head=M,u.chain=function(n){return n=new u(n),n.__chain__=J,n
},u.VERSION="1.0.2",H(u),u.prototype.chain=function(){return this.__chain__=J,this},u.prototype.value=function(){return this.__wrapped__},e("pop push reverse shift sort splice unshift".split(" "),function(n){var t=Z[n];u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),Rt&&0===n.length&&delete n[0],this}}),e(["concat","join","slice"],function(n){var t=Z[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new u(n),n.__chain__=J),n
}}),Q?X?(X.exports=u)._=u:Q._=u:n._=u})(this);

View File

@@ -0,0 +1,83 @@
{
"_from": "lodash@~1.0.1",
"_id": "lodash@1.0.2",
"_inBundle": false,
"_integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=",
"_location": "/globule/lodash",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "lodash@~1.0.1",
"name": "lodash",
"escapedName": "lodash",
"rawSpec": "~1.0.1",
"saveSpec": null,
"fetchSpec": "~1.0.1"
},
"_requiredBy": [
"/globule"
],
"_resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz",
"_shasum": "8f57560c83b59fc270bd3d561b690043430e2551",
"_spec": "lodash@~1.0.1",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/globule",
"author": {
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com",
"url": "http://allyoucanleet.com/"
},
"bugs": {
"url": "https://github.com/lodash/lodash/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com",
"url": "http://allyoucanleet.com/"
},
{
"name": "Blaine Bublitz",
"email": "blaine@iceddev.com",
"url": "http://iceddev.com/"
},
{
"name": "Kit Cambridge",
"email": "github@kitcambridge.be",
"url": "http://kitcambridge.be/"
},
{
"name": "Mathias Bynens",
"email": "mathias@qiwi.be",
"url": "http://mathiasbynens.be/"
}
],
"deprecated": false,
"description": "A utility library delivering consistency, customization, performance, and extras.",
"engines": [
"node",
"rhino"
],
"homepage": "https://lodash.com/",
"jam": {
"main": "./dist/lodash.compat.js"
},
"keywords": [
"browser",
"client",
"functional",
"performance",
"server",
"speed",
"util"
],
"license": "MIT",
"main": "./dist/lodash.js",
"name": "lodash",
"repository": {
"type": "git",
"url": "git+https://github.com/lodash/lodash.git"
},
"version": "1.0.2"
}

View File

@@ -0,0 +1 @@
/node_modules

View File

@@ -0,0 +1,8 @@
language: node_js
node_js:
- '0.8'
- '0.10'
- '0.12'
- 'iojs'
before_install:
- npm install -g npm@latest

View File

@@ -0,0 +1,14 @@
# Authors, sorted by whether or not they are me
Isaac Z. Schlueter <i@izs.me>
Brian Cottingham <spiffytech@gmail.com>
Carlos Brito Lage <carlos@carloslage.net>
Jesse Dailey <jesse.dailey@gmail.com>
Kevin O'Hara <kevinohara80@gmail.com>
Marco Rogers <marco.rogers@gmail.com>
Mark Cavage <mcavage@gmail.com>
Marko Mikulicic <marko.mikulicic@isti.cnr.it>
Nathan Rajlich <nathan@tootallnate.net>
Satheesh Natesan <snateshan@myspace-inc.com>
Trent Mick <trentm@gmail.com>
ashleybrener <ashley@starlogik.com>
n4kz <n4kz@n4kz.com>

View File

@@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,137 @@
# lru cache
A cache object that deletes the least-recently-used items.
## Usage:
```javascript
var LRU = require("lru-cache")
, options = { max: 500
, length: function (n) { return n * 2 }
, dispose: function (key, n) { n.close() }
, maxAge: 1000 * 60 * 60 }
, cache = LRU(options)
, otherCache = LRU(50) // sets just the max size
cache.set("key", "value")
cache.get("key") // "value"
cache.reset() // empty the cache
```
If you put more stuff in it, then items will fall out.
If you try to put an oversized thing in it, then it'll fall out right
away.
## Keys should always be Strings or Numbers
Note: this module will print warnings to `console.error` if you use a
key that is not a String or Number. Because items are stored in an
object, which coerces keys to a string, it won't go well for you if
you try to use a key that is not a unique string, it'll cause surprise
collisions. For example:
```JavaScript
// Bad Example! Dont' do this!
var cache = LRU()
var a = {}
var b = {}
cache.set(a, 'this is a')
cache.set(b, 'this is b')
console.log(cache.get(a)) // prints: 'this is b'
```
## Options
* `max` The maximum size of the cache, checked by applying the length
function to all values in the cache. Not setting this is kind of
silly, since that's the whole purpose of this lib, but it defaults
to `Infinity`.
* `maxAge` Maximum age in ms. Items are not pro-actively pruned out
as they age, but if you try to get an item that is too old, it'll
drop it and return undefined instead of giving it to you.
* `length` Function that is used to calculate the length of stored
items. If you're storing strings or buffers, then you probably want
to do something like `function(n){return n.length}`. The default is
`function(n){return 1}`, which is fine if you want to store `max`
like-sized things.
* `dispose` Function that is called on items when they are dropped
from the cache. This can be handy if you want to close file
descriptors or do other cleanup tasks when items are no longer
accessible. Called with `key, value`. It's called *before*
actually removing the item from the internal cache, so if you want
to immediately put it back in, you'll have to do that in a
`nextTick` or `setTimeout` callback or it won't do anything.
* `stale` By default, if you set a `maxAge`, it'll only actually pull
stale items out of the cache when you `get(key)`. (That is, it's
not pre-emptively doing a `setTimeout` or anything.) If you set
`stale:true`, it'll return the stale value before deleting it. If
you don't set this, then it'll return `undefined` when you try to
get a stale entry, as if it had already been deleted.
## API
* `set(key, value, maxAge)`
* `get(key) => value`
Both of these will update the "recently used"-ness of the key.
They do what you think. `max` is optional and overrides the
cache `max` option if provided.
* `peek(key)`
Returns the key value (or `undefined` if not found) without
updating the "recently used"-ness of the key.
(If you find yourself using this a lot, you *might* be using the
wrong sort of data structure, but there are some use cases where
it's handy.)
* `del(key)`
Deletes a key out of the cache.
* `reset()`
Clear the cache entirely, throwing away all values.
* `has(key)`
Check if a key is in the cache, without updating the recent-ness
or deleting it for being stale.
* `forEach(function(value,key,cache), [thisp])`
Just like `Array.prototype.forEach`. Iterates over all the keys
in the cache, in order of recent-ness. (Ie, more recently used
items are iterated over first.)
* `keys()`
Return an array of the keys in the cache.
* `values()`
Return an array of the values in the cache.
* `length()`
Return total length of objects in cache taking into account
`length` options function.
* `itemCount`
Return total quantity of objects currently in cache. Note, that
`stale` (see options) items are returned as part of this item
count.
* `dump()`
Return an array of the cache entries ready for serialization and usage
with 'destinationCache.load(arr)`.
* `load(cacheEntriesArray)`
Loads another cache entries array, obtained with `sourceCache.dump()`,
into the cache. The destination cache is reset before loading new entries

View File

@@ -0,0 +1,334 @@
;(function () { // closure for web browsers
if (typeof module === 'object' && module.exports) {
module.exports = LRUCache
} else {
// just set the global for non-node platforms.
this.LRUCache = LRUCache
}
function hOP (obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key)
}
function naiveLength () { return 1 }
var didTypeWarning = false
function typeCheckKey(key) {
if (!didTypeWarning && typeof key !== 'string' && typeof key !== 'number') {
didTypeWarning = true
console.error(new TypeError("LRU: key must be a string or number. Almost certainly a bug! " + typeof key).stack)
}
}
function LRUCache (options) {
if (!(this instanceof LRUCache))
return new LRUCache(options)
if (typeof options === 'number')
options = { max: options }
if (!options)
options = {}
this._max = options.max
// Kind of weird to have a default max of Infinity, but oh well.
if (!this._max || !(typeof this._max === "number") || this._max <= 0 )
this._max = Infinity
this._lengthCalculator = options.length || naiveLength
if (typeof this._lengthCalculator !== "function")
this._lengthCalculator = naiveLength
this._allowStale = options.stale || false
this._maxAge = options.maxAge || null
this._dispose = options.dispose
this.reset()
}
// resize the cache when the max changes.
Object.defineProperty(LRUCache.prototype, "max",
{ set : function (mL) {
if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity
this._max = mL
if (this._length > this._max) trim(this)
}
, get : function () { return this._max }
, enumerable : true
})
// resize the cache when the lengthCalculator changes.
Object.defineProperty(LRUCache.prototype, "lengthCalculator",
{ set : function (lC) {
if (typeof lC !== "function") {
this._lengthCalculator = naiveLength
this._length = this._itemCount
for (var key in this._cache) {
this._cache[key].length = 1
}
} else {
this._lengthCalculator = lC
this._length = 0
for (var key in this._cache) {
this._cache[key].length = this._lengthCalculator(this._cache[key].value)
this._length += this._cache[key].length
}
}
if (this._length > this._max) trim(this)
}
, get : function () { return this._lengthCalculator }
, enumerable : true
})
Object.defineProperty(LRUCache.prototype, "length",
{ get : function () { return this._length }
, enumerable : true
})
Object.defineProperty(LRUCache.prototype, "itemCount",
{ get : function () { return this._itemCount }
, enumerable : true
})
LRUCache.prototype.forEach = function (fn, thisp) {
thisp = thisp || this
var i = 0
var itemCount = this._itemCount
for (var k = this._mru - 1; k >= 0 && i < itemCount; k--) if (this._lruList[k]) {
i++
var hit = this._lruList[k]
if (isStale(this, hit)) {
del(this, hit)
if (!this._allowStale) hit = undefined
}
if (hit) {
fn.call(thisp, hit.value, hit.key, this)
}
}
}
LRUCache.prototype.keys = function () {
var keys = new Array(this._itemCount)
var i = 0
for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
var hit = this._lruList[k]
keys[i++] = hit.key
}
return keys
}
LRUCache.prototype.values = function () {
var values = new Array(this._itemCount)
var i = 0
for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
var hit = this._lruList[k]
values[i++] = hit.value
}
return values
}
LRUCache.prototype.reset = function () {
if (this._dispose && this._cache) {
for (var k in this._cache) {
this._dispose(k, this._cache[k].value)
}
}
this._cache = Object.create(null) // hash of items by key
this._lruList = Object.create(null) // list of items in order of use recency
this._mru = 0 // most recently used
this._lru = 0 // least recently used
this._length = 0 // number of items in the list
this._itemCount = 0
}
LRUCache.prototype.dump = function () {
var arr = []
var i = 0
for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
var hit = this._lruList[k]
if (!isStale(this, hit)) {
//Do not store staled hits
++i
arr.push({
k: hit.key,
v: hit.value,
e: hit.now + (hit.maxAge || 0)
});
}
}
//arr has the most read first
return arr
}
LRUCache.prototype.dumpLru = function () {
return this._lruList
}
LRUCache.prototype.set = function (key, value, maxAge) {
maxAge = maxAge || this._maxAge
typeCheckKey(key)
var now = maxAge ? Date.now() : 0
var len = this._lengthCalculator(value)
if (hOP(this._cache, key)) {
if (len > this._max) {
del(this, this._cache[key])
return false
}
// dispose of the old one before overwriting
if (this._dispose)
this._dispose(key, this._cache[key].value)
this._cache[key].now = now
this._cache[key].maxAge = maxAge
this._cache[key].value = value
this._length += (len - this._cache[key].length)
this._cache[key].length = len
this.get(key)
if (this._length > this._max)
trim(this)
return true
}
var hit = new Entry(key, value, this._mru++, len, now, maxAge)
// oversized objects fall out of cache automatically.
if (hit.length > this._max) {
if (this._dispose) this._dispose(key, value)
return false
}
this._length += hit.length
this._lruList[hit.lu] = this._cache[key] = hit
this._itemCount ++
if (this._length > this._max)
trim(this)
return true
}
LRUCache.prototype.has = function (key) {
typeCheckKey(key)
if (!hOP(this._cache, key)) return false
var hit = this._cache[key]
if (isStale(this, hit)) {
return false
}
return true
}
LRUCache.prototype.get = function (key) {
typeCheckKey(key)
return get(this, key, true)
}
LRUCache.prototype.peek = function (key) {
typeCheckKey(key)
return get(this, key, false)
}
LRUCache.prototype.pop = function () {
var hit = this._lruList[this._lru]
del(this, hit)
return hit || null
}
LRUCache.prototype.del = function (key) {
typeCheckKey(key)
del(this, this._cache[key])
}
LRUCache.prototype.load = function (arr) {
//reset the cache
this.reset();
var now = Date.now()
//A previous serialized cache has the most recent items first
for (var l = arr.length - 1; l >= 0; l-- ) {
var hit = arr[l]
typeCheckKey(hit.k)
var expiresAt = hit.e || 0
if (expiresAt === 0) {
//the item was created without expiration in a non aged cache
this.set(hit.k, hit.v)
} else {
var maxAge = expiresAt - now
//dont add already expired items
if (maxAge > 0) this.set(hit.k, hit.v, maxAge)
}
}
}
function get (self, key, doUse) {
typeCheckKey(key)
var hit = self._cache[key]
if (hit) {
if (isStale(self, hit)) {
del(self, hit)
if (!self._allowStale) hit = undefined
} else {
if (doUse) use(self, hit)
}
if (hit) hit = hit.value
}
return hit
}
function isStale(self, hit) {
if (!hit || (!hit.maxAge && !self._maxAge)) return false
var stale = false;
var diff = Date.now() - hit.now
if (hit.maxAge) {
stale = diff > hit.maxAge
} else {
stale = self._maxAge && (diff > self._maxAge)
}
return stale;
}
function use (self, hit) {
shiftLU(self, hit)
hit.lu = self._mru ++
self._lruList[hit.lu] = hit
}
function trim (self) {
while (self._lru < self._mru && self._length > self._max)
del(self, self._lruList[self._lru])
}
function shiftLU (self, hit) {
delete self._lruList[ hit.lu ]
while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++
}
function del (self, hit) {
if (hit) {
if (self._dispose) self._dispose(hit.key, hit.value)
self._length -= hit.length
self._itemCount --
delete self._cache[ hit.key ]
shiftLU(self, hit)
}
}
// classy, since V8 prefers predictable objects.
function Entry (key, value, lu, length, now, maxAge) {
this.key = key
this.value = value
this.lu = lu
this.length = length
this.now = now
if (maxAge) this.maxAge = maxAge
}
})()

View File

@@ -0,0 +1,56 @@
{
"_from": "lru-cache@2",
"_id": "lru-cache@2.7.3",
"_inBundle": false,
"_integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
"_location": "/globule/lru-cache",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "lru-cache@2",
"name": "lru-cache",
"escapedName": "lru-cache",
"rawSpec": "2",
"saveSpec": null,
"fetchSpec": "2"
},
"_requiredBy": [
"/globule/minimatch"
],
"_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
"_shasum": "6d4524e8b955f95d4f5b58851ce21dd72fb4e952",
"_spec": "lru-cache@2",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/globule/node_modules/minimatch",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me"
},
"bugs": {
"url": "https://github.com/isaacs/node-lru-cache/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "A cache object that deletes the least-recently-used items.",
"devDependencies": {
"tap": "^1.2.0",
"weak": ""
},
"homepage": "https://github.com/isaacs/node-lru-cache#readme",
"keywords": [
"mru",
"lru",
"cache"
],
"license": "ISC",
"main": "lib/lru-cache.js",
"name": "lru-cache",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-lru-cache.git"
},
"scripts": {
"test": "tap test --gc"
},
"version": "2.7.3"
}

View File

@@ -0,0 +1,396 @@
var test = require("tap").test
, LRU = require("../")
test("basic", function (t) {
var cache = new LRU({max: 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.max, 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("max", function (t) {
var cache = new LRU(3)
// test changing the max, verify that the LRU items get dropped.
cache.max = 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.max = 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 max restriction, and try again.
cache.max = "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.max = 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.max, 10)
t.equal(cache.get("a"), undefined)
t.equal(cache.get("b"), undefined)
t.end()
})
test("basic with weighed length", function (t) {
var cache = new LRU({
max: 100,
length: function (item) { return item.size }
})
cache.set("key", {val: "value", size: 50})
t.equal(cache.get("key").val, "value")
t.equal(cache.get("nada"), undefined)
t.equal(cache.lengthCalculator(cache.get("key")), 50)
t.equal(cache.length, 50)
t.equal(cache.max, 100)
t.end()
})
test("weighed length item too large", function (t) {
var cache = new LRU({
max: 10,
length: function (item) { return item.size }
})
t.equal(cache.max, 10)
// should fall out immediately
cache.set("key", {val: "value", size: 50})
t.equal(cache.length, 0)
t.equal(cache.get("key"), undefined)
t.end()
})
test("least recently set with weighed length", function (t) {
var cache = new LRU({
max:8,
length: function (item) { return item.length }
})
cache.set("a", "A")
cache.set("b", "BB")
cache.set("c", "CCC")
cache.set("d", "DDDD")
t.equal(cache.get("d"), "DDDD")
t.equal(cache.get("c"), "CCC")
t.equal(cache.get("b"), undefined)
t.equal(cache.get("a"), undefined)
t.end()
})
test("lru recently gotten with weighed length", function (t) {
var cache = new LRU({
max: 8,
length: function (item) { return item.length }
})
cache.set("a", "A")
cache.set("b", "BB")
cache.set("c", "CCC")
cache.get("a")
cache.get("b")
cache.set("d", "DDDD")
t.equal(cache.get("c"), undefined)
t.equal(cache.get("d"), "DDDD")
t.equal(cache.get("b"), "BB")
t.equal(cache.get("a"), "A")
t.end()
})
test("lru recently updated with weighed length", function (t) {
var cache = new LRU({
max: 8,
length: function (item) { return item.length }
})
cache.set("a", "A")
cache.set("b", "BB")
cache.set("c", "CCC")
t.equal(cache.length, 6) //CCC BB A
cache.set("a", "+A")
t.equal(cache.length, 7) //+A CCC BB
cache.set("b", "++BB")
t.equal(cache.length, 6) //++BB +A
t.equal(cache.get("c"), undefined)
cache.set("c", "oversized")
t.equal(cache.length, 6) //++BB +A
t.equal(cache.get("c"), undefined)
cache.set("a", "oversized")
t.equal(cache.length, 4) //++BB
t.equal(cache.get("a"), undefined)
t.equal(cache.get("b"), "++BB")
t.end()
})
test("set returns proper booleans", function(t) {
var cache = new LRU({
max: 5,
length: function (item) { return item.length }
})
t.equal(cache.set("a", "A"), true)
// should return false for max exceeded
t.equal(cache.set("b", "donuts"), false)
t.equal(cache.set("b", "B"), true)
t.equal(cache.set("c", "CCCC"), true)
t.end()
})
test("drop the old items", function(t) {
var cache = new LRU({
max: 5,
maxAge: 50
})
cache.set("a", "A")
setTimeout(function () {
cache.set("b", "b")
t.equal(cache.get("a"), "A")
}, 25)
setTimeout(function () {
cache.set("c", "C")
// timed out
t.notOk(cache.get("a"))
}, 60 + 25)
setTimeout(function () {
t.notOk(cache.get("b"))
t.equal(cache.get("c"), "C")
}, 90)
setTimeout(function () {
t.notOk(cache.get("c"))
t.end()
}, 155)
})
test("individual item can have it's own maxAge", function(t) {
var cache = new LRU({
max: 5,
maxAge: 50
})
cache.set("a", "A", 20)
setTimeout(function () {
t.notOk(cache.get("a"))
t.end()
}, 25)
})
test("individual item can have it's own maxAge > cache's", function(t) {
var cache = new LRU({
max: 5,
maxAge: 20
})
cache.set("a", "A", 50)
setTimeout(function () {
t.equal(cache.get("a"), "A")
t.end()
}, 25)
})
test("disposal function", function(t) {
var disposed = false
var cache = new LRU({
max: 1,
dispose: function (k, n) {
disposed = n
}
})
cache.set(1, 1)
cache.set(2, 2)
t.equal(disposed, 1)
cache.set(3, 3)
t.equal(disposed, 2)
cache.reset()
t.equal(disposed, 3)
t.end()
})
test("disposal function on too big of item", function(t) {
var disposed = false
var cache = new LRU({
max: 1,
length: function (k) {
return k.length
},
dispose: function (k, n) {
disposed = n
}
})
var obj = [ 1, 2 ]
t.equal(disposed, false)
cache.set("obj", obj)
t.equal(disposed, obj)
t.end()
})
test("has()", function(t) {
var cache = new LRU({
max: 1,
maxAge: 10
})
cache.set('foo', 'bar')
t.equal(cache.has('foo'), true)
cache.set('blu', 'baz')
t.equal(cache.has('foo'), false)
t.equal(cache.has('blu'), true)
setTimeout(function() {
t.equal(cache.has('blu'), false)
t.end()
}, 15)
})
test("stale", function(t) {
var cache = new LRU({
maxAge: 10,
stale: true
})
cache.set('foo', 'bar')
t.equal(cache.get('foo'), 'bar')
t.equal(cache.has('foo'), true)
setTimeout(function() {
t.equal(cache.has('foo'), false)
t.equal(cache.get('foo'), 'bar')
t.equal(cache.get('foo'), undefined)
t.end()
}, 15)
})
test("lru update via set", function(t) {
var cache = LRU({ max: 2 });
cache.set('foo', 1);
cache.set('bar', 2);
cache.del('bar');
cache.set('baz', 3);
cache.set('qux', 4);
t.equal(cache.get('foo'), undefined)
t.equal(cache.get('bar'), undefined)
t.equal(cache.get('baz'), 3)
t.equal(cache.get('qux'), 4)
t.end()
})
test("least recently set w/ peek", function (t) {
var cache = new LRU(2)
cache.set("a", "A")
cache.set("b", "B")
t.equal(cache.peek("a"), "A")
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("pop the least used item", function (t) {
var cache = new LRU(3)
, last
cache.set("a", "A")
cache.set("b", "B")
cache.set("c", "C")
t.equal(cache.length, 3)
t.equal(cache.max, 3)
// Ensure we pop a, c, b
cache.get("b", "B")
last = cache.pop()
t.equal(last.key, "a")
t.equal(last.value, "A")
t.equal(cache.length, 2)
t.equal(cache.max, 3)
last = cache.pop()
t.equal(last.key, "c")
t.equal(last.value, "C")
t.equal(cache.length, 1)
t.equal(cache.max, 3)
last = cache.pop()
t.equal(last.key, "b")
t.equal(last.value, "B")
t.equal(cache.length, 0)
t.equal(cache.max, 3)
last = cache.pop()
t.equal(last, null)
t.equal(cache.length, 0)
t.equal(cache.max, 3)
t.end()
})

View File

@@ -0,0 +1,120 @@
var test = require('tap').test
var LRU = require('../')
test('forEach', function (t) {
var l = new LRU(5)
for (var i = 0; i < 10; i ++) {
l.set(i.toString(), i.toString(2))
}
var i = 9
l.forEach(function (val, key, cache) {
t.equal(cache, l)
t.equal(key, i.toString())
t.equal(val, i.toString(2))
i -= 1
})
// get in order of most recently used
l.get(6)
l.get(8)
var order = [ 8, 6, 9, 7, 5 ]
var i = 0
l.forEach(function (val, key, cache) {
var j = order[i ++]
t.equal(cache, l)
t.equal(key, j.toString())
t.equal(val, j.toString(2))
})
t.equal(i, order.length);
t.end()
})
test('keys() and values()', function (t) {
var l = new LRU(5)
for (var i = 0; i < 10; i ++) {
l.set(i.toString(), i.toString(2))
}
t.similar(l.keys(), ['9', '8', '7', '6', '5'])
t.similar(l.values(), ['1001', '1000', '111', '110', '101'])
// get in order of most recently used
l.get(6)
l.get(8)
t.similar(l.keys(), ['8', '6', '9', '7', '5'])
t.similar(l.values(), ['1000', '110', '1001', '111', '101'])
t.end()
})
test('all entries are iterated over', function(t) {
var l = new LRU(5)
for (var i = 0; i < 10; i ++) {
l.set(i.toString(), i.toString(2))
}
var i = 0
l.forEach(function (val, key, cache) {
if (i > 0) {
cache.del(key)
}
i += 1
})
t.equal(i, 5)
t.equal(l.keys().length, 1)
t.end()
})
test('all stale entries are removed', function(t) {
var l = new LRU({ max: 5, maxAge: -5, stale: true })
for (var i = 0; i < 10; i ++) {
l.set(i.toString(), i.toString(2))
}
var i = 0
l.forEach(function () {
i += 1
})
t.equal(i, 5)
t.equal(l.keys().length, 0)
t.end()
})
test('expires', function (t) {
var l = new LRU({
max: 10,
maxAge: 50
})
for (var i = 0; i < 10; i++) {
l.set(i.toString(), i.toString(2), ((i % 2) ? 25 : undefined))
}
var i = 0
var order = [ 8, 6, 4, 2, 0 ]
setTimeout(function () {
l.forEach(function (val, key, cache) {
var j = order[i++]
t.equal(cache, l)
t.equal(key, j.toString())
t.equal(val, j.toString(2))
})
t.equal(i, order.length);
setTimeout(function () {
var count = 0;
l.forEach(function (val, key, cache) { count++; })
t.equal(0, count);
t.end()
}, 25)
}, 26)
})

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env node --expose_gc
var weak = require('weak');
var test = require('tap').test
var LRU = require('../')
var l = new LRU({ max: 10 })
var refs = 0
function X() {
refs ++
weak(this, deref)
}
function deref() {
refs --
}
test('no leaks', function (t) {
// fill up the cache
for (var i = 0; i < 100; i++) {
l.set(i, new X);
// throw some gets in there, too.
if (i % 2 === 0)
l.get(i / 2)
}
gc()
var start = process.memoryUsage()
// capture the memory
var startRefs = refs
// do it again, but more
for (var i = 0; i < 10000; i++) {
l.set(i, new X);
// throw some gets in there, too.
if (i % 2 === 0)
l.get(i / 2)
}
gc()
var end = process.memoryUsage()
t.equal(refs, startRefs, 'no leaky refs')
console.error('start: %j\n' +
'end: %j', start, end);
t.pass();
t.end();
})

View File

@@ -0,0 +1,216 @@
var test = require('tap').test
var LRU = require('../')
test('dump', function (t) {
var cache = new LRU()
t.equal(cache.dump().length, 0, "nothing in dump for empty cache")
cache.set("a", "A")
cache.set("b", "B")
t.deepEqual(cache.dump(), [
{ k: "b", v: "B", e: 0 },
{ k: "a", v: "A", e: 0 }
])
cache.set("a", "A");
t.deepEqual(cache.dump(), [
{ k: "a", v: "A", e: 0 },
{ k: "b", v: "B", e: 0 }
])
cache.get("b");
t.deepEqual(cache.dump(), [
{ k: "b", v: "B", e: 0 },
{ k: "a", v: "A", e: 0 }
])
cache.del("a");
t.deepEqual(cache.dump(), [
{ k: "b", v: "B", e: 0 }
])
t.end()
})
test("do not dump stale items", function(t) {
var cache = new LRU({
max: 5,
maxAge: 50
})
//expires at 50
cache.set("a", "A")
setTimeout(function () {
//expires at 75
cache.set("b", "B")
var s = cache.dump()
t.equal(s.length, 2)
t.equal(s[0].k, "b")
t.equal(s[1].k, "a")
}, 25)
setTimeout(function () {
//expires at 110
cache.set("c", "C")
var s = cache.dump()
t.equal(s.length, 2)
t.equal(s[0].k, "c")
t.equal(s[1].k, "b")
}, 60)
setTimeout(function () {
//expires at 130
cache.set("d", "D", 40)
var s = cache.dump()
t.equal(s.length, 2)
t.equal(s[0].k, "d")
t.equal(s[1].k, "c")
}, 90)
setTimeout(function () {
var s = cache.dump()
t.equal(s.length, 1)
t.equal(s[0].k, "d")
}, 120)
setTimeout(function () {
var s = cache.dump()
t.deepEqual(s, [])
t.end()
}, 155)
})
test("load basic cache", function(t) {
var cache = new LRU(),
copy = new LRU()
cache.set("a", "A")
cache.set("b", "B")
copy.load(cache.dump())
t.deepEquals(cache.dump(), copy.dump())
t.end()
})
test("load staled cache", function(t) {
var cache = new LRU({maxAge: 50}),
copy = new LRU({maxAge: 50}),
arr
//expires at 50
cache.set("a", "A")
setTimeout(function () {
//expires at 80
cache.set("b", "B")
arr = cache.dump()
t.equal(arr.length, 2)
}, 30)
setTimeout(function () {
copy.load(arr)
t.equal(copy.get("a"), undefined)
t.equal(copy.get("b"), "B")
}, 60)
setTimeout(function () {
t.equal(copy.get("b"), undefined)
t.end()
}, 90)
})
test("load to other size cache", function(t) {
var cache = new LRU({max: 2}),
copy = new LRU({max: 1})
cache.set("a", "A")
cache.set("b", "B")
copy.load(cache.dump())
t.equal(copy.get("a"), undefined)
t.equal(copy.get("b"), "B")
//update the last read from original cache
cache.get("a")
copy.load(cache.dump())
t.equal(copy.get("a"), "A")
t.equal(copy.get("b"), undefined)
t.end()
})
test("load to other age cache", function(t) {
var cache = new LRU({maxAge: 50}),
aged = new LRU({maxAge: 100}),
simple = new LRU(),
arr,
expired
//created at 0
//a would be valid till 0 + 50
cache.set("a", "A")
setTimeout(function () {
//created at 20
//b would be valid till 20 + 50
cache.set("b", "B")
//b would be valid till 20 + 70
cache.set("c", "C", 70)
arr = cache.dump()
t.equal(arr.length, 3)
}, 20)
setTimeout(function () {
t.equal(cache.get("a"), undefined)
t.equal(cache.get("b"), "B")
t.equal(cache.get("c"), "C")
aged.load(arr)
t.equal(aged.get("a"), undefined)
t.equal(aged.get("b"), "B")
t.equal(aged.get("c"), "C")
simple.load(arr)
t.equal(simple.get("a"), undefined)
t.equal(simple.get("b"), "B")
t.equal(simple.get("c"), "C")
}, 60)
setTimeout(function () {
t.equal(cache.get("a"), undefined)
t.equal(cache.get("b"), undefined)
t.equal(cache.get("c"), "C")
aged.load(arr)
t.equal(aged.get("a"), undefined)
t.equal(aged.get("b"), undefined)
t.equal(aged.get("c"), "C")
simple.load(arr)
t.equal(simple.get("a"), undefined)
t.equal(simple.get("b"), undefined)
t.equal(simple.get("c"), "C")
}, 80)
setTimeout(function () {
t.equal(cache.get("a"), undefined)
t.equal(cache.get("b"), undefined)
t.equal(cache.get("c"), undefined)
aged.load(arr)
t.equal(aged.get("a"), undefined)
t.equal(aged.get("b"), undefined)
t.equal(aged.get("c"), undefined)
simple.load(arr)
t.equal(simple.get("a"), undefined)
t.equal(simple.get("b"), undefined)
t.equal(simple.get("c"), undefined)
t.end()
}, 100)
})

View File

@@ -0,0 +1 @@
node_modules

View 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.

View File

@@ -0,0 +1,218 @@
# minimatch
A minimal matching utility.
[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](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!
minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
```
## Features
Supports these glob features:
* Brace Expansion
* Extended glob matching
* "Globstar" `**` matching
See:
* `man sh`
* `man bash`
* `man 3 fnmatch`
* `man 5 gitignore`
## 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, and
options.nonull is set, then return a list containing the pattern itself.
```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.
### flipNegate
Returns from negate expressions the same as if they were not negated.
(Ie, true on a hit, false on a miss.)
## 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.
If an escaped pattern has no matches, and the `nonull` flag is 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?"`. 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.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
{
"_from": "minimatch@~0.2.11",
"_id": "minimatch@0.2.14",
"_inBundle": false,
"_integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
"_location": "/globule/minimatch",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "minimatch@~0.2.11",
"name": "minimatch",
"escapedName": "minimatch",
"rawSpec": "~0.2.11",
"saveSpec": null,
"fetchSpec": "~0.2.11"
},
"_requiredBy": [
"/globule",
"/globule/glob"
],
"_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
"_shasum": "c74e780574f63c6f9a090e90efbe6ef53a6a756a",
"_spec": "minimatch@~0.2.11",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/globule",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me"
},
"bugs": {
"url": "https://github.com/isaacs/minimatch/issues"
},
"bundleDependencies": false,
"dependencies": {
"lru-cache": "2",
"sigmund": "~1.0.0"
},
"deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue",
"description": "a glob matcher in javascript",
"devDependencies": {
"tap": ""
},
"engines": {
"node": "*"
},
"homepage": "https://github.com/isaacs/minimatch#readme",
"license": {
"type": "MIT",
"url": "http://github.com/isaacs/minimatch/raw/master/LICENSE"
},
"main": "minimatch.js",
"name": "minimatch",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/minimatch.git"
},
"scripts": {
"test": "tap test/*.js"
},
"version": "0.2.14"
}

View File

@@ -0,0 +1,399 @@
// 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" ])
var patterns =
[ "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"]]
// negation nestled within a pattern
, function () {
files = [ "foo.js"
, "foo.bar"
// can't match this one without negative lookbehind.
, "foo.js.js"
, "blar.js"
, "foo."
, "boo.js.boo" ]
}
, ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ]
// https://github.com/isaacs/minimatch/issues/5
, function () {
files = [ 'a/b/.x/c'
, 'a/b/.x/c/d'
, 'a/b/.x/c/d/e'
, 'a/b/.x'
, 'a/b/.x/'
, 'a/.x/b'
, '.x'
, '.x/'
, '.x/a'
, '.x/a/b'
, 'a/.x/b/.x/c'
, '.x/.x' ]
}
, ["**/.x/**", [ '.x/'
, '.x/a'
, '.x/a/b'
, 'a/.x/b'
, 'a/b/.x/'
, 'a/b/.x/c'
, 'a/b/.x/c/d'
, 'a/b/.x/c/d/e' ] ]
]
var regexps =
[ '/^(?:(?=.)a[^/]*?)$/',
'/^(?:(?=.)X[^/]*?)$/',
'/^(?:(?=.)X[^/]*?)$/',
'/^(?:\\*)$/',
'/^(?:(?=.)\\*[^/]*?)$/',
'/^(?:\\*\\*)$/',
'/^(?:(?=.)b[^/]*?\\/)$/',
'/^(?:(?=.)c[^/]*?)$/',
'/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
'/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/',
'/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/',
'/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/',
'/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/',
'/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/',
'/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/',
'/^(?:(?=.)a[^/]*?[^c])$/',
'/^(?:(?=.)a[X-]b)$/',
'/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/',
'/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/',
'/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/',
'/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/',
'/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/',
'/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/',
'/^(?:(?=.)a[b]c)$/',
'/^(?:(?=.)a[b]c)$/',
'/^(?:(?=.)a[^/]c)$/',
'/^(?:a\\*c)$/',
'false',
'/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/',
'/^(?:man\\/man1\\/bash\\.1)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
'/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
'/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/',
'/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
'/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
'/^(?:(?!\\.)(?=.)[-abc])$/',
'/^(?:(?!\\.)(?=.)[abc-])$/',
'/^(?:\\\\)$/',
'/^(?:(?!\\.)(?=.)[\\\\])$/',
'/^(?:(?!\\.)(?=.)[\\[])$/',
'/^(?:\\[)$/',
'/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/',
'/^(?:(?!\\.)(?=.)[\\]])$/',
'/^(?:(?!\\.)(?=.)[\\]-])$/',
'/^(?:(?!\\.)(?=.)[a-z])$/',
'/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
'/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
'/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
'/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
'/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
'/^(?:\\[\\])$/',
'/^(?:\\[abc)$/',
'/^(?:(?=.)XYZ)$/i',
'/^(?:(?=.)ab[^/]*?)$/i',
'/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i',
'/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/',
'/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/',
'/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
'/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/',
'/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
'/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/',
'/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
'/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/',
'/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/',
'/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
'/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/',
'/^(?:(?=.)\\[(?=.)#a[^/]*?)$/',
'/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/',
'/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
'/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/',
'/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/',
'/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/',
'/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/',
'/^(?:(?=.)a[^/]b)$/',
'/^(?:(?=.)#[^/]*?)$/',
'/^(?!^(?:(?=.)a[^/]*?)$).*$/',
'/^(?:(?=.)\\!a[^/]*?)$/',
'/^(?:(?=.)a[^/]*?)$/',
'/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/',
'/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/',
'/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ]
var re = 0;
tap.test("basic tests", function (t) {
var start = Date.now()
// [ pattern, [matches], MM opts, files, TAP opts]
patterns.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()
var expectRe = regexps[re++]
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.equal(tapOpts.re, expectRe, 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
}

View 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()
})

View 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()
})

View File

@@ -0,0 +1,274 @@
// 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"]]
// negation nestled within a pattern
, function () {
files = [ "foo.js"
, "foo.bar"
// can't match this one without negative lookbehind.
, "foo.js.js"
, "blar.js"
, "foo."
, "boo.js.boo" ]
}
, ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ]
].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 Class = mm.defaults(options).Minimatch
var m = new Class(pattern, {})
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
}

View File

@@ -0,0 +1,8 @@
var test = require('tap').test
var minimatch = require('../')
test('extglob ending with statechar', function(t) {
t.notOk(minimatch('ax', 'a?(b*)'))
t.ok(minimatch('ax', '?(a*|b)'))
t.end()
})

79
build/node_modules/globule/package.json generated vendored Normal file
View File

@@ -0,0 +1,79 @@
{
"_from": "globule@~0.1.0",
"_id": "globule@0.1.0",
"_inBundle": false,
"_integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=",
"_location": "/globule",
"_phantomChildren": {
"sigmund": "1.0.1"
},
"_requested": {
"type": "range",
"registry": true,
"raw": "globule@~0.1.0",
"name": "globule",
"escapedName": "globule",
"rawSpec": "~0.1.0",
"saveSpec": null,
"fetchSpec": "~0.1.0"
},
"_requiredBy": [
"/gaze"
],
"_resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz",
"_shasum": "d9c8edde1da79d125a151b79533b978676346ae5",
"_spec": "globule@~0.1.0",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/gaze",
"author": {
"name": "\"Cowboy\" Ben Alman",
"url": "http://benalman.com/"
},
"bugs": {
"url": "https://github.com/cowboy/node-globule/issues"
},
"bundleDependencies": false,
"dependencies": {
"glob": "~3.1.21",
"lodash": "~1.0.1",
"minimatch": "~0.2.11"
},
"deprecated": false,
"description": "An easy-to-use wildcard globbing library.",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.1.1",
"grunt-contrib-nodeunit": "~0.1.2",
"grunt-contrib-watch": "~0.2.0"
},
"engines": {
"node": ">= 0.8.0"
},
"homepage": "https://github.com/cowboy/node-globule",
"keywords": [
"glob",
"file",
"match",
"mapping",
"expand",
"wildcard",
"pattern",
"sync",
"awesome"
],
"licenses": [
{
"type": "MIT",
"url": "https://github.com/cowboy/node-globule/blob/master/LICENSE-MIT"
}
],
"main": "lib/globule",
"name": "globule",
"repository": {
"type": "git",
"url": "git://github.com/cowboy/node-globule.git"
},
"scripts": {
"test": "grunt nodeunit"
},
"version": "0.1.0"
}

View File

View File

View File

View File

View File

View File

486
build/node_modules/globule/test/globule_test.js generated vendored Normal file
View File

@@ -0,0 +1,486 @@
'use strict';
var path = require('path');
var globule = require('../lib/globule.js');
/*
======== A Handy Little Nodeunit Reference ========
https://github.com/caolan/nodeunit
Test methods:
test.expect(numAssertions)
test.done()
Test assertions:
test.ok(value, [message])
test.equal(actual, expected, [message])
test.notEqual(actual, expected, [message])
test.deepEqual(actual, expected, [message])
test.notDeepEqual(actual, expected, [message])
test.strictEqual(actual, expected, [message])
test.notStrictEqual(actual, expected, [message])
test.throws(block, [error], [message])
test.doesNotThrow(block, [error], [message])
test.ifError(value)
*/
exports['match'] = {
'empty set': function(test) {
test.expect(6);
// Should return empty set if a required argument is missing or an empty set.
test.deepEqual(globule.match(null, 'foo.js'), [], 'should return empty set.');
test.deepEqual(globule.match('*.js', null), [], 'should return empty set.');
test.deepEqual(globule.match([], 'foo.js'), [], 'should return empty set.');
test.deepEqual(globule.match('*.js', []), [], 'should return empty set.');
test.deepEqual(globule.match(null, ['foo.js']), [], 'should return empty set.');
test.deepEqual(globule.match(['*.js'], null), [], 'should return empty set.');
test.done();
},
'basic matching': function(test) {
test.expect(6);
test.deepEqual(globule.match('*.js', 'foo.js'), ['foo.js'], 'should match correctly.');
test.deepEqual(globule.match('*.js', ['foo.js']), ['foo.js'], 'should match correctly.');
test.deepEqual(globule.match('*.js', ['foo.js', 'bar.css']), ['foo.js'], 'should match correctly.');
test.deepEqual(globule.match(['*.js', '*.css'], 'foo.js'), ['foo.js'], 'should match correctly.');
test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js']), ['foo.js'], 'should match correctly.');
test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js', 'bar.css']), ['foo.js', 'bar.css'], 'should match correctly.');
test.done();
},
'no matches': function(test) {
test.expect(2);
test.deepEqual(globule.match('*.js', 'foo.css'), [], 'should fail to match.');
test.deepEqual(globule.match('*.js', ['foo.css', 'bar.css']), [], 'should fail to match.');
test.done();
},
'unique': function(test) {
test.expect(2);
test.deepEqual(globule.match('*.js', ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.');
test.deepEqual(globule.match(['*.js', '*.*'], ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.');
test.done();
},
'flatten': function(test) {
test.expect(1);
test.deepEqual(globule.match([['*.js', '*.css'], ['*.*', '*.js']], ['foo.js', 'bar.css']),
['foo.js', 'bar.css'],
'should process nested pattern arrays correctly.');
test.done();
},
'exclusion': function(test) {
test.expect(5);
test.deepEqual(globule.match(['!*.js'], ['foo.js', 'bar.js']), [], 'solitary exclusion should match nothing');
test.deepEqual(globule.match(['*.js', '!*.js'], ['foo.js', 'bar.js']), [], 'exclusion should cancel match');
test.deepEqual(globule.match(['*.js', '!f*.js'], ['foo.js', 'bar.js', 'baz.js']),
['bar.js', 'baz.js'],
'partial exclusion should partially cancel match');
test.deepEqual(globule.match(['*.js', '!*.js', 'b*.js'], ['foo.js', 'bar.js', 'baz.js']),
['bar.js', 'baz.js'],
'inclusion / exclusion order matters');
test.deepEqual(globule.match(['*.js', '!f*.js', '*.js'], ['foo.js', 'bar.js', 'baz.js']),
['bar.js', 'baz.js', 'foo.js'],
'inclusion / exclusion order matters');
test.done();
},
'options.matchBase': function(test) {
test.expect(2);
test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js'], {matchBase: true}),
['foo.js', 'baz/xyz.js'],
'should matchBase (minimatch) when specified.');
test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js']),
['foo.js'],
'should not matchBase (minimatch) by default.');
test.done();
},
};
exports['isMatch'] = {
'basic matching': function(test) {
test.expect(6);
test.ok(globule.isMatch('*.js', 'foo.js'), 'should match correctly.');
test.ok(globule.isMatch('*.js', ['foo.js']), 'should match correctly.');
test.ok(globule.isMatch('*.js', ['foo.js', 'bar.css']), 'should match correctly.');
test.ok(globule.isMatch(['*.js', '*.css'], 'foo.js'), 'should match correctly.');
test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js']), 'should match correctly.');
test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js', 'bar.css']), 'should match correctly.');
test.done();
},
'no matches': function(test) {
test.expect(6);
test.ok(!globule.isMatch('*.js', 'foo.css'), 'should fail to match.');
test.ok(!globule.isMatch('*.js', ['foo.css', 'bar.css']), 'should fail to match.');
test.ok(!globule.isMatch(null, 'foo.css'), 'should fail to match.');
test.ok(!globule.isMatch('*.js', null), 'should fail to match.');
test.ok(!globule.isMatch([], 'foo.css'), 'should fail to match.');
test.ok(!globule.isMatch('*.js', []), 'should fail to match.');
test.done();
},
'options.matchBase': function(test) {
test.expect(2);
test.ok(globule.isMatch('*.js', ['baz/xyz.js'], {matchBase: true}), 'should matchBase (minimatch) when specified.');
test.ok(!globule.isMatch('*.js', ['baz/xyz.js']), 'should not matchBase (minimatch) by default.');
test.done();
},
};
exports['find'] = {
setUp: function(done) {
this.cwd = process.cwd();
process.chdir('test/fixtures/expand');
done();
},
tearDown: function(done) {
process.chdir(this.cwd);
done();
},
'basic matching': function(test) {
test.expect(5);
test.deepEqual(globule.find('**/*.js'), ['js/bar.js', 'js/foo.js'], 'single pattern argument should match.');
test.deepEqual(globule.find('**/*.js', '**/*.css'),
['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
'multiple pattern arguments should match.');
test.deepEqual(globule.find(['**/*.js', '**/*.css']),
['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
'array of patterns should match.');
test.deepEqual(globule.find([['**/*.js'], [['**/*.css', 'js/*.js']]]),
['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
'array of arrays of patterns should be flattened.');
test.deepEqual(globule.find('*.xyz'), [], 'bad pattern should fail to match.');
test.done();
},
'unique': function(test) {
test.expect(4);
test.deepEqual(globule.find('**/*.js', 'js/*.js'),
['js/bar.js', 'js/foo.js'],
'file list should be uniqed.');
test.deepEqual(globule.find('**/*.js', '**/*.css', 'js/*.js'), ['js/bar.js', 'js/foo.js',
'css/baz.css', 'css/qux.css'],
'file list should be uniqed.');
test.deepEqual(globule.find('js', 'js/'),
['js', 'js/'],
'mixed non-ending-/ and ending-/ dirs will not be uniqed by default.');
test.deepEqual(globule.find('js', 'js/', {mark: true}),
['js/'],
'mixed non-ending-/ and ending-/ dirs will be uniqed when "mark" is specified.');
test.done();
},
'file order': function(test) {
test.expect(5);
var actual = globule.find('**/*.{js,css}');
var expected = ['css/baz.css', 'css/qux.css', 'js/bar.js', 'js/foo.js'];
test.deepEqual(actual, expected, 'should select 4 files in this order, by default.');
actual = globule.find('js/foo.js', 'js/bar.js', '**/*.{js,css}');
expected = ['js/foo.js', 'js/bar.js', 'css/baz.css', 'css/qux.css'];
test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
actual = globule.find('js/bar.js', 'js/foo.js', '**/*.{js,css}');
expected = ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'];
test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
actual = globule.find('**/*.{js,css}', '!css/qux.css', 'css/qux.css');
expected = ['css/baz.css', 'js/bar.js', 'js/foo.js', 'css/qux.css'];
test.deepEqual(actual, expected, 'if a file is excluded and then re-added, it should be added at the end.');
actual = globule.find('js/foo.js', '**/*.{js,css}', '!css/qux.css', 'css/qux.css');
expected = ['js/foo.js', 'css/baz.css', 'js/bar.js', 'css/qux.css'];
test.deepEqual(actual, expected, 'should be able to combine specified-up-front and excluded/added-at-end.');
test.done();
},
'exclusion': function(test) {
test.expect(8);
test.deepEqual(globule.find(['!js/*.js']), [], 'solitary exclusion should match nothing');
test.deepEqual(globule.find(['js/bar.js','!js/bar.js']), [], 'exclusion should negate match');
test.deepEqual(globule.find(['**/*.js', '!js/foo.js']),
['js/bar.js'],
'should omit single file from matched set');
test.deepEqual(globule.find(['!js/foo.js', '**/*.js']),
['js/bar.js', 'js/foo.js'],
'inclusion / exclusion order matters');
test.deepEqual(globule.find(['**/*.js', '**/*.css', '!js/bar.js', '!css/baz.css']),
['js/foo.js','css/qux.css'],
'multiple exclusions should be removed from the set');
test.deepEqual(globule.find(['**/*.js', '**/*.css', '!**/*.css']),
['js/bar.js', 'js/foo.js'],
'excluded wildcards should be removed from the matched set');
test.deepEqual(globule.find(['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css', '!**/b*.*']),
['js/foo.js', 'css/qux.css'],
'different pattern for exclusion should still work');
test.deepEqual(globule.find(['js/bar.js', '!**/b*.*', 'js/foo.js', 'css/baz.css', 'css/qux.css']),
['js/foo.js', 'css/baz.css', 'css/qux.css'],
'inclusion / exclusion order matters');
test.done();
},
'options.mark': function(test) {
test.expect(4);
test.deepEqual(globule.find('**d*/**'), [
'deep',
'deep/deep.txt',
'deep/deeper',
'deep/deeper/deeper.txt',
'deep/deeper/deepest',
'deep/deeper/deepest/deepest.txt'], 'should match files and directories.');
test.deepEqual(globule.find('**d*/**/'), [
'deep/',
'deep/deeper/',
'deep/deeper/deepest/'], 'trailing / in pattern should match directories only, matches end in /.');
test.deepEqual(globule.find('**d*/**', {mark: true}), [
'deep/',
'deep/deep.txt',
'deep/deeper/',
'deep/deeper/deeper.txt',
'deep/deeper/deepest/',
'deep/deeper/deepest/deepest.txt'], 'the minimatch "mark" option ensures directories end in /.');
test.deepEqual(globule.find('**d*/**/', {mark: true}), [
'deep/',
'deep/deeper/',
'deep/deeper/deepest/'], 'the minimatch "mark" option should not remove trailing / from matched paths.');
test.done();
},
'options.filter': function(test) {
test.expect(5);
test.deepEqual(globule.find('**d*/**', {filter: 'isFile'}), [
'deep/deep.txt',
'deep/deeper/deeper.txt',
'deep/deeper/deepest/deepest.txt'
], 'should match files only.');
test.deepEqual(globule.find('**d*/**', {filter: 'isDirectory'}), [
'deep',
'deep/deeper',
'deep/deeper/deepest'
], 'should match directories only.');
test.deepEqual(globule.find('**', {
arbitraryProp: /deepest/,
filter: function(filepath, options) {
return options.arbitraryProp.test(filepath);
}
}), [
'deep/deeper/deepest',
'deep/deeper/deepest/deepest.txt',
], 'should filter arbitrarily.');
test.deepEqual(globule.find('js', 'css', {filter: 'isFile'}), [], 'should fail to match.');
test.deepEqual(globule.find('**/*.js', {filter: 'isDirectory'}), [], 'should fail to match.');
test.done();
},
'options.matchBase': function(test) {
test.expect(3);
test.deepEqual(globule.find('*.js'), [], 'should not matchBase (minimatch) by default.');
test.deepEqual(globule.find('*.js', {matchBase: true}),
['js/bar.js', 'js/foo.js'],
'matchBase option should be passed through to minimatch.');
test.deepEqual(globule.find('*.js', '*.css', {matchBase: true}),
['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
'matchBase option should be passed through to minimatch.');
test.done();
},
'options.srcBase': function(test) {
test.expect(5);
test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep'}),
['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
'should find paths matching pattern relative to srcBase.');
test.deepEqual(globule.find(['**/deep*.txt'], {cwd: 'deep'}),
['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
'cwd and srcBase should do the same thing.');
test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isFile'}),
['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
'srcBase should not prevent filtering.');
test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isDirectory'}),
['deeper', 'deeper/deepest'],
'srcBase should not prevent filtering.');
test.deepEqual(globule.find(['**/deep*.txt', '!**/deeper**'], {srcBase: 'deep'}),
['deep.txt', 'deeper/deepest/deepest.txt'],
'srcBase should not prevent exclusions.');
test.done();
},
'options.prefixBase': function(test) {
test.expect(2);
test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: false}),
['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
'should not prefix srcBase to returned paths.');
test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: true}),
['deep/deep.txt', 'deep/deeper/deeper.txt', 'deep/deeper/deepest/deepest.txt'],
'should prefix srcBase to returned paths.');
test.done();
},
'options.nonull': function(test) {
test.expect(3);
test.deepEqual(globule.find(['*omg*'], {nonull: true}),
['*omg*'],
'non-matching patterns should be returned in result set.');
test.deepEqual(globule.find(['js/a*', 'js/b*', 'js/c*'], {nonull: true}),
['js/a*', 'js/bar.js', 'js/c*'],
'non-matching patterns should be returned in result set.');
test.deepEqual(globule.find(['js/foo.js', 'js/bar.js', 'js/nonexistent.js'], {nonull: true}),
['js/foo.js', 'js/bar.js', 'js/nonexistent.js'],
'non-matching filenames should be returned in result set.');
test.done();
},
};
exports['mapping'] = {
'basic mapping': function(test) {
test.expect(1);
var actual = globule.mapping(['a.txt', 'b.txt', 'c.txt']);
var expected = [
{dest: 'a.txt', src: ['a.txt']},
{dest: 'b.txt', src: ['b.txt']},
{dest: 'c.txt', src: ['c.txt']},
];
test.deepEqual(actual, expected, 'default options should create same-to-same src-dest mappings.');
test.done();
},
'options.srcBase': function(test) {
test.expect(2);
var actual, expected;
actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo'});
expected = [
{dest: 'a.txt', src: ['foo/a.txt']},
{dest: 'bar/b.txt', src: ['foo/bar/b.txt']},
{dest: 'bar/baz/c.txt', src: ['foo/bar/baz/c.txt']},
];
test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (no trailing /).');
actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo/'});
test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (trailing /).');
test.done();
},
'options.destBase': function(test) {
test.expect(2);
var actual, expected;
actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest'});
expected = [
{dest: 'dest/a.txt', src: ['a.txt']},
{dest: 'dest/bar/b.txt', src: ['bar/b.txt']},
{dest: 'dest/bar/baz/c.txt', src: ['bar/baz/c.txt']},
];
test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (no trailing /).');
actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest/'});
test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (trailing /).');
test.done();
},
'options.flatten': function(test) {
test.expect(1);
var actual, expected;
actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {flatten: true});
expected = [
{dest: 'a.txt', src: ['a.txt']},
{dest: 'b.txt', src: ['bar/b.txt']},
{dest: 'c.txt', src: ['bar/baz/c.txt']},
];
test.deepEqual(actual, expected, 'flatten should remove all src path parts from dest.');
test.done();
},
'options.flatten + options.destBase': function(test) {
test.expect(1);
var actual, expected;
actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest', flatten: true});
expected = [
{dest: 'dest/a.txt', src: ['a.txt']},
{dest: 'dest/b.txt', src: ['bar/b.txt']},
{dest: 'dest/c.txt', src: ['bar/baz/c.txt']},
];
test.deepEqual(actual, expected, 'flatten and destBase should work together.');
test.done();
},
'options.ext': function(test) {
test.expect(1);
var actual, expected;
actual = globule.mapping(['x/a.js', 'x.y/b.min.js', 'x.y/z.z/c'], {ext: '.foo'});
expected = [
{dest: 'x/a.foo', src: ['x/a.js']},
{dest: 'x.y/b.foo', src: ['x.y/b.min.js']},
{dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
];
test.deepEqual(actual, expected, 'by default, ext should replace everything after the first dot in the filename.');
test.done();
},
'options.extDot': function(test) {
test.expect(2);
var actual, expected;
actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'first'});
expected = [
{dest: 'x/a.foo', src: ['x/a.js']},
{dest: 'x.y/b.foo', src: ['x.y/b.bbb.min.js']},
{dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
];
test.deepEqual(actual, expected, 'extDot of "first" should replace everything after the first dot in the filename.');
actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'last'});
expected = [
{dest: 'x/a.foo', src: ['x/a.js']},
{dest: 'x.y/b.bbb.min.foo', src: ['x.y/b.bbb.min.js']},
{dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
];
test.deepEqual(actual, expected, 'extDot of "last" should replace everything after the last dot in the filename.');
test.done();
},
'options.rename': function(test) {
test.expect(1);
var actual, expected;
actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {
arbitraryProp: 'FOO',
rename: function(dest, options) {
return path.join(options.arbitraryProp, dest.toUpperCase());
}
});
expected = [
{dest: 'FOO/A.TXT', src: ['a.txt']},
{dest: 'FOO/BAR/B.TXT', src: ['bar/b.txt']},
{dest: 'FOO/BAR/BAZ/C.TXT', src: ['bar/baz/c.txt']},
];
test.deepEqual(actual, expected, 'allow arbitrary renaming of files.');
test.done();
},
};
exports['findMapping'] = {
setUp: function(done) {
this.cwd = process.cwd();
process.chdir('test/fixtures');
done();
},
tearDown: function(done) {
process.chdir(this.cwd);
done();
},
'basic matching': function(test) {
test.expect(2);
var actual = globule.findMapping(['expand/**/*.txt']);
var expected = [
{dest: 'expand/deep/deep.txt', src: ['expand/deep/deep.txt']},
{dest: 'expand/deep/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
{dest: 'expand/deep/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
];
test.deepEqual(actual, expected, 'default options');
expected = globule.mapping(globule.find(['expand/**/*.txt']));
test.deepEqual(actual, expected, 'this is what it\'s doing under the hood, anwyays.');
test.done();
},
'options.srcBase': function(test) {
test.expect(1);
var actual = globule.findMapping(['**/*.txt'], {destBase: 'dest', srcBase: 'expand/deep'});
var expected = [
{dest: 'dest/deep.txt', src: ['expand/deep/deep.txt']},
{dest: 'dest/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
{dest: 'dest/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
];
test.deepEqual(actual, expected, 'srcBase should be stripped from front of destPath, pre-destBase+destPath join');
test.done();
},
};