Nettoyage exercices
This commit is contained in:
parent
c645af4112
commit
f4e96ea040
|
@ -0,0 +1,6 @@
|
||||||
|
# Exemple Linting avec JSHint
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
./node_modules/.bin/jshint bad.js
|
||||||
|
```
|
|
@ -1 +0,0 @@
|
||||||
../jshint/bin/jshint
|
|
|
@ -1,20 +0,0 @@
|
||||||
Copyright 2012 Anton Kovalyov (http://jshint.com)
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,56 +0,0 @@
|
||||||
# JSHint, A Static Code Analysis Tool for JavaScript
|
|
||||||
|
|
||||||
\[ [Use it online](http://jshint.com/) • [About](http://jshint.com/about/) •
|
|
||||||
[Docs](http://jshint.com/docs/) • [FAQ](http://jshint.com/docs/faq) •
|
|
||||||
[Install](http://jshint.com/install/) • [Hack](http://jshint.com/hack/) •
|
|
||||||
[Blog](http://jshint.com/blog/) • [Twitter](https://twitter.com/jshint/) \]
|
|
||||||
|
|
||||||
[![NPM version](https://img.shields.io/npm/v/jshint.svg?style=flat)](https://www.npmjs.com/package/jshint)
|
|
||||||
[![Linux Build Status](https://img.shields.io/travis/jshint/jshint/master.svg?style=flat&label=Linux%20build)](https://travis-ci.org/jshint/jshint)
|
|
||||||
[![Windows Build status](https://img.shields.io/appveyor/ci/jshint/jshint/master.svg?style=flat&label=Windows%20build)](https://ci.appveyor.com/project/jshint/jshint/branch/master)
|
|
||||||
[![Dependency Status](https://img.shields.io/david/jshint/jshint.svg?style=flat)](https://david-dm.org/jshint/jshint)
|
|
||||||
[![devDependency Status](https://img.shields.io/david/dev/jshint/jshint.svg?style=flat)](https://david-dm.org/jshint/jshint#info=devDependencies)
|
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/jshint/jshint.svg?style=flat)](https://coveralls.io/r/jshint/jshint?branch=master)
|
|
||||||
|
|
||||||
JSHint is a community-driven tool to detect errors and potential problems
|
|
||||||
in JavaScript code. It is very flexible so you can easily adjust it to your
|
|
||||||
particular coding guidelines and the environment you expect your code to
|
|
||||||
execute in.
|
|
||||||
|
|
||||||
## Reporting a bug
|
|
||||||
|
|
||||||
To report a bug simply create a
|
|
||||||
[new GitHub Issue](https://github.com/jshint/jshint/issues/new) and describe
|
|
||||||
your problem or suggestion. We welcome all kind of feedback regarding
|
|
||||||
JSHint including but not limited to:
|
|
||||||
|
|
||||||
* When JSHint doesn't work as expected
|
|
||||||
* When JSHint complains about valid JavaScript code that works in all browsers
|
|
||||||
* When you simply want a new option or feature
|
|
||||||
|
|
||||||
Before reporting a bug look around to see if there are any open or closed tickets
|
|
||||||
that cover your issue. And remember the wisdom: pull request > bug report > tweet.
|
|
||||||
|
|
||||||
## Issue Priority
|
|
||||||
|
|
||||||
- *P1:* Something is throwing exceptions; broken JSHint backward compatibility.
|
|
||||||
- *P2:* Something is not being parsed correctly.
|
|
||||||
- *P3:* Features that the core team will work on once P2s and P1s are done.
|
|
||||||
- *P4:* Patches welcome; The request is good, but low priority.
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
JSHint is distributed under the MIT License. One file and one file only
|
|
||||||
(src/stable/jshint.js) is distributed under the slightly modified MIT License.
|
|
||||||
|
|
||||||
## The JSHint Team
|
|
||||||
|
|
||||||
JSHint is maintained by [Rick Waldron](https://github.com/rwaldron/), [Caitlin
|
|
||||||
Potter](https://github.com/caitp/), [Mike
|
|
||||||
Sherov](https://github.com/mikesherov/), and [Mike
|
|
||||||
Pennisi](https://github.com/jugglinmike/).
|
|
||||||
|
|
||||||
## Thank you!
|
|
||||||
|
|
||||||
We really appreciate all kind of feedback and contributions. Thanks for using and supporting JSHint!
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var shjs = require("shelljs");
|
|
||||||
var url = "https://github.com/jshint/jshint/pull/" + process.argv[2] + ".diff";
|
|
||||||
|
|
||||||
shjs.exec('curl "' + url + '" | git apply');
|
|
|
@ -1,38 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
/*jshint shelljs:true */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var browserify = require("browserify");
|
|
||||||
var bundle = browserify();
|
|
||||||
var path = require("path");
|
|
||||||
var version = require("../package.json").version;
|
|
||||||
require("shelljs/make");
|
|
||||||
|
|
||||||
var distDir = path.join(__dirname, "../dist");
|
|
||||||
var srcDir = path.join(__dirname, "../src");
|
|
||||||
|
|
||||||
if (!test("-e", distDir))
|
|
||||||
mkdir(distDir);
|
|
||||||
|
|
||||||
bundle.require(srcDir + "/jshint.js", { expose: "jshint" });
|
|
||||||
bundle.bundle(function (err, src) {
|
|
||||||
var web = distDir + "/jshint.js";
|
|
||||||
var rhino = distDir + "/jshint-rhino.js";
|
|
||||||
|
|
||||||
[ "/*! " + version + " */",
|
|
||||||
"var JSHINT;",
|
|
||||||
"if (typeof window === 'undefined') window = {};",
|
|
||||||
"(function () {",
|
|
||||||
"var require;",
|
|
||||||
src,
|
|
||||||
"JSHINT = require('jshint').JSHINT;",
|
|
||||||
"if (typeof exports === 'object' && exports) exports.JSHINT = JSHINT;",
|
|
||||||
"}());"
|
|
||||||
].join("\n").to(web);
|
|
||||||
|
|
||||||
("#!/usr/bin/env rhino\nvar window = {};\n" + cat(web, srcDir + "/platforms/rhino.js")).to(rhino);
|
|
||||||
chmod("+x", rhino);
|
|
||||||
|
|
||||||
echo("Built: " + version);
|
|
||||||
});
|
|
|
@ -1,39 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
/*jshint shelljs:true, lastsemic:true, -W101*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var version = require("../package.json").version;
|
|
||||||
require("shelljs/make");
|
|
||||||
|
|
||||||
exec("git log --format='%H|%h|%an|%s' " + version + "..HEAD", { silent: true }, function (code, output) {
|
|
||||||
if (code !== 0)
|
|
||||||
return void console.log("git log return code is non-zero");
|
|
||||||
|
|
||||||
var commits = output.split("\n")
|
|
||||||
.filter(function (cmt) { return cmt.trim() !== ""; })
|
|
||||||
.map(function (cmt) { return cmt.split("|"); });
|
|
||||||
|
|
||||||
var html = "";
|
|
||||||
var authors = {};
|
|
||||||
|
|
||||||
commits.forEach(function (cmt) {
|
|
||||||
if (cmt[3].indexOf("Merge") === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var tr = "";
|
|
||||||
tr += "<td class='commit'><a href='https://github.com/jshint/jshint/commit/" + cmt[0] + "'>" + cmt[1] + "</a></td>";
|
|
||||||
tr += "<td class='desc'>" + cmt[3].replace(/(#(\d+))/, "<a href='https://github.com/jshint/jshint/issues/$2/'>$1</a>") + "</td>";
|
|
||||||
html += "<tr>" + tr + "</tr>\n";
|
|
||||||
|
|
||||||
if (cmt[2] !== "Anton Kovalyov")
|
|
||||||
authors[cmt[2]] = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
echo("<!-- auto-generated -->");
|
|
||||||
echo("<table class='changelog'>\n" + html + "</table>\n");
|
|
||||||
|
|
||||||
if (Object.keys(authors).length) {
|
|
||||||
echo("<p class='thx'><strong>Thanks</strong> to " + Object.keys(authors).join(", ") + " for sending patches!</p>");
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require("../src/cli.js").interpret(process.argv);
|
|
|
@ -1,36 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var url = "https://github.com/jshint/jshint/pull/" + process.argv[2] + ".patch";
|
|
||||||
var https = require("https");
|
|
||||||
var shjs = require("shelljs");
|
|
||||||
var opts = require("url").parse(url);
|
|
||||||
var msg = process.argv[3];
|
|
||||||
|
|
||||||
opts.rejectUnauthorized = false;
|
|
||||||
opts.agent = new https.Agent(opts);
|
|
||||||
|
|
||||||
https.get(opts, succ).on("error", err);
|
|
||||||
|
|
||||||
function succ(res) {
|
|
||||||
if (res.statusCode !== 200)
|
|
||||||
return void console.log("error:", res.statusCode);
|
|
||||||
|
|
||||||
var data = "";
|
|
||||||
res.on("data", function (chunk) {
|
|
||||||
data += chunk.toString();
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("end", function () {
|
|
||||||
data = data.split("\n");
|
|
||||||
data = data[1].replace(/^From\:\s/, "");
|
|
||||||
data = data.replace(/"/g, "");
|
|
||||||
|
|
||||||
shjs.exec("git commit -s --author=\"" + data + "\" --message=\"" + msg + "\"");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function err(res) {
|
|
||||||
console.log("error:", res.message);
|
|
||||||
}
|
|
22
javascript/base/exercices/linting/node_modules/jshint/data/ascii-identifier-data.js
generated
vendored
22
javascript/base/exercices/linting/node_modules/jshint/data/ascii-identifier-data.js
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
var identifierStartTable = [];
|
|
||||||
|
|
||||||
for (var i = 0; i < 128; i++) {
|
|
||||||
identifierStartTable[i] =
|
|
||||||
i === 36 || // $
|
|
||||||
i >= 65 && i <= 90 || // A-Z
|
|
||||||
i === 95 || // _
|
|
||||||
i >= 97 && i <= 122; // a-z
|
|
||||||
}
|
|
||||||
|
|
||||||
var identifierPartTable = [];
|
|
||||||
|
|
||||||
for (var i = 0; i < 128; i++) {
|
|
||||||
identifierPartTable[i] =
|
|
||||||
identifierStartTable[i] || // $, _, A-Z, a-z
|
|
||||||
i >= 48 && i <= 57; // 0-9
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
asciiIdentifierStartTable: identifierStartTable,
|
|
||||||
asciiIdentifierPartTable: identifierPartTable
|
|
||||||
};
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
||||||
../shelljs/bin/shjs
|
|
|
@ -1 +0,0 @@
|
||||||
../strip-json-comments/cli.js
|
|
196
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/README.md
generated
vendored
196
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/README.md
generated
vendored
|
@ -1,196 +0,0 @@
|
||||||
**cli is a toolkit for rapidly building command line apps - it includes:**
|
|
||||||
|
|
||||||
- Full featured opts/args parser
|
|
||||||
- Plugin support for adding common options and switches
|
|
||||||
- Helper methods for working with input/output and spawning child processes
|
|
||||||
- Output colored/styled messages, [progress bars](https://github.com/chriso/cli/blob/master/examples/progress.js) or [spinners](https://github.com/chriso/cli/blob/master/examples/spinner.js)
|
|
||||||
- Command [auto-completion](https://github.com/chriso/cli/blob/master/examples/command.js) and [glob support](https://github.com/chriso/cli/blob/master/examples/glob.js)
|
|
||||||
|
|
||||||
Install using `npm install cli` or just bundle [cli.js](https://github.com/chriso/cli/raw/master/cli.js) with your app.
|
|
||||||
|
|
||||||
## Example apps
|
|
||||||
|
|
||||||
### sort.js
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
#!/usr/bin/env node
|
|
||||||
require('cli').withStdinLines(function(lines, newline) {
|
|
||||||
this.output(lines.sort().join(newline));
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Try it out
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ./sort.js < input.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
Let's add support for an `-n` switch to use a numeric sort, and a `-r` switch to reverse output - only 5 extra lines of code (!)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var cli = require('cli'), options = cli.parse();
|
|
||||||
|
|
||||||
cli.withStdinLines(function(lines, newline) {
|
|
||||||
lines.sort(!options.n ? null : function(a, b) {
|
|
||||||
return parseInt(a) > parseInt(b);
|
|
||||||
});
|
|
||||||
if (options.r) lines.reverse();
|
|
||||||
this.output(lines.join(newline));
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### static.js
|
|
||||||
|
|
||||||
Let's create a static file server with daemon support to see the opts parser + plugins in use - note: this requires `npm install creationix daemon`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var cli = require('cli').enable('daemon', 'status'); //Enable 2 plugins
|
|
||||||
|
|
||||||
cli.parse({
|
|
||||||
log: ['l', 'Enable logging'],
|
|
||||||
port: ['p', 'Listen on this port', 'number', 8080],
|
|
||||||
serve: [false, 'Serve static files from PATH', 'path', './public']
|
|
||||||
});
|
|
||||||
|
|
||||||
cli.main(function(args, options) {
|
|
||||||
var server, middleware = [];
|
|
||||||
|
|
||||||
if (options.log) {
|
|
||||||
this.debug('Enabling logging');
|
|
||||||
middleware.push(require('creationix/log')());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.debug('Serving files from ' + options.serve);
|
|
||||||
middleware.push(require('creationix/static')('/', options.serve, 'index.html'));
|
|
||||||
|
|
||||||
server = this.createServer(middleware).listen(options.port);
|
|
||||||
|
|
||||||
this.ok('Listening on port ' + options.port);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
To output usage information
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ./static.js --help
|
|
||||||
```
|
|
||||||
|
|
||||||
To create a daemon that serves files from */tmp*, run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ./static.js -ld --serve=/tmp
|
|
||||||
```
|
|
||||||
|
|
||||||
For more examples, see [./examples](https://github.com/chriso/cli/tree/master/examples)
|
|
||||||
|
|
||||||
## Helper methods
|
|
||||||
|
|
||||||
cli has methods that collect stdin (newline is autodetected as \n or \r\n)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cli.withStdin(callback); //callback receives stdin as a string
|
|
||||||
cli.withStdinLines(callback); //callback receives stdin split into an array of lines (lines, newline)
|
|
||||||
```
|
|
||||||
|
|
||||||
cli also has a lower level method for working with input line by line (see [./examples/cat.js](https://github.com/chriso/cli/blob/master/examples/cat.js) for an example).
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cli.withInput(file, function (line, newline, eof) {
|
|
||||||
if (!eof) {
|
|
||||||
this.output(line + newline);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
*Note: `file` can be omitted if you want to work with stdin*
|
|
||||||
|
|
||||||
To output a progress bar, call
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cli.progress(progress); //Where 0 <= progress <= 1
|
|
||||||
```
|
|
||||||
|
|
||||||
To spawn a child process, use
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cli.exec(cmd, callback); //callback receives the output of the process (split into lines)
|
|
||||||
```
|
|
||||||
|
|
||||||
cli also comes bundled with kof's [node-natives](https://github.com/kof/node-natives) (access with cli.native) and creationix' [stack](https://github.com/creationix/stack) (access with cli.createServer)
|
|
||||||
|
|
||||||
## Plugins
|
|
||||||
|
|
||||||
Plugins are a way of adding common opts and can be enabled using
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cli.enable(plugin1, [plugin2, ...]); //To disable, use the equivalent disable() method
|
|
||||||
```
|
|
||||||
|
|
||||||
**help** - *enabled by default*
|
|
||||||
|
|
||||||
Adds `-h,--help` to output auto-generated usage information
|
|
||||||
|
|
||||||
**version**
|
|
||||||
|
|
||||||
Adds `-v,--version` to output version information for the app. cli will attempt to locate and parse a nearby *package.json*
|
|
||||||
|
|
||||||
To set your own app name and version, use `cli.setApp(app_name, version)`
|
|
||||||
|
|
||||||
**status**
|
|
||||||
|
|
||||||
Adds options to show/hide the stylized status messages that are output to the console when using one of these methods
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
cli.debug(msg); //Only shown when using --debug
|
|
||||||
cli.error(msg);
|
|
||||||
cli.fatal(msg); //Exits the process after outputting msg
|
|
||||||
cli.info(msg);
|
|
||||||
cli.ok(msg);
|
|
||||||
```
|
|
||||||
|
|
||||||
`-k,--no-color` will omit ANSI color escapes from the output
|
|
||||||
|
|
||||||
**glob** - *requires* `npm install glob`
|
|
||||||
|
|
||||||
Enables glob matching of arguments
|
|
||||||
|
|
||||||
**daemon** - *requires* `npm install daemon`
|
|
||||||
|
|
||||||
Adds `-d,--daemon ARG` for daemonizing the process and controlling the resulting daemon
|
|
||||||
|
|
||||||
`ARG` can be either start (default), stop, restart, pid (outputs the daemon's pid if it's running), or log (output the daemon's stdout+stderr)
|
|
||||||
|
|
||||||
**timeout**
|
|
||||||
|
|
||||||
Adds `-t,--timeout N` to exit the process after N seconds with an error
|
|
||||||
|
|
||||||
**catchall**
|
|
||||||
|
|
||||||
Adds `-c,--catch` to catch and output uncaughtExceptions and resume execution
|
|
||||||
|
|
||||||
*Note: Plugins are automatically disabled if an option or switch of the same name is already defined*
|
|
||||||
|
|
||||||
## LICENSE
|
|
||||||
|
|
||||||
(MIT license)
|
|
||||||
|
|
||||||
Copyright (c) 2010 Chris O'Hara <cohara87@gmail.com>
|
|
||||||
|
|
||||||
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.
|
|
1152
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/cli.js
generated
vendored
1152
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/cli.js
generated
vendored
|
@ -1,1152 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2010 Chris O'Hara <cohara87@gmail.com>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//Note: cli includes kof/node-natives and creationix/stack. I couldn't find
|
|
||||||
//license information for either - contact me if you want your license added
|
|
||||||
|
|
||||||
var cli = exports,
|
|
||||||
argv, curr_opt, curr_val, full_opt, is_long,
|
|
||||||
short_tags = [], opt_list, parsed = {},
|
|
||||||
usage, argv_parsed, command_list, commands,
|
|
||||||
daemon, daemon_arg, no_color, show_debug;
|
|
||||||
|
|
||||||
cli.app = null;
|
|
||||||
cli.version = null;
|
|
||||||
cli.argv = [];
|
|
||||||
cli.argc = 0;
|
|
||||||
|
|
||||||
cli.options = {};
|
|
||||||
cli.args = [];
|
|
||||||
cli.command = null;
|
|
||||||
|
|
||||||
cli.width = 70;
|
|
||||||
cli.option_width = 25;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind kof's node-natives (https://github.com/kof/node-natives) to `cli.native`
|
|
||||||
*
|
|
||||||
* Rather than requiring node natives (e.g. var fs = require('fs')), all
|
|
||||||
* native modules can be accessed like `cli.native.fs`
|
|
||||||
*/
|
|
||||||
cli.native = {};
|
|
||||||
var define_native = function (module) {
|
|
||||||
Object.defineProperty(cli.native, module, {
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true,
|
|
||||||
get: function() {
|
|
||||||
delete cli.native[module];
|
|
||||||
return (cli.native[module] = require(module));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var natives = process.binding('natives');
|
|
||||||
for (var module in natives) {
|
|
||||||
define_native(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
cli.output = console.log;
|
|
||||||
cli.exit = require('exit');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define plugins. Plugins can be enabled and disabled by calling:
|
|
||||||
*
|
|
||||||
* `cli.enable(plugin1, [plugin2, ...])`
|
|
||||||
* `cli.disable(plugin1, [plugin2, ...])`
|
|
||||||
*
|
|
||||||
* Methods are chainable - `cli.enable(plugin).disable(plugin2)`.
|
|
||||||
*
|
|
||||||
* The 'help' plugin is enabled by default.
|
|
||||||
*/
|
|
||||||
var enable = {
|
|
||||||
help: true, //Adds -h, --help
|
|
||||||
version: false, //Adds -v,--version => gets version by parsing a nearby package.json
|
|
||||||
daemon: false, //Adds -d,--daemon [ARG] => (see cli.daemon() below)
|
|
||||||
status: false, //Adds -k,--no-color & --debug => display plain status messages /display debug messages
|
|
||||||
timeout: false, //Adds -t,--timeout N => timeout the process after N seconds
|
|
||||||
catchall: false, //Adds -c,--catch => catch and output uncaughtExceptions
|
|
||||||
glob: false //Adds glob matching => use cli.glob(arg)
|
|
||||||
}
|
|
||||||
cli.enable = function (/*plugins*/) {
|
|
||||||
Array.prototype.slice.call(arguments).forEach(function (plugin) {
|
|
||||||
switch (plugin) {
|
|
||||||
case 'daemon':
|
|
||||||
try {
|
|
||||||
daemon = require('daemon');
|
|
||||||
if (typeof daemon.daemonize !== 'function') {
|
|
||||||
throw 'Invalid module';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
cli.fatal('daemon.node not installed. Please run `npm install daemon`');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'catchall':
|
|
||||||
process.on('uncaughtException', function (err) {
|
|
||||||
cli.error('Uncaught exception: ' + (err.msg || err));
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'help': case 'version': case 'status':
|
|
||||||
case 'autocomplete': case 'timeout':
|
|
||||||
//Just add switches.
|
|
||||||
break;
|
|
||||||
case 'glob':
|
|
||||||
cli.glob = require('glob');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cli.fatal('Unknown plugin "' + plugin + '"');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
enable[plugin] = true;
|
|
||||||
});
|
|
||||||
return cli;
|
|
||||||
}
|
|
||||||
cli.disable = function (/*plugins*/) {
|
|
||||||
Array.prototype.slice.call(arguments).forEach(function (plugin) {
|
|
||||||
if (enable[plugin]) {
|
|
||||||
enable[plugin] = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return cli;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets argv (default is process.argv).
|
|
||||||
*
|
|
||||||
* @param {Array|String} argv
|
|
||||||
* @param {Boolean} keep_arg0 (optional - default is false)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.setArgv = function (arr, keep_arg0) {
|
|
||||||
if (typeof arr == 'string') {
|
|
||||||
arr = arr.split(' ');
|
|
||||||
} else {
|
|
||||||
arr = arr.slice();
|
|
||||||
}
|
|
||||||
cli.app = arr.shift();
|
|
||||||
// Strip off argv[0] if it's a node binary
|
|
||||||
// So this is still broken and will break if you are calling node through a
|
|
||||||
// symlink, unless you are lucky enough to have it as 'node' literal. Latter
|
|
||||||
// is a hack, but resolving abspaths/symlinks is an unportable can of worms.
|
|
||||||
if (!keep_arg0 && (['node', 'node.exe'].indexOf(cli.native.path.basename(cli.app)) !== -1
|
|
||||||
|| cli.native.path.basename(process.execPath) === cli.app
|
|
||||||
|| process.execPath === cli.app)) {
|
|
||||||
cli.app = arr.shift();
|
|
||||||
}
|
|
||||||
cli.app = cli.native.path.basename(cli.app);
|
|
||||||
argv_parsed = false;
|
|
||||||
cli.args = cli.argv = argv = arr;
|
|
||||||
cli.argc = argv.length;
|
|
||||||
cli.options = {};
|
|
||||||
cli.command = null;
|
|
||||||
};
|
|
||||||
cli.setArgv(process.argv);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next opt, or false if no opts are found.
|
|
||||||
*
|
|
||||||
* @return {String} opt
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.next = function () {
|
|
||||||
if (!argv_parsed) {
|
|
||||||
cli.args = [];
|
|
||||||
argv_parsed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
curr_val = null;
|
|
||||||
|
|
||||||
//If we're currently in a group of short opts (e.g. -abc), return the next opt
|
|
||||||
if (short_tags.length) {
|
|
||||||
curr_opt = short_tags.shift();
|
|
||||||
full_opt = '-' + curr_opt;
|
|
||||||
return curr_opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!argv.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
curr_opt = argv.shift();
|
|
||||||
|
|
||||||
//If an escape sequence is found (- or --), subsequent opts are ignored
|
|
||||||
if (curr_opt === '-' || curr_opt === '--') {
|
|
||||||
while (argv.length) {
|
|
||||||
cli.args.push(argv.shift());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If the next element in argv isn't an opt, add it to the list of args
|
|
||||||
if (curr_opt[0] !== '-') {
|
|
||||||
cli.args.push(curr_opt);
|
|
||||||
return cli.next();
|
|
||||||
} else {
|
|
||||||
//Check if the opt is short/long
|
|
||||||
is_long = curr_opt[1] === '-';
|
|
||||||
curr_opt = curr_opt.substr(is_long ? 2 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Accept grouped short opts, e.g. -abc => -a -b -c
|
|
||||||
if (!is_long && curr_opt.length > 1) {
|
|
||||||
short_tags = curr_opt.split('');
|
|
||||||
return cli.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
var eq, len;
|
|
||||||
|
|
||||||
//Check if the long opt is in the form --option=VALUE
|
|
||||||
if (is_long && (eq = curr_opt.indexOf('=')) >= 0) {
|
|
||||||
curr_val = curr_opt.substr(eq + 1);
|
|
||||||
curr_opt = curr_opt.substr(0, eq);
|
|
||||||
len = curr_val.length;
|
|
||||||
//Allow values to be quoted
|
|
||||||
if ((curr_val[0] === '"' && curr_val[len - 1] === '"') ||
|
|
||||||
(curr_val[0] === "'" && curr_val[len - 1] === "'"))
|
|
||||||
{
|
|
||||||
curr_val = curr_val.substr(1, len-2);
|
|
||||||
}
|
|
||||||
if (curr_val.match(/^[0-9]+$/)) {
|
|
||||||
curr_val = parseInt(curr_val, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Save the opt representation for later
|
|
||||||
full_opt = (is_long ? '--' : '-') + curr_opt;
|
|
||||||
|
|
||||||
return curr_opt;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses command line opts.
|
|
||||||
*
|
|
||||||
* `opts` must be an object with opts defined like:
|
|
||||||
* long_tag: [short_tag, description, value_type, default_value];
|
|
||||||
*
|
|
||||||
* `commands` is an optional array or object for apps that are of the form
|
|
||||||
* my_app [OPTIONS] <command> [ARGS]
|
|
||||||
* The command list is output with usage information + there is bundled
|
|
||||||
* support for auto-completion, etc.
|
|
||||||
*
|
|
||||||
* See README.md for more information.
|
|
||||||
*
|
|
||||||
* @param {Object} opts
|
|
||||||
* @param {Object} commands (optional)
|
|
||||||
* @return {Object} opts (parsed)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.parse = function (opts, command_def) {
|
|
||||||
var default_val, i, parsed = cli.options, seen,
|
|
||||||
catch_all = !opts;
|
|
||||||
opt_list = opts || {};
|
|
||||||
commands = command_def;
|
|
||||||
command_list = commands || [];
|
|
||||||
if (commands && !Array.isArray(commands)) {
|
|
||||||
command_list = Object.keys(commands);
|
|
||||||
}
|
|
||||||
while ((o = cli.next())) {
|
|
||||||
seen = false;
|
|
||||||
for (var opt in opt_list) {
|
|
||||||
if (!(opt_list[opt] instanceof Array)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!opt_list[opt][0]) {
|
|
||||||
opt_list[opt][0] = opt;
|
|
||||||
}
|
|
||||||
if (o === opt || o === opt_list[opt][0]) {
|
|
||||||
seen = true;
|
|
||||||
if (opt_list[opt].length === 2) {
|
|
||||||
parsed[opt] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default_val = null;
|
|
||||||
if (opt_list[opt].length === 4) {
|
|
||||||
default_val = opt_list[opt][3];
|
|
||||||
}
|
|
||||||
if (opt_list[opt][2] instanceof Array) {
|
|
||||||
for (i = 0, l = opt_list[opt][2].length; i < l; i++) {
|
|
||||||
if (typeof opt_list[opt][2][i] === 'number') {
|
|
||||||
opt_list[opt][2][i] += '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parsed[opt] = cli.getArrayValue(opt_list[opt][2], is_long ? null : default_val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (opt_list[opt][2].toLowerCase) {
|
|
||||||
opt_list[opt][2] = opt_list[opt][2].toLowerCase();
|
|
||||||
}
|
|
||||||
switch (opt_list[opt][2]) {
|
|
||||||
case 'string': case 1: case true:
|
|
||||||
parsed[opt] = cli.getValue(default_val);
|
|
||||||
break;
|
|
||||||
case 'int': case 'number': case 'num':
|
|
||||||
case 'time': case 'seconds': case 'secs': case 'minutes': case 'mins':
|
|
||||||
case 'x': case 'n':
|
|
||||||
parsed[opt] = cli.getInt(default_val);
|
|
||||||
break;
|
|
||||||
case 'float': case 'decimal':
|
|
||||||
parsed[opt] = cli.getFloat(default_val);
|
|
||||||
break;
|
|
||||||
case 'path': case 'file': case 'directory': case 'dir':
|
|
||||||
parsed[opt] = cli.getPath(default_val, opt_list[opt][2]);
|
|
||||||
break;
|
|
||||||
case 'email':
|
|
||||||
parsed[opt] = cli.getEmail(default_val);
|
|
||||||
break;
|
|
||||||
case 'url': case 'uri': case 'domain': case 'host':
|
|
||||||
parsed[opt] = cli.getUrl(default_val, opt_list[opt][2]);
|
|
||||||
break;
|
|
||||||
case 'ip':
|
|
||||||
parsed[opt] = cli.getIp(default_val);
|
|
||||||
break;
|
|
||||||
case 'bool': case 'boolean': case 'on':
|
|
||||||
parsed[opt] = true;
|
|
||||||
break;
|
|
||||||
case 'false': case 'off': case false: case 0:
|
|
||||||
parsed[opt] = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cli.fatal('Unknown opt type "' + opt_list[opt][2] + '"');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (process.env.NODE_DISABLE_COLORS) {
|
|
||||||
no_color = true;
|
|
||||||
}
|
|
||||||
if (!seen) {
|
|
||||||
if (enable.help && (o === 'h' || o === 'help')) {
|
|
||||||
cli.getUsage();
|
|
||||||
} else if (enable.version && (o === 'v' || o === 'version')) {
|
|
||||||
if (cli.version == null) {
|
|
||||||
cli.parsePackageJson();
|
|
||||||
}
|
|
||||||
console.error(cli.app + ' v' + cli.version);
|
|
||||||
cli.exit();
|
|
||||||
break;
|
|
||||||
} else if (enable.daemon && (o === 'd' || o === 'daemon')) {
|
|
||||||
daemon_arg = cli.getArrayValue(['start','stop','restart','pid','log'], is_long ? null : 'start');
|
|
||||||
continue;
|
|
||||||
} else if (enable.catchall && (o === 'c' || o === 'catch')) {
|
|
||||||
continue;
|
|
||||||
} else if (enable.status && (o === 'k' || o === 'no-color' || o === 'debug')) {
|
|
||||||
no_color = (o === 'k' || o === 'no-color');
|
|
||||||
show_debug = o === 'debug';
|
|
||||||
continue;
|
|
||||||
} else if (enable.timeout && (o === 't' || o === 'timeout')) {
|
|
||||||
var secs = cli.getInt();
|
|
||||||
setTimeout(function () {
|
|
||||||
cli.fatal('Process timed out after ' + secs + 's');
|
|
||||||
}, secs * 1000);
|
|
||||||
continue;
|
|
||||||
} else if (catch_all) {
|
|
||||||
parsed[o] = curr_val || true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cli.fatal('Unknown option ' + full_opt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Fill the remaining options with their default value or null
|
|
||||||
for (var opt in opt_list) {
|
|
||||||
default_val = opt_list[opt].length === 4 ? opt_list[opt][3] : null;
|
|
||||||
if (!(opt_list[opt] instanceof Array)) {
|
|
||||||
parsed[opt] = opt_list[opt];
|
|
||||||
continue;
|
|
||||||
} else if (typeof parsed[opt] === 'undefined') {
|
|
||||||
parsed[opt] = default_val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (command_list.length) {
|
|
||||||
if (cli.args.length === 0) {
|
|
||||||
if (enable.help) {
|
|
||||||
cli.getUsage();
|
|
||||||
} else {
|
|
||||||
cli.fatal('A command is required (' + command_list.join(', ') + ').');
|
|
||||||
}
|
|
||||||
return cli.exit(1);
|
|
||||||
} else {
|
|
||||||
cli.command = cli.autocompleteCommand(cli.args.shift());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cli.argc = cli.args.length;
|
|
||||||
return parsed;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for matching a command from the command list.
|
|
||||||
*
|
|
||||||
* @param {String} command
|
|
||||||
* @return {String} full_command
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.autocompleteCommand = function (command) {
|
|
||||||
var list;
|
|
||||||
if (!(command_list instanceof Array)) {
|
|
||||||
list = Object.keys(command_list);
|
|
||||||
} else {
|
|
||||||
list = command_list;
|
|
||||||
}
|
|
||||||
var i, j = 0, c = command.length, tmp_list;
|
|
||||||
if (list.length === 0 || list.indexOf(command) !== -1) {
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
for (i = 0; i < c; i++) {
|
|
||||||
tmp_list = [];
|
|
||||||
l = list.length;
|
|
||||||
if (l <= 1) break;
|
|
||||||
for (j = 0; j < l; j++)
|
|
||||||
if (list[j].length >= i && list[j][i] === command[i])
|
|
||||||
tmp_list.push(list[j]);
|
|
||||||
list = tmp_list;
|
|
||||||
}
|
|
||||||
l = list.length;
|
|
||||||
if (l === 1) {
|
|
||||||
return list[0];
|
|
||||||
} else if (l === 0) {
|
|
||||||
cli.fatal('Unknown command "' + command + '"' + (enable.help ? '. Please see --help for more information' : ''));
|
|
||||||
} else {
|
|
||||||
list.sort();
|
|
||||||
cli.fatal('The command "' + command + '" is ambiguous and could mean "' + list.join('", "') + '"');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds methods to output styled status messages to stderr.
|
|
||||||
*
|
|
||||||
* Added methods are cli.info(msg), cli.error(msg), cli.ok(msg), and
|
|
||||||
* cli.debug(msg).
|
|
||||||
*
|
|
||||||
* To control status messages, use the 'status' plugin
|
|
||||||
* 1) debug() messages are hidden by default. Display them with
|
|
||||||
* the --debug opt.
|
|
||||||
* 2) to hide all status messages, use the -s or --silent opt.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
cli.status = function (msg, type) {
|
|
||||||
var pre;
|
|
||||||
switch (type) {
|
|
||||||
case 'info':
|
|
||||||
pre = no_color ? 'INFO:' : '\x1B[33mINFO\x1B[0m:';
|
|
||||||
break;
|
|
||||||
case 'debug':
|
|
||||||
pre = no_color ? 'DEBUG:' : '\x1B[36mDEBUG\x1B[0m:';
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
case 'fatal':
|
|
||||||
pre = no_color ? 'ERROR:' : '\x1B[31mERROR\x1B[0m:';
|
|
||||||
break;
|
|
||||||
case 'ok':
|
|
||||||
pre = no_color ? 'OK:' : '\x1B[32mOK\x1B[0m:';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
msg = pre + ' ' + msg;
|
|
||||||
if (type === 'fatal') {
|
|
||||||
console.error(msg);
|
|
||||||
return cli.exit(1);
|
|
||||||
}
|
|
||||||
if (enable.status && !show_debug && type === 'debug') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.error(msg);
|
|
||||||
};
|
|
||||||
['info','error','ok','debug','fatal'].forEach(function (type) {
|
|
||||||
cli[type] = function (msg) {
|
|
||||||
cli.status(msg, type);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the app name and version.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* setApp('myapp', '0.1.0');
|
|
||||||
* setApp('./package.json'); //Pull name/version from package.json
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @return cli (for chaining)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.setApp = function (name, version) {
|
|
||||||
if (name.indexOf('package.json') !== -1) {
|
|
||||||
cli.parsePackageJson(name);
|
|
||||||
} else {
|
|
||||||
cli.app = name;
|
|
||||||
cli.version = version;
|
|
||||||
}
|
|
||||||
return cli;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the version number from package.json. If no path is specified, cli
|
|
||||||
* will attempt to locate a package.json in ./, ../ or ../../
|
|
||||||
*
|
|
||||||
* @param {String} path (optional)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.parsePackageJson = function (path) {
|
|
||||||
var parse_packagejson = function (path) {
|
|
||||||
var packagejson = JSON.parse(cli.native.fs.readFileSync(path, 'utf8'));
|
|
||||||
cli.version = packagejson.version;
|
|
||||||
cli.app = packagejson.name;
|
|
||||||
};
|
|
||||||
var try_all = function (arr, func, err) {
|
|
||||||
for (var i = 0, l = arr.length; i < l; i++) {
|
|
||||||
try {
|
|
||||||
func(arr[i]);
|
|
||||||
return;
|
|
||||||
} catch (e) {
|
|
||||||
if (i === l-1) {
|
|
||||||
cli.fatal(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
if (path) {
|
|
||||||
return parse_packagejson(path);
|
|
||||||
}
|
|
||||||
try_all([
|
|
||||||
__dirname + '/package.json',
|
|
||||||
__dirname + '/../package.json',
|
|
||||||
__dirname + '/../../package.json'
|
|
||||||
], parse_packagejson);
|
|
||||||
} catch (e) {
|
|
||||||
cli.fatal('Could not detect ' + cli.app + ' version');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the usage string - default is `app [OPTIONS] [ARGS]`.
|
|
||||||
*
|
|
||||||
* @param {String} u
|
|
||||||
* @return cli (for chaining)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.setUsage = function (u) {
|
|
||||||
usage = u;
|
|
||||||
return cli;
|
|
||||||
};
|
|
||||||
|
|
||||||
var pad = function (str, len) {
|
|
||||||
if (typeof len === 'undefined') {
|
|
||||||
len = str;
|
|
||||||
str = '';
|
|
||||||
}
|
|
||||||
if (str.length < len) {
|
|
||||||
len -= str.length;
|
|
||||||
while (len--) str += ' ';
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Automatically build usage information from the opts list. If the help
|
|
||||||
* plugin is enabled (default), this info is displayed with -h, --help.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.getUsage = function (code) {
|
|
||||||
var short, desc, optional, line, seen_opts = [],
|
|
||||||
switch_pad = cli.option_width;
|
|
||||||
|
|
||||||
var trunc_desc = function (pref, desc, len) {
|
|
||||||
var pref_len = pref.length,
|
|
||||||
desc_len = cli.width - pref_len,
|
|
||||||
truncated = '';
|
|
||||||
if (desc.length <= desc_len) {
|
|
||||||
return desc;
|
|
||||||
}
|
|
||||||
var desc_words = (desc+'').split(' '), chars = 0, word;
|
|
||||||
while (desc_words.length) {
|
|
||||||
truncated += (word = desc_words.shift()) + ' ';
|
|
||||||
chars += word.length;
|
|
||||||
if (desc_words.length && chars + desc_words[0].length > desc_len) {
|
|
||||||
truncated += '\n' + pad(pref_len);
|
|
||||||
chars = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return truncated;
|
|
||||||
};
|
|
||||||
|
|
||||||
usage = usage || cli.app + ' [OPTIONS]' + (command_list.length ? ' <command>' : '') + ' [ARGS]';
|
|
||||||
if (no_color) {
|
|
||||||
console.error('Usage:\n ' + usage);
|
|
||||||
console.error('Options: ');
|
|
||||||
} else {
|
|
||||||
console.error('\x1b[1mUsage\x1b[0m:\n ' + usage);
|
|
||||||
console.error('\n\x1b[1mOptions\x1b[0m: ');
|
|
||||||
}
|
|
||||||
for (var opt in opt_list) {
|
|
||||||
|
|
||||||
if (opt.length === 1) {
|
|
||||||
long = opt_list[opt][0];
|
|
||||||
short = opt;
|
|
||||||
} else {
|
|
||||||
long = opt;
|
|
||||||
short = opt_list[opt][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
//Parse opt_list
|
|
||||||
desc = opt_list[opt][1].trim();
|
|
||||||
type = opt_list[opt].length >= 3 ? opt_list[opt][2] : null;
|
|
||||||
optional = opt_list[opt].length === 4 ? opt_list[opt][3] : null;
|
|
||||||
|
|
||||||
//Build usage line
|
|
||||||
if (short === long) {
|
|
||||||
if (short.length === 1) {
|
|
||||||
line = ' -' + short;
|
|
||||||
} else {
|
|
||||||
line = ' --' + long;
|
|
||||||
}
|
|
||||||
} else if (short) {
|
|
||||||
line = ' -' + short + ', --' + long;
|
|
||||||
} else {
|
|
||||||
line = ' --' + long;
|
|
||||||
}
|
|
||||||
line += ' ';
|
|
||||||
|
|
||||||
if (type) {
|
|
||||||
if (type instanceof Array) {
|
|
||||||
desc += '. VALUE must be either [' + type.join('|') + ']';
|
|
||||||
type = 'VALUE';
|
|
||||||
}
|
|
||||||
if (type === true || type === 1) {
|
|
||||||
type = long.toUpperCase();
|
|
||||||
}
|
|
||||||
type = type.toUpperCase();
|
|
||||||
if (type === 'FLOAT' || type === 'INT') {
|
|
||||||
type = 'NUMBER';
|
|
||||||
}
|
|
||||||
line += optional ? '[' + type + ']' : type;
|
|
||||||
}
|
|
||||||
line = pad(line, switch_pad);
|
|
||||||
line += trunc_desc(line, desc);
|
|
||||||
line += optional ? ' (Default is ' + optional + ')' : '';
|
|
||||||
console.error(line.replace('%s', '%\0s'));
|
|
||||||
|
|
||||||
seen_opts.push(short);
|
|
||||||
seen_opts.push(long);
|
|
||||||
}
|
|
||||||
if (enable.timeout && seen_opts.indexOf('t') === -1 && seen_opts.indexOf('timeout') === -1) {
|
|
||||||
console.error(pad(' -t, --timeout N', switch_pad) + 'Exit if the process takes longer than N seconds');
|
|
||||||
}
|
|
||||||
if (enable.status) {
|
|
||||||
if (seen_opts.indexOf('k') === -1 && seen_opts.indexOf('no-color') === -1) {
|
|
||||||
console.error(pad(' -k, --no-color', switch_pad) + 'Omit color from output');
|
|
||||||
}
|
|
||||||
if (seen_opts.indexOf('debug') === -1) {
|
|
||||||
console.error(pad(' --debug', switch_pad) + 'Show debug information');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (enable.catchall && seen_opts.indexOf('c') === -1 && seen_opts.indexOf('catch') === -1) {
|
|
||||||
console.error(pad(' -c, --catch', switch_pad) + 'Catch unanticipated errors');
|
|
||||||
}
|
|
||||||
if (enable.daemon && seen_opts.indexOf('d') === -1 && seen_opts.indexOf('daemon') === -1) {
|
|
||||||
console.error(pad(' -d, --daemon [ARG]', switch_pad) + 'Daemonize the process. Control the daemon using [start, stop, restart, log, pid]');
|
|
||||||
}
|
|
||||||
if (enable.version && seen_opts.indexOf('v') === -1 && seen_opts.indexOf('version') === -1) {
|
|
||||||
console.error(pad(' -v, --version', switch_pad) + 'Display the current version');
|
|
||||||
}
|
|
||||||
if (enable.help && seen_opts.indexOf('h') === -1 && seen_opts.indexOf('help') === -1) {
|
|
||||||
console.error(pad(' -h, --help', switch_pad) + 'Display help and usage details');
|
|
||||||
}
|
|
||||||
if (command_list.length) {
|
|
||||||
console.error('\n\x1b[1mCommands\x1b[0m: ');
|
|
||||||
if (!Array.isArray(commands)) {
|
|
||||||
for (var c in commands) {
|
|
||||||
line = ' ' + pad(c, switch_pad - 2);
|
|
||||||
line += trunc_desc(line, commands[c]);
|
|
||||||
console.error(line);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
command_list.sort();
|
|
||||||
console.error(' ' + trunc_desc(' ', command_list.join(', ')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cli.exit(code);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an error message when an opt is incorrectly used.
|
|
||||||
*
|
|
||||||
* @param {String} expects (e.g. 'a value')
|
|
||||||
* @param {String} type (e.g. 'VALUE')
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.getOptError = function (expects, type) {
|
|
||||||
var err = full_opt + ' expects ' + expects
|
|
||||||
+ '. Use `' + cli.app + ' ' + full_opt + (is_long ? '=' : ' ') + type + '`';
|
|
||||||
return err;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the next opt value and validates it with an optional validation
|
|
||||||
* function. If validation fails or no value can be obtained, this method
|
|
||||||
* will return the default value (if specified) or exit with err_msg.
|
|
||||||
*
|
|
||||||
* @param {String} default_val
|
|
||||||
* @param {Function} validate_func
|
|
||||||
* @param {String} err_msg
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.getValue = function (default_val, validate_func, err_msg) {
|
|
||||||
err_msg = err_msg || cli.getOptError('a value', 'VALUE');
|
|
||||||
|
|
||||||
var value;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (curr_val) {
|
|
||||||
if (validate_func) {
|
|
||||||
curr_val = validate_func(curr_val);
|
|
||||||
}
|
|
||||||
return curr_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Grouped short opts aren't allowed to have values
|
|
||||||
if (short_tags.length) {
|
|
||||||
throw 'Short tags';
|
|
||||||
}
|
|
||||||
|
|
||||||
//If there's no args left or the next arg is an opt, return the
|
|
||||||
//default value (if specified) - otherwise fail
|
|
||||||
if (!argv.length || (argv[0].length === 1 && argv[0][0] === '-')) {
|
|
||||||
throw 'No value';
|
|
||||||
}
|
|
||||||
|
|
||||||
value = argv.shift();
|
|
||||||
|
|
||||||
if (value.match(/^[0-9]+$/)) {
|
|
||||||
value = parseInt(value, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Run the value through a validation/transformation function if specified
|
|
||||||
if (validate_func) {
|
|
||||||
value = validate_func(value);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
|
|
||||||
//The value didn't pass the validation/transformation. Unshift the value and
|
|
||||||
//return the default value (if specified)
|
|
||||||
if (value) {
|
|
||||||
argv.unshift(value);
|
|
||||||
}
|
|
||||||
return default_val != null ? default_val : cli.fatal(err_msg);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
cli.getInt = function (default_val) {
|
|
||||||
return cli.getValue(default_val, function (value) {
|
|
||||||
if (typeof value === 'number') return value;
|
|
||||||
if (!value.match(/^(?:-?(?:0|[1-9][0-9]*))$/)) {
|
|
||||||
throw 'Invalid int';
|
|
||||||
}
|
|
||||||
return parseInt(value);
|
|
||||||
}, cli.getOptError('a number', 'NUMBER'));
|
|
||||||
}
|
|
||||||
|
|
||||||
cli.getFloat = function (default_val) {
|
|
||||||
return cli.getValue(default_val, function (value) {
|
|
||||||
if (!value.match(/^(?:-?(?:0|[1-9][0-9]*))?(?:\.[0-9]*)?$/)) {
|
|
||||||
throw 'Invalid float';
|
|
||||||
}
|
|
||||||
return parseFloat(value, 10);
|
|
||||||
}, cli.getOptError('a number', 'NUMBER'));
|
|
||||||
}
|
|
||||||
|
|
||||||
cli.getUrl = function (default_val, identifier) {
|
|
||||||
identifier = identifier || 'url';
|
|
||||||
return cli.getValue(default_val, function (value) {
|
|
||||||
if (!value.match(/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/i)) {
|
|
||||||
throw 'Invalid URL';
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}, cli.getOptError('a ' + identifier, identifier.toUpperCase()));
|
|
||||||
}
|
|
||||||
|
|
||||||
cli.getEmail = function (default_val) {
|
|
||||||
return cli.getValue(default_val, function (value) {
|
|
||||||
if (!value.match(/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/)) {
|
|
||||||
throw 'Invalid email';
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}, cli.getOptError('an email', 'EMAIL'));
|
|
||||||
}
|
|
||||||
|
|
||||||
cli.getIp = function (default_val) {
|
|
||||||
return cli.getValue(default_val, function (value) {
|
|
||||||
if (!value.match(/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/)) {
|
|
||||||
throw 'Invalid IP';
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}, cli.getOptError('an IP', 'IP'));
|
|
||||||
}
|
|
||||||
|
|
||||||
cli.getPath = function (default_val, identifier) {
|
|
||||||
identifier = identifier || 'path';
|
|
||||||
return cli.getValue(default_val, function (value) {
|
|
||||||
if (value.match(/[?*;{}]/)) {
|
|
||||||
throw 'Invalid path';
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}, cli.getOptError('a ' + identifier, identifier.toUpperCase()));
|
|
||||||
}
|
|
||||||
|
|
||||||
cli.getArrayValue = function (arr, default_val) {
|
|
||||||
return cli.getValue(default_val, function (value) {
|
|
||||||
if (arr.indexOf(value) === -1) {
|
|
||||||
throw 'Unexpected value';
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}, cli.getOptError('either [' + arr.join('|') + ']', 'VALUE'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all data from STDIN (with optional encoding) and sends it to callback.
|
|
||||||
*
|
|
||||||
* @param {String} encoding (optional - default is 'utf8')
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.withStdin = function (encoding, callback) {
|
|
||||||
if (typeof encoding === 'function') {
|
|
||||||
callback = encoding;
|
|
||||||
encoding = 'utf8';
|
|
||||||
}
|
|
||||||
var stream = process.openStdin(), data = '';
|
|
||||||
stream.setEncoding(encoding);
|
|
||||||
stream.on('data', function (chunk) {
|
|
||||||
data += chunk;
|
|
||||||
});
|
|
||||||
stream.on('end', function () {
|
|
||||||
callback.apply(cli, [data]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all data from STDIN, splits the data into lines and sends it
|
|
||||||
* to callback (callback isn't called until all of STDIN is read. To
|
|
||||||
* process each line as it's received, see the method below
|
|
||||||
*
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.withStdinLines = function (callback) {
|
|
||||||
cli.withStdin(function (data) {
|
|
||||||
var sep = data.indexOf('\r\n') !== -1 ? '\r\n' : '\n';
|
|
||||||
callback.apply(cli, [data.split(sep), sep]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronously reads a file line by line. When a line is received,
|
|
||||||
* callback is called with (line, sep) - when EOF is reached, callback
|
|
||||||
* receives (null, null, true)
|
|
||||||
*
|
|
||||||
* @param {String} file (optional - default is 'stdin')
|
|
||||||
* @param {String} encoding (optional - default is 'utf8')
|
|
||||||
* @param {Function} callback (line, sep, eof)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.withInput = function (file, encoding, callback) {
|
|
||||||
if (typeof encoding === 'function') {
|
|
||||||
callback = encoding;
|
|
||||||
encoding = 'utf8';
|
|
||||||
} else if (typeof file === 'function') {
|
|
||||||
callback = file;
|
|
||||||
encoding = 'utf8';
|
|
||||||
file = 'stdin';
|
|
||||||
}
|
|
||||||
if (file === 'stdin') {
|
|
||||||
file = process.openStdin();
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
file = cli.native.fs.createReadStream(file);
|
|
||||||
file.on('error', cli.fatal);
|
|
||||||
} catch (e) {
|
|
||||||
return cli.fatal(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.setEncoding(encoding);
|
|
||||||
var lines = [], data = '', eof, sep;
|
|
||||||
file.on('data', function (chunk) {
|
|
||||||
if (eof) return;
|
|
||||||
data += chunk;
|
|
||||||
if (!sep) {
|
|
||||||
if (data.indexOf('\r\n') !== -1) {
|
|
||||||
sep = '\r\n';
|
|
||||||
} else if (data.indexOf('\n') !== -1) {
|
|
||||||
sep = '\n';
|
|
||||||
} else {
|
|
||||||
last_line = data;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lines = data.split(sep);
|
|
||||||
data = eof ? null : lines.pop();
|
|
||||||
while (lines.length) {
|
|
||||||
callback.apply(cli, [lines.shift(), sep, false]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
file.on('end', function () {
|
|
||||||
eof = true;
|
|
||||||
if (data.length) {
|
|
||||||
callback.apply(cli, [data, sep || '', false]);
|
|
||||||
}
|
|
||||||
callback.apply(cli, [null, null, true]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A method for creating and controlling a daemon.
|
|
||||||
*
|
|
||||||
* `arg` can be:
|
|
||||||
* start = daemonizes the process
|
|
||||||
* stop = stops the daemon if it is running
|
|
||||||
* restart = alias for stop -> start
|
|
||||||
* pid = outputs the daemon's PID if it is running
|
|
||||||
* log = outputs the daemon's log file (stdout + stderr)
|
|
||||||
*
|
|
||||||
* @param {String} arg (Optional - default is 'start')
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.daemon = function (arg, callback) {
|
|
||||||
if (typeof daemon === 'undefined') {
|
|
||||||
cli.fatal('Daemon is not initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof arg === 'function') {
|
|
||||||
callback = arg;
|
|
||||||
arg = 'start';
|
|
||||||
}
|
|
||||||
|
|
||||||
var lock_file = '/tmp/' + cli.app + '.pid',
|
|
||||||
log_file = '/tmp/' + cli.app + '.log';
|
|
||||||
|
|
||||||
var start = function () {
|
|
||||||
daemon.daemonize(log_file, lock_file, function (err) {
|
|
||||||
if (err) return cli.error('Error starting daemon: ' + err);
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var stop = function () {
|
|
||||||
try {
|
|
||||||
cli.native.fs.readFileSync(lock_file);
|
|
||||||
} catch (e) {
|
|
||||||
return cli.error('Daemon is not running');
|
|
||||||
}
|
|
||||||
daemon.kill(lock_file, function (err, pid) {
|
|
||||||
if (err && err.errno === 3) {
|
|
||||||
return cli.error('Daemon is not running');
|
|
||||||
} else if (err) {
|
|
||||||
return cli.error('Error stopping daemon: ' + err.errno);
|
|
||||||
}
|
|
||||||
cli.ok('Successfully stopped daemon with pid: ' + pid);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
switch(arg) {
|
|
||||||
case 'stop':
|
|
||||||
stop();
|
|
||||||
break;
|
|
||||||
case 'restart':
|
|
||||||
daemon.stop(lock_file, function () {
|
|
||||||
start();
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'log':
|
|
||||||
try {
|
|
||||||
cli.native.fs.createReadStream(log_file, {encoding: 'utf8'}).pipe(process.stdout);
|
|
||||||
} catch (e) {
|
|
||||||
return cli.error('No daemon log file');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'pid':
|
|
||||||
try {
|
|
||||||
var pid = cli.native.fs.readFileSync(lock_file, 'utf8');
|
|
||||||
cli.native.fs.statSync('/proc/' + pid);
|
|
||||||
cli.info(pid);
|
|
||||||
} catch (e) {
|
|
||||||
return cli.error('Daemon is not running');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
start();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main entry method. Calling cli.main() is only necessary in
|
|
||||||
* scripts that have daemon support enabled. `callback` receives (args, options)
|
|
||||||
*
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.main = function (callback) {
|
|
||||||
var after = function () {
|
|
||||||
callback.apply(cli, [cli.args, cli.options]);
|
|
||||||
};
|
|
||||||
if (enable.daemon && daemon_arg) {
|
|
||||||
cli.daemon(daemon_arg, after);
|
|
||||||
} else {
|
|
||||||
after();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind creationix's stack (https://github.com/creationix/stack).
|
|
||||||
*
|
|
||||||
* Create a simple middleware stack by calling:
|
|
||||||
*
|
|
||||||
* cli.createServer(middleware).listen(port);
|
|
||||||
*
|
|
||||||
* @return {Server} server
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.createServer = function(/*layers*/) {
|
|
||||||
var defaultStackErrorHandler = function (req, res, err) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err.stack);
|
|
||||||
res.writeHead(500, {"Content-Type": "text/plain"});
|
|
||||||
return res.end(err.stack + "\n");
|
|
||||||
}
|
|
||||||
res.writeHead(404, {"Content-Type": "text/plain"});
|
|
||||||
res.end("Not Found\n");
|
|
||||||
};
|
|
||||||
var handle, error;
|
|
||||||
handle = error = defaultStackErrorHandler;
|
|
||||||
var layers = Array.prototype.slice.call(arguments);
|
|
||||||
|
|
||||||
//Allow createServer(a,b,c) and createServer([a,b,c])
|
|
||||||
if (layers.length && layers[0] instanceof Array) {
|
|
||||||
layers = layers[0];
|
|
||||||
}
|
|
||||||
layers.reverse().forEach(function (layer) {
|
|
||||||
var child = handle;
|
|
||||||
handle = function (req, res) {
|
|
||||||
try {
|
|
||||||
layer(req, res, function (err) {
|
|
||||||
if (err) return error(req, res, err);
|
|
||||||
child(req, res);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
error(req, res, err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return cli.native.http.createServer(handle);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for child_process.exec().
|
|
||||||
*
|
|
||||||
* If the child_process exits successfully, `callback` receives an array of
|
|
||||||
* stdout lines. The current process exits if the child process has an error
|
|
||||||
* and `errback` isn't defined.
|
|
||||||
*
|
|
||||||
* @param {String} cmd
|
|
||||||
* @param {Function} callback (optional)
|
|
||||||
* @param {Function} errback (optional)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
cli.exec = function (cmd, callback, errback) {
|
|
||||||
cli.native.child_process.exec(cmd, function (err, stdout, stderr) {
|
|
||||||
err = err || stderr;
|
|
||||||
if (err) {
|
|
||||||
if (errback) {
|
|
||||||
return errback(err, stdout);
|
|
||||||
}
|
|
||||||
return cli.fatal('exec() failed\n' + err);
|
|
||||||
}
|
|
||||||
if (callback) {
|
|
||||||
callback(stdout.split('\n'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for outputting a progress bar to the console.
|
|
||||||
*
|
|
||||||
* @param {Number} progress (0 <= progress <= 1)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
var last_progress_call, progress_len = 74;
|
|
||||||
cli.progress = function (progress, decimals, stream) {
|
|
||||||
stream = stream || process.stdout;
|
|
||||||
if (progress < 0 || progress > 1 || isNaN(progress)) return;
|
|
||||||
if (!decimals) decimals = 0;
|
|
||||||
var now = (new Date()).getTime();
|
|
||||||
if (last_progress_call && (now - last_progress_call) < 100 && progress !== 1) {
|
|
||||||
return; //Throttle progress calls
|
|
||||||
}
|
|
||||||
last_progress_call = now;
|
|
||||||
|
|
||||||
|
|
||||||
var barLength = Math.floor(progress_len * progress),
|
|
||||||
str = '';
|
|
||||||
if (barLength == 0 && progress > 0) {
|
|
||||||
barLength = 1;
|
|
||||||
}
|
|
||||||
for (var i = 1; i <= progress_len; i++) {
|
|
||||||
str += i <= barLength ? '#' : ' ';
|
|
||||||
}
|
|
||||||
var pwr = Math.pow(10, decimals);
|
|
||||||
var percentage = Math.floor(progress * 100 * pwr) / pwr + '%';
|
|
||||||
for (i = 0; i < decimals; i++) {
|
|
||||||
percentage += ' ';
|
|
||||||
}
|
|
||||||
stream.clearLine();
|
|
||||||
stream.write('[' + str + '] ' + percentage);
|
|
||||||
if (progress === 1) {
|
|
||||||
stream.write('\n');
|
|
||||||
} else {
|
|
||||||
stream.cursorTo(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for outputting a spinner to the console.
|
|
||||||
*
|
|
||||||
* @param {String|Boolean} prefix (optional)
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
var spinnerInterval;
|
|
||||||
cli.spinner = function (prefix, end, stream) {
|
|
||||||
stream = stream || process.stdout;
|
|
||||||
if (end) {
|
|
||||||
stream.clearLine();
|
|
||||||
stream.cursorTo(0);
|
|
||||||
stream.write(prefix + '\n');
|
|
||||||
return clearInterval(spinnerInterval);
|
|
||||||
}
|
|
||||||
prefix = prefix + ' ' || '';
|
|
||||||
var spinner = ['-','\\','|','/'], i = 0, l = spinner.length;
|
|
||||||
spinnerInterval = setInterval(function () {
|
|
||||||
stream.clearLine();
|
|
||||||
stream.cursorTo(0);
|
|
||||||
stream.write(prefix + spinner[i++]);
|
|
||||||
if (i == l) i = 0;
|
|
||||||
}, 200);
|
|
||||||
};
|
|
17
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/examples/cat.js
generated
vendored
17
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/examples/cat.js
generated
vendored
|
@ -1,17 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('cli');
|
|
||||||
|
|
||||||
var output_file = function (file) {
|
|
||||||
cli.withInput(file, function (line, sep, eof) {
|
|
||||||
if (!eof) {
|
|
||||||
cli.output(line + sep);
|
|
||||||
} else if (cli.args.length) {
|
|
||||||
output_file(cli.args.shift());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (cli.args.length) {
|
|
||||||
output_file(cli.args.shift());
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('cli');
|
|
||||||
|
|
||||||
//The second (optional) argument of cli.parse() is a command list
|
|
||||||
//Type `./command.js --help` for usage info
|
|
||||||
|
|
||||||
//cli enables auto-completion of commands (similiar to npm), e.g. all of
|
|
||||||
//the following are equivalent and result in "Command is: install":
|
|
||||||
// $ ./command.js install
|
|
||||||
// $ ./command.js inst
|
|
||||||
// $ ./command.js i
|
|
||||||
|
|
||||||
cli.parse(null, ['install', 'test', 'edit', 'remove', 'uninstall', 'ls']);
|
|
||||||
|
|
||||||
console.log('Command is: ' + cli.command);
|
|
54
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/examples/echo.js
generated
vendored
54
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/examples/echo.js
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
/* All of the following commands are equivalent and write `foo\tbar foo` to out.txt
|
|
||||||
$ ./echo.js -n -e --output=out.txt "foo\tbar" "foo"
|
|
||||||
$ ./echo.js --newline --escape --output "out.txt" "foo\tbar" "foo"
|
|
||||||
$ ./echo.js -ne --output=out.txt "foo\tbar" "foo"
|
|
||||||
$ ./echo.js -en --output="out.txt" "foo\tbar" "foo"
|
|
||||||
*/
|
|
||||||
|
|
||||||
var cli = require('cli');
|
|
||||||
|
|
||||||
cli.parse({
|
|
||||||
newline: ['n', 'Do not output the trailing newline'],
|
|
||||||
escape: ['e', 'Enable interpretation of backslash escapes'],
|
|
||||||
separator: ['s', 'Separate arguments using this value', 'string', ' '],
|
|
||||||
output: [false, 'Write to FILE rather than the console', 'file']
|
|
||||||
});
|
|
||||||
|
|
||||||
cli.main(function (args, options) {
|
|
||||||
var output = '', i, j, l, output_stream;
|
|
||||||
|
|
||||||
if (this.argc) {
|
|
||||||
if (options.escape) {
|
|
||||||
var replace = {'\\n':'\n','\\r':'\r','\\t':'\t','\\e':'\e','\\v':'\v','\\f':'\f','\\c':'\c','\\b':'\b','\\a':'\a','\\\\':'\\'};
|
|
||||||
var escape = function (str) {
|
|
||||||
str += '';
|
|
||||||
for (j in replace) {
|
|
||||||
str = str.replace(i, replace[i]);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
for (i = 0, l = this.argc; i < l; i++) {
|
|
||||||
args[i] = escape(args[i]);
|
|
||||||
}
|
|
||||||
options.separator = escape(options.separator);
|
|
||||||
}
|
|
||||||
output += args.join(options.separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.newline) {
|
|
||||||
output += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (options.output) {
|
|
||||||
output_stream = this.native.fs.createWriteStream(options.output)
|
|
||||||
} else {
|
|
||||||
output_stream = process.stdout;
|
|
||||||
}
|
|
||||||
output_stream.write(output);
|
|
||||||
} catch (e) {
|
|
||||||
this.fatal('Could not write to output stream');
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('cli').enable('glob');
|
|
||||||
|
|
||||||
//Running `./glob.js *.js` will output a list of .js files in this directory
|
|
||||||
console.log(cli.args);
|
|
|
@ -1,20 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('../');
|
|
||||||
|
|
||||||
//You can (optionally) boost the width of output with:
|
|
||||||
//cli.width = 120;
|
|
||||||
|
|
||||||
//You can also adjust the width of the options/command definitions
|
|
||||||
//cli.option_width = 25;
|
|
||||||
|
|
||||||
var long_desc = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s '
|
|
||||||
+ 'standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make'
|
|
||||||
+ ' a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, '
|
|
||||||
+ 'remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing '
|
|
||||||
+ 'Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions'
|
|
||||||
+ ' of Lorem Ipsum.';
|
|
||||||
|
|
||||||
cli.parse({
|
|
||||||
foo: ['f', long_desc]
|
|
||||||
});
|
|
|
@ -1,11 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('cli');
|
|
||||||
|
|
||||||
var i = 0, interval = setInterval(function () {
|
|
||||||
cli.progress(++i / 100);
|
|
||||||
if (i === 100) {
|
|
||||||
clearInterval(interval);
|
|
||||||
cli.ok('Finished!');
|
|
||||||
}
|
|
||||||
}, 50);
|
|
18
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/examples/sort.js
generated
vendored
18
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/examples/sort.js
generated
vendored
|
@ -1,18 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('cli');
|
|
||||||
|
|
||||||
var options = cli.parse({
|
|
||||||
numeric: ['n', 'Compare using a numeric sort'],
|
|
||||||
reverse: ['r', 'Reverse the results']
|
|
||||||
});
|
|
||||||
|
|
||||||
cli.withStdinLines(function (lines, newline) {
|
|
||||||
lines.sort(!options.numeric ? null : function (a, b) {
|
|
||||||
return parseInt(a) > parseInt(b);
|
|
||||||
});
|
|
||||||
if (options.reverse) {
|
|
||||||
lines.reverse();
|
|
||||||
}
|
|
||||||
this.output(lines.join(newline));
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('cli');
|
|
||||||
|
|
||||||
cli.spinner('Working..');
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
cli.spinner('Working.. done!', true); //End the spinner
|
|
||||||
}, 3000);
|
|
|
@ -1,27 +0,0 @@
|
||||||
#!/usr/bin/env coffee
|
|
||||||
|
|
||||||
cli = require 'cli'
|
|
||||||
|
|
||||||
cli.enable('daemon','status')
|
|
||||||
.setUsage('static.coffee [OPTIONS]')
|
|
||||||
|
|
||||||
cli.parse {
|
|
||||||
log: ['l', 'Enable logging']
|
|
||||||
port: ['p', 'Listen on this port', 'number', 8080]
|
|
||||||
serve: [false, 'Serve static files from PATH', 'path', './public']
|
|
||||||
}
|
|
||||||
|
|
||||||
middleware = []
|
|
||||||
|
|
||||||
cli.main (args, options) ->
|
|
||||||
|
|
||||||
if options.log
|
|
||||||
@debug 'Enabling logging'
|
|
||||||
middleware.push require('creationix/log')()
|
|
||||||
|
|
||||||
@debug 'Serving files from ' + options.serve
|
|
||||||
middleware.push require('creationix/static')('/', options.serve, 'index.html')
|
|
||||||
|
|
||||||
server = @createServer(middleware).listen options.port
|
|
||||||
|
|
||||||
@ok 'Listening on port ' + options.port
|
|
|
@ -1,25 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('cli').enable('status', 'daemon');
|
|
||||||
|
|
||||||
cli.parse({
|
|
||||||
log: ['l', 'Enable logging'],
|
|
||||||
port: ['p', 'Listen on this port', 'number', 8080],
|
|
||||||
serve: [false, 'Serve static files from PATH', 'path', './public']
|
|
||||||
});
|
|
||||||
|
|
||||||
cli.main(function (args, options) {
|
|
||||||
var server, middleware = [];
|
|
||||||
|
|
||||||
if (options.log) {
|
|
||||||
this.debug('Enabling logging');
|
|
||||||
middleware.push(require('creationix/log')());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.debug('Serving files from ' + options.serve);
|
|
||||||
middleware.push(require('creationix/static')('/', options.serve, 'index.html'));
|
|
||||||
|
|
||||||
server = this.createServer(middleware).listen(options.port);
|
|
||||||
|
|
||||||
this.ok('Listening on port ' + options.port);
|
|
||||||
});
|
|
1
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/index.js
generated
vendored
1
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/index.js
generated
vendored
|
@ -1 +0,0 @@
|
||||||
module.exports = require('./cli');
|
|
|
@ -1,2 +0,0 @@
|
||||||
.*.swp
|
|
||||||
test/a/
|
|
|
@ -1,3 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.8
|
|
|
@ -1,27 +0,0 @@
|
||||||
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.
|
|
|
@ -1,250 +0,0 @@
|
||||||
# Glob
|
|
||||||
|
|
||||||
Match files using the patterns the shell uses, like stars and stuff.
|
|
||||||
|
|
||||||
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.
|
|
||||||
* `statCache` Collection of all the stat results the glob search
|
|
||||||
performed.
|
|
||||||
* `cache` Convenience object. Each field has the following possible
|
|
||||||
values:
|
|
||||||
* `false` - Path does not exist
|
|
||||||
* `true` - Path exists
|
|
||||||
* `1` - Path exists, and is not a directory
|
|
||||||
* `2` - Path exists, and is a directory
|
|
||||||
* `[file, entries, ...]` - Path exists, is a directory, and the
|
|
||||||
array value is the results of `fs.readdir`
|
|
||||||
|
|
||||||
### 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.)
|
|
||||||
* `dot` Include `.dot` files in normal matches and `globstar` matches.
|
|
||||||
Note that an explicit dot in a portion of the pattern will always
|
|
||||||
match dot files.
|
|
||||||
* `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.
|
|
||||||
* `cache` See `cache` property above. Pass in a previously generated
|
|
||||||
cache object to save some fs calls.
|
|
||||||
* `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.
|
|
||||||
|
|
||||||
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 cache or statCache objects are 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.
|
|
|
@ -1,9 +0,0 @@
|
||||||
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")
|
|
|
@ -1,9 +0,0 @@
|
||||||
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")
|
|
|
@ -1,728 +0,0 @@
|
||||||
// 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("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)
|
|
||||||
}
|
|
||||||
|
|
||||||
this._processingEmitQueue = false
|
|
||||||
|
|
||||||
glob.Glob = Glob
|
|
||||||
inherits(Glob, EE)
|
|
||||||
function Glob (pattern, options, cb) {
|
|
||||||
if (!(this instanceof Glob)) {
|
|
||||||
return new Glob(pattern, options, cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof options === "function") {
|
|
||||||
cb = options
|
|
||||||
options = null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof cb === "function") {
|
|
||||||
this.on("error", cb)
|
|
||||||
this.on("end", function (matches) {
|
|
||||||
cb(null, matches)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {}
|
|
||||||
|
|
||||||
this._endEmitted = false
|
|
||||||
this.EOF = {}
|
|
||||||
this._emitQueue = []
|
|
||||||
|
|
||||||
this.paused = false
|
|
||||||
this._processingEmitQueue = false
|
|
||||||
|
|
||||||
this.maxDepth = options.maxDepth || 1000
|
|
||||||
this.maxLength = options.maxLength || Infinity
|
|
||||||
this.cache = options.cache || {}
|
|
||||||
this.statCache = options.statCache || {}
|
|
||||||
|
|
||||||
this.changedCwd = false
|
|
||||||
var cwd = process.cwd()
|
|
||||||
if (!options.hasOwnProperty("cwd")) this.cwd = cwd
|
|
||||||
else {
|
|
||||||
this.cwd = options.cwd
|
|
||||||
this.changedCwd = path.resolve(options.cwd) !== cwd
|
|
||||||
}
|
|
||||||
|
|
||||||
this.root = options.root || path.resolve(this.cwd, "/")
|
|
||||||
this.root = path.resolve(this.root)
|
|
||||||
if (process.platform === "win32")
|
|
||||||
this.root = this.root.replace(/\\/g, "/")
|
|
||||||
|
|
||||||
this.nomount = !!options.nomount
|
|
||||||
|
|
||||||
if (!pattern) {
|
|
||||||
throw new Error("must provide pattern")
|
|
||||||
}
|
|
||||||
|
|
||||||
// base-matching: just use globstar for that.
|
|
||||||
if (options.matchBase && -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
|
|
||||||
|
|
||||||
// list of all the patterns that ** has resolved do, so
|
|
||||||
// we can avoid visiting multiple times.
|
|
||||||
this._globstars = {}
|
|
||||||
|
|
||||||
EE.call(this)
|
|
||||||
|
|
||||||
// process each pattern in the minimatch set
|
|
||||||
var 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(this._mark, 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._mark = function (p) {
|
|
||||||
var c = this.cache[p]
|
|
||||||
var m = p
|
|
||||||
if (c) {
|
|
||||||
var isDir = c === 2 || Array.isArray(c)
|
|
||||||
var slash = p.slice(-1) === '/'
|
|
||||||
|
|
||||||
if (isDir && !slash)
|
|
||||||
m += '/'
|
|
||||||
else if (!isDir && slash)
|
|
||||||
m = m.slice(0, -1)
|
|
||||||
|
|
||||||
if (m !== p) {
|
|
||||||
this.statCache[m] = this.statCache[p]
|
|
||||||
this.cache[m] = this.cache[p]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
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.log('emitMatch', m)
|
|
||||||
this._emitQueue.push(m)
|
|
||||||
this._processEmitQueue()
|
|
||||||
}
|
|
||||||
|
|
||||||
Glob.prototype._processEmitQueue = function (m) {
|
|
||||||
this.log("pEQ paused=%j processing=%j m=%j", this.paused,
|
|
||||||
this._processingEmitQueue, m)
|
|
||||||
var done = false
|
|
||||||
while (!this._processingEmitQueue &&
|
|
||||||
!this.paused) {
|
|
||||||
this._processingEmitQueue = true
|
|
||||||
var m = this._emitQueue.shift()
|
|
||||||
this.log(">processEmitQueue", m === this.EOF ? ":EOF:" : m)
|
|
||||||
if (!m) {
|
|
||||||
this.log(">processEmitQueue, falsey m")
|
|
||||||
this._processingEmitQueue = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m === this.EOF || !(this.mark && !this.stat)) {
|
|
||||||
this.log("peq: unmarked, or eof")
|
|
||||||
next.call(this, 0, false)
|
|
||||||
} else if (this.statCache[m]) {
|
|
||||||
var sc = this.statCache[m]
|
|
||||||
var exists
|
|
||||||
if (sc)
|
|
||||||
exists = sc.isDirectory() ? 2 : 1
|
|
||||||
this.log("peq: stat cached")
|
|
||||||
next.call(this, exists, exists === 2)
|
|
||||||
} else {
|
|
||||||
this.log("peq: _stat, then next")
|
|
||||||
this._stat(m, next)
|
|
||||||
}
|
|
||||||
|
|
||||||
function next(exists, isDir) {
|
|
||||||
this.log("next", m, exists, isDir)
|
|
||||||
var ev = m === this.EOF ? "end" : "match"
|
|
||||||
|
|
||||||
// "end" can only happen once.
|
|
||||||
assert(!this._endEmitted)
|
|
||||||
if (ev === "end")
|
|
||||||
this._endEmitted = true
|
|
||||||
|
|
||||||
if (exists) {
|
|
||||||
// Doesn't mean it necessarily doesn't exist, it's possible
|
|
||||||
// we just didn't check because we don't care that much, or
|
|
||||||
// this is EOF anyway.
|
|
||||||
if (isDir && !m.match(/\/$/)) {
|
|
||||||
m = m + "/"
|
|
||||||
} else if (!isDir && m.match(/\/$/)) {
|
|
||||||
m = m.replace(/\/+$/, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.log("emit", ev, m)
|
|
||||||
this.emit(ev, m)
|
|
||||||
this._processingEmitQueue = false
|
|
||||||
if (done && m !== this.EOF && !this.paused)
|
|
||||||
this._processEmitQueue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done = true
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
s = s.filter(function (pattern) {
|
|
||||||
var key = gsKey(pattern)
|
|
||||||
var seen = !this._globstars[key]
|
|
||||||
this._globstars[key] = true
|
|
||||||
return seen
|
|
||||||
}, this)
|
|
||||||
|
|
||||||
if (!s.length)
|
|
||||||
return cb()
|
|
||||||
|
|
||||||
// now asyncForEach over this
|
|
||||||
var l = s.length
|
|
||||||
, errState = null
|
|
||||||
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]
|
|
||||||
var rawGlob = pattern[n]._glob
|
|
||||||
, dotOk = this.dot || rawGlob.charAt(0) === "."
|
|
||||||
|
|
||||||
entries = entries.filter(function (e) {
|
|
||||||
return (e.charAt(0) !== "." || dotOk) &&
|
|
||||||
e.match(pattern[n])
|
|
||||||
})
|
|
||||||
|
|
||||||
// If n === pattern.length - 1, then there's no need for the extra stat
|
|
||||||
// *unless* the user has specified "mark" or "stat" explicitly.
|
|
||||||
// We know that they exist, since the readdir returned them.
|
|
||||||
if (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)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function gsKey (pattern) {
|
|
||||||
return '**' + pattern.map(function (p) {
|
|
||||||
return (p === minimatch.GLOBSTAR) ? '**' : (''+p)
|
|
||||||
}).join('/')
|
|
||||||
}
|
|
||||||
|
|
||||||
Glob.prototype._stat = function (f, cb) {
|
|
||||||
assert(this instanceof Glob)
|
|
||||||
var abs = f
|
|
||||||
if (f.charAt(0) === "/") {
|
|
||||||
abs = path.join(this.root, f)
|
|
||||||
} else if (this.changedCwd) {
|
|
||||||
abs = path.resolve(this.cwd, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('stat', [this.cwd, f, '=', abs])
|
|
||||||
|
|
||||||
if (!this.stat && this.cache.hasOwnProperty(f)) {
|
|
||||||
var exists = this.cache[f]
|
|
||||||
, isDir = exists && (Array.isArray(exists) || exists === 2)
|
|
||||||
if (this.sync) return cb.call(this, !!exists, isDir)
|
|
||||||
return process.nextTick(cb.bind(this, !!exists, isDir))
|
|
||||||
}
|
|
||||||
|
|
||||||
var stat = this.statCache[abs]
|
|
||||||
if (this.sync || stat) {
|
|
||||||
var er
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
var emit = !this.statCache[abs]
|
|
||||||
this.statCache[abs] = stat
|
|
||||||
|
|
||||||
if (er || !stat) {
|
|
||||||
exists = false
|
|
||||||
} else {
|
|
||||||
exists = stat.isDirectory() ? 2 : 1
|
|
||||||
if (emit)
|
|
||||||
this.emit('stat', f, stat)
|
|
||||||
}
|
|
||||||
this.cache[f] = this.cache[f] || exists
|
|
||||||
cb.call(this, !!exists, exists === 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
Glob.prototype._readdir = function (f, cb) {
|
|
||||||
assert(this instanceof Glob)
|
|
||||||
var abs = f
|
|
||||||
if (f.charAt(0) === "/") {
|
|
||||||
abs = path.join(this.root, f)
|
|
||||||
} else if (isAbsolute(f)) {
|
|
||||||
abs = f
|
|
||||||
} else if (this.changedCwd) {
|
|
||||||
abs = path.resolve(this.cwd, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (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)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log('readdir', [this.cwd, f, abs])
|
|
||||||
if (this.cache.hasOwnProperty(f)) {
|
|
||||||
var c = this.cache[f]
|
|
||||||
if (Array.isArray(c)) {
|
|
||||||
if (this.sync) return cb.call(this, null, c)
|
|
||||||
return process.nextTick(cb.bind(this, null, c))
|
|
||||||
}
|
|
||||||
|
|
||||||
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.cache[f] = entries
|
|
||||||
// if we haven't asked to stat everything for suresies, then just
|
|
||||||
// assume that everything in there exists, so we can avoid
|
|
||||||
// having to stat it a second time. This also gets us one step
|
|
||||||
// further into ELOOP territory.
|
|
||||||
if (!this.mark && !this.stat) {
|
|
||||||
entries.forEach(function (e) {
|
|
||||||
if (f === "/") e = f + e
|
|
||||||
else e = f + "/" + e
|
|
||||||
this.cache[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.cache[f] = 1
|
|
||||||
return cb.call(this, er)
|
|
||||||
case "ENOENT": // not terribly unusual
|
|
||||||
case "ELOOP":
|
|
||||||
case "ENAMETOOLONG":
|
|
||||||
case "UNKNOWN":
|
|
||||||
this.cache[f] = false
|
|
||||||
return cb.call(this, er)
|
|
||||||
default: // some unusual error. Treat as failure.
|
|
||||||
this.cache[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 === ""
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
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.
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
Browser-friendly inheritance fully compatible with standard node.js
|
|
||||||
[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).
|
|
||||||
|
|
||||||
This package exports standard `inherits` from node.js `util` module in
|
|
||||||
node environment, but also provides alternative browser-friendly
|
|
||||||
implementation through [browser
|
|
||||||
field](https://gist.github.com/shtylman/4339901). Alternative
|
|
||||||
implementation is a literal copy of standard one located in standalone
|
|
||||||
module to avoid requiring of `util`. It also has a shim for old
|
|
||||||
browsers with no `Object.create` support.
|
|
||||||
|
|
||||||
While keeping you sure you are using standard `inherits`
|
|
||||||
implementation in node.js environment, it allows bundlers such as
|
|
||||||
[browserify](https://github.com/substack/node-browserify) to not
|
|
||||||
include full `util` package to your client code if all you need is
|
|
||||||
just `inherits` function. It worth, because browser shim for `util`
|
|
||||||
package is large and `inherits` is often the single function you need
|
|
||||||
from it.
|
|
||||||
|
|
||||||
It's recommended to use this package instead of
|
|
||||||
`require('util').inherits` for any code that has chances to be used
|
|
||||||
not only in node.js but in browser too.
|
|
||||||
|
|
||||||
## usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
var inherits = require('inherits');
|
|
||||||
// then use exactly as the standard one
|
|
||||||
```
|
|
||||||
|
|
||||||
## note on version ~1.0
|
|
||||||
|
|
||||||
Version ~1.0 had completely different motivation and is not compatible
|
|
||||||
neither with 2.0 nor with standard node.js `inherits`.
|
|
||||||
|
|
||||||
If you are using version ~1.0 and planning to switch to ~2.0, be
|
|
||||||
careful:
|
|
||||||
|
|
||||||
* new version uses `super_` instead of `super` for referencing
|
|
||||||
superclass
|
|
||||||
* new version overwrites current prototype while old one preserves any
|
|
||||||
existing fields on it
|
|
|
@ -1 +0,0 @@
|
||||||
module.exports = require('util').inherits
|
|
|
@ -1,23 +0,0 @@
|
||||||
if (typeof Object.create === 'function') {
|
|
||||||
// implementation from standard node.js 'util' module
|
|
||||||
module.exports = function inherits(ctor, superCtor) {
|
|
||||||
ctor.super_ = superCtor
|
|
||||||
ctor.prototype = Object.create(superCtor.prototype, {
|
|
||||||
constructor: {
|
|
||||||
value: ctor,
|
|
||||||
enumerable: false,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// old school shim for old browsers
|
|
||||||
module.exports = function inherits(ctor, superCtor) {
|
|
||||||
ctor.super_ = superCtor
|
|
||||||
var TempCtor = function () {}
|
|
||||||
TempCtor.prototype = superCtor.prototype
|
|
||||||
ctor.prototype = new TempCtor()
|
|
||||||
ctor.prototype.constructor = ctor
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
{
|
|
||||||
"name": "inherits",
|
|
||||||
"description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
|
|
||||||
"version": "2.0.1",
|
|
||||||
"keywords": [
|
|
||||||
"inheritance",
|
|
||||||
"class",
|
|
||||||
"klass",
|
|
||||||
"oop",
|
|
||||||
"object-oriented",
|
|
||||||
"inherits",
|
|
||||||
"browser",
|
|
||||||
"browserify"
|
|
||||||
],
|
|
||||||
"main": "./inherits.js",
|
|
||||||
"browser": "./inherits_browser.js",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/inherits"
|
|
||||||
},
|
|
||||||
"license": "ISC",
|
|
||||||
"scripts": {
|
|
||||||
"test": "node test"
|
|
||||||
},
|
|
||||||
"readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n superclass\n* new version overwrites current prototype while old one preserves any\n existing fields on it\n",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/inherits/issues"
|
|
||||||
},
|
|
||||||
"_id": "inherits@2.0.1",
|
|
||||||
"dist": {
|
|
||||||
"shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
|
|
||||||
"tarball": "http://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
|
||||||
},
|
|
||||||
"_from": "inherits@2",
|
|
||||||
"_npmVersion": "1.3.8",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directories": {},
|
|
||||||
"_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
|
|
||||||
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
|
|
||||||
"homepage": "https://github.com/isaacs/inherits"
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
var inherits = require('./inherits.js')
|
|
||||||
var assert = require('assert')
|
|
||||||
|
|
||||||
function test(c) {
|
|
||||||
assert(c.constructor === Child)
|
|
||||||
assert(c.constructor.super_ === Parent)
|
|
||||||
assert(Object.getPrototypeOf(c) === Child.prototype)
|
|
||||||
assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype)
|
|
||||||
assert(c instanceof Child)
|
|
||||||
assert(c instanceof Parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
function Child() {
|
|
||||||
Parent.call(this)
|
|
||||||
test(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
function Parent() {}
|
|
||||||
|
|
||||||
inherits(Child, Parent)
|
|
||||||
|
|
||||||
var c = new Child
|
|
||||||
test(c)
|
|
||||||
|
|
||||||
console.log('ok')
|
|
|
@ -1,23 +0,0 @@
|
||||||
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.
|
|
|
@ -1,218 +0,0 @@
|
||||||
# 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 if this option is set. When not 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.
|
|
|
@ -1,1061 +0,0 @@
|
||||||
;(function (require, exports, module, platform) {
|
|
||||||
|
|
||||||
if (module) module.exports = minimatch
|
|
||||||
else exports.minimatch = minimatch
|
|
||||||
|
|
||||||
if (!require) {
|
|
||||||
require = function (id) {
|
|
||||||
switch (id) {
|
|
||||||
case "sigmund": return function sigmund (obj) {
|
|
||||||
return JSON.stringify(obj)
|
|
||||||
}
|
|
||||||
case "path": return { basename: function (f) {
|
|
||||||
f = f.split(/[\/\\]/)
|
|
||||||
var e = f.pop()
|
|
||||||
if (!e) e = f.pop()
|
|
||||||
return e
|
|
||||||
}}
|
|
||||||
case "lru-cache": return function LRUCache () {
|
|
||||||
// not quite an LRU, but still space-limited.
|
|
||||||
var cache = {}
|
|
||||||
var cnt = 0
|
|
||||||
this.set = function (k, v) {
|
|
||||||
cnt ++
|
|
||||||
if (cnt >= 100) cache = {}
|
|
||||||
cache[k] = v
|
|
||||||
}
|
|
||||||
this.get = function (k) { return cache[k] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
minimatch.Minimatch = Minimatch
|
|
||||||
|
|
||||||
var LRU = require("lru-cache")
|
|
||||||
, cache = minimatch.cache = new LRU({max: 100})
|
|
||||||
, GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
|
|
||||||
, sigmund = require("sigmund")
|
|
||||||
|
|
||||||
var path = require("path")
|
|
||||||
// any single thing other than /
|
|
||||||
// don't need to escape / when using new RegExp()
|
|
||||||
, qmark = "[^/]"
|
|
||||||
|
|
||||||
// * => any number of characters
|
|
||||||
, star = qmark + "*?"
|
|
||||||
|
|
||||||
// ** when dots are allowed. Anything goes, except .. and .
|
|
||||||
// not (^ or / followed by one or two dots followed by $ or /),
|
|
||||||
// followed by anything, any number of times.
|
|
||||||
, twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?"
|
|
||||||
|
|
||||||
// not a ^ or / followed by a dot,
|
|
||||||
// followed by anything, any number of times.
|
|
||||||
, twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?"
|
|
||||||
|
|
||||||
// characters that need to be escaped in RegExp.
|
|
||||||
, reSpecials = charSet("().*{}+?[]^$\\!")
|
|
||||||
|
|
||||||
// "abc" -> { a:true, b:true, c:true }
|
|
||||||
function charSet (s) {
|
|
||||||
return s.split("").reduce(function (set, c) {
|
|
||||||
set[c] = true
|
|
||||||
return set
|
|
||||||
}, {})
|
|
||||||
}
|
|
||||||
|
|
||||||
// normalizes slashes.
|
|
||||||
var slashSplit = /\/+/
|
|
||||||
|
|
||||||
minimatch.filter = filter
|
|
||||||
function filter (pattern, options) {
|
|
||||||
options = options || {}
|
|
||||||
return function (p, i, list) {
|
|
||||||
return minimatch(p, pattern, options)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ext (a, b) {
|
|
||||||
a = a || {}
|
|
||||||
b = b || {}
|
|
||||||
var t = {}
|
|
||||||
Object.keys(b).forEach(function (k) {
|
|
||||||
t[k] = b[k]
|
|
||||||
})
|
|
||||||
Object.keys(a).forEach(function (k) {
|
|
||||||
t[k] = a[k]
|
|
||||||
})
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
minimatch.defaults = function (def) {
|
|
||||||
if (!def || !Object.keys(def).length) return minimatch
|
|
||||||
|
|
||||||
var orig = minimatch
|
|
||||||
|
|
||||||
var m = function minimatch (p, pattern, options) {
|
|
||||||
return orig.minimatch(p, pattern, ext(def, options))
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Minimatch = function Minimatch (pattern, options) {
|
|
||||||
return new orig.Minimatch(pattern, ext(def, options))
|
|
||||||
}
|
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
Minimatch.defaults = function (def) {
|
|
||||||
if (!def || !Object.keys(def).length) return Minimatch
|
|
||||||
return minimatch.defaults(def).Minimatch
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function minimatch (p, pattern, options) {
|
|
||||||
if (typeof pattern !== "string") {
|
|
||||||
throw new TypeError("glob pattern string required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options) options = {}
|
|
||||||
|
|
||||||
// shortcut: comments match nothing.
|
|
||||||
if (!options.nocomment && pattern.charAt(0) === "#") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// "" only matches ""
|
|
||||||
if (pattern.trim() === "") return p === ""
|
|
||||||
|
|
||||||
return new Minimatch(pattern, options).match(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
function Minimatch (pattern, options) {
|
|
||||||
if (!(this instanceof Minimatch)) {
|
|
||||||
return new Minimatch(pattern, options, cache)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof pattern !== "string") {
|
|
||||||
throw new TypeError("glob pattern string required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options) options = {}
|
|
||||||
pattern = pattern.trim()
|
|
||||||
|
|
||||||
// windows: need to use /, not \
|
|
||||||
// On other platforms, \ is a valid (albeit bad) filename char.
|
|
||||||
if (platform === "win32") {
|
|
||||||
pattern = pattern.split("\\").join("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
// lru storage.
|
|
||||||
// these things aren't particularly big, but walking down the string
|
|
||||||
// and turning it into a regexp can get pretty costly.
|
|
||||||
var cacheKey = pattern + "\n" + sigmund(options)
|
|
||||||
var cached = minimatch.cache.get(cacheKey)
|
|
||||||
if (cached) return cached
|
|
||||||
minimatch.cache.set(cacheKey, this)
|
|
||||||
|
|
||||||
this.options = options
|
|
||||||
this.set = []
|
|
||||||
this.pattern = pattern
|
|
||||||
this.regexp = null
|
|
||||||
this.negate = false
|
|
||||||
this.comment = false
|
|
||||||
this.empty = false
|
|
||||||
|
|
||||||
// make the set of regexps etc.
|
|
||||||
this.make()
|
|
||||||
}
|
|
||||||
|
|
||||||
Minimatch.prototype.debug = function() {}
|
|
||||||
|
|
||||||
Minimatch.prototype.make = make
|
|
||||||
function make () {
|
|
||||||
// don't do it more than once.
|
|
||||||
if (this._made) return
|
|
||||||
|
|
||||||
var pattern = this.pattern
|
|
||||||
var options = this.options
|
|
||||||
|
|
||||||
// empty patterns and comments match nothing.
|
|
||||||
if (!options.nocomment && pattern.charAt(0) === "#") {
|
|
||||||
this.comment = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!pattern) {
|
|
||||||
this.empty = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// step 1: figure out negation, etc.
|
|
||||||
this.parseNegate()
|
|
||||||
|
|
||||||
// step 2: expand braces
|
|
||||||
var set = this.globSet = this.braceExpand()
|
|
||||||
|
|
||||||
if (options.debug) this.debug = console.error
|
|
||||||
|
|
||||||
this.debug(this.pattern, set)
|
|
||||||
|
|
||||||
// step 3: now we have a set, so turn each one into a series of path-portion
|
|
||||||
// matching patterns.
|
|
||||||
// These will be regexps, except in the case of "**", which is
|
|
||||||
// set to the GLOBSTAR object for globstar behavior,
|
|
||||||
// and will not contain any / characters
|
|
||||||
set = this.globParts = set.map(function (s) {
|
|
||||||
return s.split(slashSplit)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.debug(this.pattern, set)
|
|
||||||
|
|
||||||
// glob --> regexps
|
|
||||||
set = set.map(function (s, si, set) {
|
|
||||||
return s.map(this.parse, this)
|
|
||||||
}, this)
|
|
||||||
|
|
||||||
this.debug(this.pattern, set)
|
|
||||||
|
|
||||||
// filter out everything that didn't compile properly.
|
|
||||||
set = set.filter(function (s) {
|
|
||||||
return -1 === s.indexOf(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.debug(this.pattern, set)
|
|
||||||
|
|
||||||
this.set = set
|
|
||||||
}
|
|
||||||
|
|
||||||
Minimatch.prototype.parseNegate = parseNegate
|
|
||||||
function parseNegate () {
|
|
||||||
var pattern = this.pattern
|
|
||||||
, negate = false
|
|
||||||
, options = this.options
|
|
||||||
, negateOffset = 0
|
|
||||||
|
|
||||||
if (options.nonegate) return
|
|
||||||
|
|
||||||
for ( var i = 0, l = pattern.length
|
|
||||||
; i < l && pattern.charAt(i) === "!"
|
|
||||||
; i ++) {
|
|
||||||
negate = !negate
|
|
||||||
negateOffset ++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
|
||||||
this.negate = negate
|
|
||||||
}
|
|
||||||
|
|
||||||
// Brace expansion:
|
|
||||||
// a{b,c}d -> abd acd
|
|
||||||
// a{b,}c -> abc ac
|
|
||||||
// a{0..3}d -> a0d a1d a2d a3d
|
|
||||||
// a{b,c{d,e}f}g -> abg acdfg acefg
|
|
||||||
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
|
||||||
//
|
|
||||||
// Invalid sets are not expanded.
|
|
||||||
// a{2..}b -> a{2..}b
|
|
||||||
// a{b}c -> a{b}c
|
|
||||||
minimatch.braceExpand = function (pattern, options) {
|
|
||||||
return new Minimatch(pattern, options).braceExpand()
|
|
||||||
}
|
|
||||||
|
|
||||||
Minimatch.prototype.braceExpand = braceExpand
|
|
||||||
function braceExpand (pattern, options) {
|
|
||||||
options = options || this.options
|
|
||||||
pattern = typeof pattern === "undefined"
|
|
||||||
? this.pattern : pattern
|
|
||||||
|
|
||||||
if (typeof pattern === "undefined") {
|
|
||||||
throw new Error("undefined pattern")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.nobrace ||
|
|
||||||
!pattern.match(/\{.*\}/)) {
|
|
||||||
// shortcut. no need to expand.
|
|
||||||
return [pattern]
|
|
||||||
}
|
|
||||||
|
|
||||||
var escaping = false
|
|
||||||
|
|
||||||
// examples and comments refer to this crazy pattern:
|
|
||||||
// a{b,c{d,e},{f,g}h}x{y,z}
|
|
||||||
// expected:
|
|
||||||
// abxy
|
|
||||||
// abxz
|
|
||||||
// acdxy
|
|
||||||
// acdxz
|
|
||||||
// acexy
|
|
||||||
// acexz
|
|
||||||
// afhxy
|
|
||||||
// afhxz
|
|
||||||
// aghxy
|
|
||||||
// aghxz
|
|
||||||
|
|
||||||
// everything before the first \{ is just a prefix.
|
|
||||||
// So, we pluck that off, and work with the rest,
|
|
||||||
// and then prepend it to everything we find.
|
|
||||||
if (pattern.charAt(0) !== "{") {
|
|
||||||
this.debug(pattern)
|
|
||||||
var prefix = null
|
|
||||||
for (var i = 0, l = pattern.length; i < l; i ++) {
|
|
||||||
var c = pattern.charAt(i)
|
|
||||||
this.debug(i, c)
|
|
||||||
if (c === "\\") {
|
|
||||||
escaping = !escaping
|
|
||||||
} else if (c === "{" && !escaping) {
|
|
||||||
prefix = pattern.substr(0, i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// actually no sets, all { were escaped.
|
|
||||||
if (prefix === null) {
|
|
||||||
this.debug("no sets")
|
|
||||||
return [pattern]
|
|
||||||
}
|
|
||||||
|
|
||||||
var tail = braceExpand.call(this, pattern.substr(i), options)
|
|
||||||
return tail.map(function (t) {
|
|
||||||
return prefix + t
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we have something like:
|
|
||||||
// {b,c{d,e},{f,g}h}x{y,z}
|
|
||||||
// walk through the set, expanding each part, until
|
|
||||||
// the set ends. then, we'll expand the suffix.
|
|
||||||
// If the set only has a single member, then'll put the {} back
|
|
||||||
|
|
||||||
// first, handle numeric sets, since they're easier
|
|
||||||
var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/)
|
|
||||||
if (numset) {
|
|
||||||
this.debug("numset", numset[1], numset[2])
|
|
||||||
var suf = braceExpand.call(this, pattern.substr(numset[0].length), options)
|
|
||||||
, start = +numset[1]
|
|
||||||
, end = +numset[2]
|
|
||||||
, inc = start > end ? -1 : 1
|
|
||||||
, set = []
|
|
||||||
for (var i = start; i != (end + inc); i += inc) {
|
|
||||||
// append all the suffixes
|
|
||||||
for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
|
|
||||||
set.push(i + suf[ii])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return set
|
|
||||||
}
|
|
||||||
|
|
||||||
// ok, walk through the set
|
|
||||||
// We hope, somewhat optimistically, that there
|
|
||||||
// will be a } at the end.
|
|
||||||
// If the closing brace isn't found, then the pattern is
|
|
||||||
// interpreted as braceExpand("\\" + pattern) so that
|
|
||||||
// the leading \{ will be interpreted literally.
|
|
||||||
var i = 1 // skip the \{
|
|
||||||
, depth = 1
|
|
||||||
, set = []
|
|
||||||
, member = ""
|
|
||||||
, sawEnd = false
|
|
||||||
, escaping = false
|
|
||||||
|
|
||||||
function addMember () {
|
|
||||||
set.push(member)
|
|
||||||
member = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
this.debug("Entering for")
|
|
||||||
FOR: for (i = 1, l = pattern.length; i < l; i ++) {
|
|
||||||
var c = pattern.charAt(i)
|
|
||||||
this.debug("", i, c)
|
|
||||||
|
|
||||||
if (escaping) {
|
|
||||||
escaping = false
|
|
||||||
member += "\\" + c
|
|
||||||
} else {
|
|
||||||
switch (c) {
|
|
||||||
case "\\":
|
|
||||||
escaping = true
|
|
||||||
continue
|
|
||||||
|
|
||||||
case "{":
|
|
||||||
depth ++
|
|
||||||
member += "{"
|
|
||||||
continue
|
|
||||||
|
|
||||||
case "}":
|
|
||||||
depth --
|
|
||||||
// if this closes the actual set, then we're done
|
|
||||||
if (depth === 0) {
|
|
||||||
addMember()
|
|
||||||
// pluck off the close-brace
|
|
||||||
i ++
|
|
||||||
break FOR
|
|
||||||
} else {
|
|
||||||
member += c
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
case ",":
|
|
||||||
if (depth === 1) {
|
|
||||||
addMember()
|
|
||||||
} else {
|
|
||||||
member += c
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
|
|
||||||
default:
|
|
||||||
member += c
|
|
||||||
continue
|
|
||||||
} // switch
|
|
||||||
} // else
|
|
||||||
} // for
|
|
||||||
|
|
||||||
// now we've either finished the set, and the suffix is
|
|
||||||
// pattern.substr(i), or we have *not* closed the set,
|
|
||||||
// and need to escape the leading brace
|
|
||||||
if (depth !== 0) {
|
|
||||||
this.debug("didn't close", pattern)
|
|
||||||
return braceExpand.call(this, "\\" + pattern, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
// x{y,z} -> ["xy", "xz"]
|
|
||||||
this.debug("set", set)
|
|
||||||
this.debug("suffix", pattern.substr(i))
|
|
||||||
var suf = braceExpand.call(this, pattern.substr(i), options)
|
|
||||||
// ["b", "c{d,e}","{f,g}h"] ->
|
|
||||||
// [["b"], ["cd", "ce"], ["fh", "gh"]]
|
|
||||||
var addBraces = set.length === 1
|
|
||||||
this.debug("set pre-expanded", set)
|
|
||||||
set = set.map(function (p) {
|
|
||||||
return braceExpand.call(this, p, options)
|
|
||||||
}, this)
|
|
||||||
this.debug("set expanded", set)
|
|
||||||
|
|
||||||
|
|
||||||
// [["b"], ["cd", "ce"], ["fh", "gh"]] ->
|
|
||||||
// ["b", "cd", "ce", "fh", "gh"]
|
|
||||||
set = set.reduce(function (l, r) {
|
|
||||||
return l.concat(r)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (addBraces) {
|
|
||||||
set = set.map(function (s) {
|
|
||||||
return "{" + s + "}"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// now attach the suffixes.
|
|
||||||
var ret = []
|
|
||||||
for (var i = 0, l = set.length; i < l; i ++) {
|
|
||||||
for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
|
|
||||||
ret.push(set[i] + suf[ii])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse a component of the expanded set.
|
|
||||||
// At this point, no pattern may contain "/" in it
|
|
||||||
// so we're going to return a 2d array, where each entry is the full
|
|
||||||
// pattern, split on '/', and then turned into a regular expression.
|
|
||||||
// A regexp is made at the end which joins each array with an
|
|
||||||
// escaped /, and another full one which joins each regexp with |.
|
|
||||||
//
|
|
||||||
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
|
||||||
// when it is the *only* thing in a path portion. Otherwise, any series
|
|
||||||
// of * is equivalent to a single *. Globstar behavior is enabled by
|
|
||||||
// default, and can be disabled by setting options.noglobstar.
|
|
||||||
Minimatch.prototype.parse = parse
|
|
||||||
var SUBPARSE = {}
|
|
||||||
function parse (pattern, isSub) {
|
|
||||||
var options = this.options
|
|
||||||
|
|
||||||
// shortcuts
|
|
||||||
if (!options.noglobstar && pattern === "**") return GLOBSTAR
|
|
||||||
if (pattern === "") return ""
|
|
||||||
|
|
||||||
var re = ""
|
|
||||||
, hasMagic = !!options.nocase
|
|
||||||
, escaping = false
|
|
||||||
// ? => one single character
|
|
||||||
, patternListStack = []
|
|
||||||
, plType
|
|
||||||
, stateChar
|
|
||||||
, inClass = false
|
|
||||||
, reClassStart = -1
|
|
||||||
, classStart = -1
|
|
||||||
// . and .. never match anything that doesn't start with .,
|
|
||||||
// even when options.dot is set.
|
|
||||||
, patternStart = pattern.charAt(0) === "." ? "" // anything
|
|
||||||
// not (start or / followed by . or .. followed by / or end)
|
|
||||||
: options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))"
|
|
||||||
: "(?!\\.)"
|
|
||||||
, self = this
|
|
||||||
|
|
||||||
function clearStateChar () {
|
|
||||||
if (stateChar) {
|
|
||||||
// we had some state-tracking character
|
|
||||||
// that wasn't consumed by this pass.
|
|
||||||
switch (stateChar) {
|
|
||||||
case "*":
|
|
||||||
re += star
|
|
||||||
hasMagic = true
|
|
||||||
break
|
|
||||||
case "?":
|
|
||||||
re += qmark
|
|
||||||
hasMagic = true
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
re += "\\"+stateChar
|
|
||||||
break
|
|
||||||
}
|
|
||||||
self.debug('clearStateChar %j %j', stateChar, re)
|
|
||||||
stateChar = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( var i = 0, len = pattern.length, c
|
|
||||||
; (i < len) && (c = pattern.charAt(i))
|
|
||||||
; i ++ ) {
|
|
||||||
|
|
||||||
this.debug("%s\t%s %s %j", pattern, i, re, c)
|
|
||||||
|
|
||||||
// skip over any that are escaped.
|
|
||||||
if (escaping && reSpecials[c]) {
|
|
||||||
re += "\\" + c
|
|
||||||
escaping = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
SWITCH: switch (c) {
|
|
||||||
case "/":
|
|
||||||
// completely not allowed, even escaped.
|
|
||||||
// Should already be path-split by now.
|
|
||||||
return false
|
|
||||||
|
|
||||||
case "\\":
|
|
||||||
clearStateChar()
|
|
||||||
escaping = true
|
|
||||||
continue
|
|
||||||
|
|
||||||
// the various stateChar values
|
|
||||||
// for the "extglob" stuff.
|
|
||||||
case "?":
|
|
||||||
case "*":
|
|
||||||
case "+":
|
|
||||||
case "@":
|
|
||||||
case "!":
|
|
||||||
this.debug("%s\t%s %s %j <-- stateChar", pattern, i, re, c)
|
|
||||||
|
|
||||||
// all of those are literals inside a class, except that
|
|
||||||
// the glob [!a] means [^a] in regexp
|
|
||||||
if (inClass) {
|
|
||||||
this.debug(' in class')
|
|
||||||
if (c === "!" && i === classStart + 1) c = "^"
|
|
||||||
re += c
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we already have a stateChar, then it means
|
|
||||||
// that there was something like ** or +? in there.
|
|
||||||
// Handle the stateChar, then proceed with this one.
|
|
||||||
self.debug('call clearStateChar %j', stateChar)
|
|
||||||
clearStateChar()
|
|
||||||
stateChar = c
|
|
||||||
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|
||||||
// just clear the statechar *now*, rather than even diving into
|
|
||||||
// the patternList stuff.
|
|
||||||
if (options.noext) clearStateChar()
|
|
||||||
continue
|
|
||||||
|
|
||||||
case "(":
|
|
||||||
if (inClass) {
|
|
||||||
re += "("
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stateChar) {
|
|
||||||
re += "\\("
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
plType = stateChar
|
|
||||||
patternListStack.push({ type: plType
|
|
||||||
, start: i - 1
|
|
||||||
, reStart: re.length })
|
|
||||||
// negation is (?:(?!js)[^/]*)
|
|
||||||
re += stateChar === "!" ? "(?:(?!" : "(?:"
|
|
||||||
this.debug('plType %j %j', stateChar, re)
|
|
||||||
stateChar = false
|
|
||||||
continue
|
|
||||||
|
|
||||||
case ")":
|
|
||||||
if (inClass || !patternListStack.length) {
|
|
||||||
re += "\\)"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
clearStateChar()
|
|
||||||
hasMagic = true
|
|
||||||
re += ")"
|
|
||||||
plType = patternListStack.pop().type
|
|
||||||
// negation is (?:(?!js)[^/]*)
|
|
||||||
// The others are (?:<pattern>)<type>
|
|
||||||
switch (plType) {
|
|
||||||
case "!":
|
|
||||||
re += "[^/]*?)"
|
|
||||||
break
|
|
||||||
case "?":
|
|
||||||
case "+":
|
|
||||||
case "*": re += plType
|
|
||||||
case "@": break // the default anyway
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
|
|
||||||
case "|":
|
|
||||||
if (inClass || !patternListStack.length || escaping) {
|
|
||||||
re += "\\|"
|
|
||||||
escaping = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
clearStateChar()
|
|
||||||
re += "|"
|
|
||||||
continue
|
|
||||||
|
|
||||||
// these are mostly the same in regexp and glob
|
|
||||||
case "[":
|
|
||||||
// swallow any state-tracking char before the [
|
|
||||||
clearStateChar()
|
|
||||||
|
|
||||||
if (inClass) {
|
|
||||||
re += "\\" + c
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
inClass = true
|
|
||||||
classStart = i
|
|
||||||
reClassStart = re.length
|
|
||||||
re += c
|
|
||||||
continue
|
|
||||||
|
|
||||||
case "]":
|
|
||||||
// a right bracket shall lose its special
|
|
||||||
// meaning and represent itself in
|
|
||||||
// a bracket expression if it occurs
|
|
||||||
// first in the list. -- POSIX.2 2.8.3.2
|
|
||||||
if (i === classStart + 1 || !inClass) {
|
|
||||||
re += "\\" + c
|
|
||||||
escaping = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish up the class.
|
|
||||||
hasMagic = true
|
|
||||||
inClass = false
|
|
||||||
re += c
|
|
||||||
continue
|
|
||||||
|
|
||||||
default:
|
|
||||||
// swallow any state char that wasn't consumed
|
|
||||||
clearStateChar()
|
|
||||||
|
|
||||||
if (escaping) {
|
|
||||||
// no need
|
|
||||||
escaping = false
|
|
||||||
} else if (reSpecials[c]
|
|
||||||
&& !(c === "^" && inClass)) {
|
|
||||||
re += "\\"
|
|
||||||
}
|
|
||||||
|
|
||||||
re += c
|
|
||||||
|
|
||||||
} // switch
|
|
||||||
} // for
|
|
||||||
|
|
||||||
|
|
||||||
// handle the case where we left a class open.
|
|
||||||
// "[abc" is valid, equivalent to "\[abc"
|
|
||||||
if (inClass) {
|
|
||||||
// split where the last [ was, and escape it
|
|
||||||
// this is a huge pita. We now have to re-walk
|
|
||||||
// the contents of the would-be class to re-translate
|
|
||||||
// any characters that were passed through as-is
|
|
||||||
var cs = pattern.substr(classStart + 1)
|
|
||||||
, sp = this.parse(cs, SUBPARSE)
|
|
||||||
re = re.substr(0, reClassStart) + "\\[" + sp[0]
|
|
||||||
hasMagic = hasMagic || sp[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle the case where we had a +( thing at the *end*
|
|
||||||
// of the pattern.
|
|
||||||
// each pattern list stack adds 3 chars, and we need to go through
|
|
||||||
// and escape any | chars that were passed through as-is for the regexp.
|
|
||||||
// Go through and escape them, taking care not to double-escape any
|
|
||||||
// | chars that were already escaped.
|
|
||||||
var pl
|
|
||||||
while (pl = patternListStack.pop()) {
|
|
||||||
var tail = re.slice(pl.reStart + 3)
|
|
||||||
// maybe some even number of \, then maybe 1 \, followed by a |
|
|
||||||
tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
|
|
||||||
if (!$2) {
|
|
||||||
// the | isn't already escaped, so escape it.
|
|
||||||
$2 = "\\"
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to escape all those slashes *again*, without escaping the
|
|
||||||
// one that we need for escaping the | character. As it works out,
|
|
||||||
// escaping an even number of slashes can be done by simply repeating
|
|
||||||
// it exactly after itself. That's why this trick works.
|
|
||||||
//
|
|
||||||
// I am sorry that you have to see this.
|
|
||||||
return $1 + $1 + $2 + "|"
|
|
||||||
})
|
|
||||||
|
|
||||||
this.debug("tail=%j\n %s", tail, tail)
|
|
||||||
var t = pl.type === "*" ? star
|
|
||||||
: pl.type === "?" ? qmark
|
|
||||||
: "\\" + pl.type
|
|
||||||
|
|
||||||
hasMagic = true
|
|
||||||
re = re.slice(0, pl.reStart)
|
|
||||||
+ t + "\\("
|
|
||||||
+ tail
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle trailing things that only matter at the very end.
|
|
||||||
clearStateChar()
|
|
||||||
if (escaping) {
|
|
||||||
// trailing \\
|
|
||||||
re += "\\\\"
|
|
||||||
}
|
|
||||||
|
|
||||||
// only need to apply the nodot start if the re starts with
|
|
||||||
// something that could conceivably capture a dot
|
|
||||||
var addPatternStart = false
|
|
||||||
switch (re.charAt(0)) {
|
|
||||||
case ".":
|
|
||||||
case "[":
|
|
||||||
case "(": addPatternStart = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the re is not "" at this point, then we need to make sure
|
|
||||||
// it doesn't match against an empty path part.
|
|
||||||
// Otherwise a/* will match a/, which it should not.
|
|
||||||
if (re !== "" && hasMagic) re = "(?=.)" + re
|
|
||||||
|
|
||||||
if (addPatternStart) re = patternStart + re
|
|
||||||
|
|
||||||
// parsing just a piece of a larger pattern.
|
|
||||||
if (isSub === SUBPARSE) {
|
|
||||||
return [ re, hasMagic ]
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip the regexp for non-magical patterns
|
|
||||||
// unescape anything in it, though, so that it'll be
|
|
||||||
// an exact match against a file etc.
|
|
||||||
if (!hasMagic) {
|
|
||||||
return globUnescape(pattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
var flags = options.nocase ? "i" : ""
|
|
||||||
, regExp = new RegExp("^" + re + "$", flags)
|
|
||||||
|
|
||||||
regExp._glob = pattern
|
|
||||||
regExp._src = re
|
|
||||||
|
|
||||||
return regExp
|
|
||||||
}
|
|
||||||
|
|
||||||
minimatch.makeRe = function (pattern, options) {
|
|
||||||
return new Minimatch(pattern, options || {}).makeRe()
|
|
||||||
}
|
|
||||||
|
|
||||||
Minimatch.prototype.makeRe = makeRe
|
|
||||||
function makeRe () {
|
|
||||||
if (this.regexp || this.regexp === false) return this.regexp
|
|
||||||
|
|
||||||
// at this point, this.set is a 2d array of partial
|
|
||||||
// pattern strings, or "**".
|
|
||||||
//
|
|
||||||
// It's better to use .match(). This function shouldn't
|
|
||||||
// be used, really, but it's pretty convenient sometimes,
|
|
||||||
// when you just want to work with a regex.
|
|
||||||
var set = this.set
|
|
||||||
|
|
||||||
if (!set.length) return this.regexp = false
|
|
||||||
var options = this.options
|
|
||||||
|
|
||||||
var twoStar = options.noglobstar ? star
|
|
||||||
: options.dot ? twoStarDot
|
|
||||||
: twoStarNoDot
|
|
||||||
, flags = options.nocase ? "i" : ""
|
|
||||||
|
|
||||||
var re = set.map(function (pattern) {
|
|
||||||
return pattern.map(function (p) {
|
|
||||||
return (p === GLOBSTAR) ? twoStar
|
|
||||||
: (typeof p === "string") ? regExpEscape(p)
|
|
||||||
: p._src
|
|
||||||
}).join("\\\/")
|
|
||||||
}).join("|")
|
|
||||||
|
|
||||||
// must match entire pattern
|
|
||||||
// ending in a * or ** will make it less strict.
|
|
||||||
re = "^(?:" + re + ")$"
|
|
||||||
|
|
||||||
// can match anything, as long as it's not this.
|
|
||||||
if (this.negate) re = "^(?!" + re + ").*$"
|
|
||||||
|
|
||||||
try {
|
|
||||||
return this.regexp = new RegExp(re, flags)
|
|
||||||
} catch (ex) {
|
|
||||||
return this.regexp = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
minimatch.match = function (list, pattern, options) {
|
|
||||||
options = options || {}
|
|
||||||
var mm = new Minimatch(pattern, options)
|
|
||||||
list = list.filter(function (f) {
|
|
||||||
return mm.match(f)
|
|
||||||
})
|
|
||||||
if (mm.options.nonull && !list.length) {
|
|
||||||
list.push(pattern)
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
Minimatch.prototype.match = match
|
|
||||||
function match (f, partial) {
|
|
||||||
this.debug("match", f, this.pattern)
|
|
||||||
// short-circuit in the case of busted things.
|
|
||||||
// comments, etc.
|
|
||||||
if (this.comment) return false
|
|
||||||
if (this.empty) return f === ""
|
|
||||||
|
|
||||||
if (f === "/" && partial) return true
|
|
||||||
|
|
||||||
var options = this.options
|
|
||||||
|
|
||||||
// windows: need to use /, not \
|
|
||||||
// On other platforms, \ is a valid (albeit bad) filename char.
|
|
||||||
if (platform === "win32") {
|
|
||||||
f = f.split("\\").join("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
// treat the test path as a set of pathparts.
|
|
||||||
f = f.split(slashSplit)
|
|
||||||
this.debug(this.pattern, "split", f)
|
|
||||||
|
|
||||||
// just ONE of the pattern sets in this.set needs to match
|
|
||||||
// in order for it to be valid. If negating, then just one
|
|
||||||
// match means that we have failed.
|
|
||||||
// Either way, return on the first hit.
|
|
||||||
|
|
||||||
var set = this.set
|
|
||||||
this.debug(this.pattern, "set", set)
|
|
||||||
|
|
||||||
// Find the basename of the path by looking for the last non-empty segment
|
|
||||||
var filename;
|
|
||||||
for (var i = f.length - 1; i >= 0; i--) {
|
|
||||||
filename = f[i]
|
|
||||||
if (filename) break
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0, l = set.length; i < l; i ++) {
|
|
||||||
var pattern = set[i], file = f
|
|
||||||
if (options.matchBase && pattern.length === 1) {
|
|
||||||
file = [filename]
|
|
||||||
}
|
|
||||||
var hit = this.matchOne(file, pattern, partial)
|
|
||||||
if (hit) {
|
|
||||||
if (options.flipNegate) return true
|
|
||||||
return !this.negate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// didn't get any hits. this is success if it's a negative
|
|
||||||
// pattern, failure otherwise.
|
|
||||||
if (options.flipNegate) return false
|
|
||||||
return this.negate
|
|
||||||
}
|
|
||||||
|
|
||||||
// set partial to true to test if, for example,
|
|
||||||
// "/a/b" matches the start of "/*/b/*/d"
|
|
||||||
// Partial means, if you run out of file before you run
|
|
||||||
// out of pattern, then that's fine, as long as all
|
|
||||||
// the parts match.
|
|
||||||
Minimatch.prototype.matchOne = function (file, pattern, partial) {
|
|
||||||
var options = this.options
|
|
||||||
|
|
||||||
this.debug("matchOne",
|
|
||||||
{ "this": this
|
|
||||||
, file: file
|
|
||||||
, pattern: pattern })
|
|
||||||
|
|
||||||
this.debug("matchOne", file.length, pattern.length)
|
|
||||||
|
|
||||||
for ( var fi = 0
|
|
||||||
, pi = 0
|
|
||||||
, fl = file.length
|
|
||||||
, pl = pattern.length
|
|
||||||
; (fi < fl) && (pi < pl)
|
|
||||||
; fi ++, pi ++ ) {
|
|
||||||
|
|
||||||
this.debug("matchOne loop")
|
|
||||||
var p = pattern[pi]
|
|
||||||
, f = file[fi]
|
|
||||||
|
|
||||||
this.debug(pattern, p, f)
|
|
||||||
|
|
||||||
// should be impossible.
|
|
||||||
// some invalid regexp stuff in the set.
|
|
||||||
if (p === false) return false
|
|
||||||
|
|
||||||
if (p === GLOBSTAR) {
|
|
||||||
this.debug('GLOBSTAR', [pattern, p, f])
|
|
||||||
|
|
||||||
// "**"
|
|
||||||
// a/**/b/**/c would match the following:
|
|
||||||
// a/b/x/y/z/c
|
|
||||||
// a/x/y/z/b/c
|
|
||||||
// a/b/x/b/x/c
|
|
||||||
// a/b/c
|
|
||||||
// To do this, take the rest of the pattern after
|
|
||||||
// the **, and see if it would match the file remainder.
|
|
||||||
// If so, return success.
|
|
||||||
// If not, the ** "swallows" a segment, and try again.
|
|
||||||
// This is recursively awful.
|
|
||||||
//
|
|
||||||
// a/**/b/**/c matching a/b/x/y/z/c
|
|
||||||
// - a matches a
|
|
||||||
// - doublestar
|
|
||||||
// - matchOne(b/x/y/z/c, b/**/c)
|
|
||||||
// - b matches b
|
|
||||||
// - doublestar
|
|
||||||
// - matchOne(x/y/z/c, c) -> no
|
|
||||||
// - matchOne(y/z/c, c) -> no
|
|
||||||
// - matchOne(z/c, c) -> no
|
|
||||||
// - matchOne(c, c) yes, hit
|
|
||||||
var fr = fi
|
|
||||||
, pr = pi + 1
|
|
||||||
if (pr === pl) {
|
|
||||||
this.debug('** at the end')
|
|
||||||
// a ** at the end will just swallow the rest.
|
|
||||||
// We have found a match.
|
|
||||||
// however, it will not swallow /.x, unless
|
|
||||||
// options.dot is set.
|
|
||||||
// . and .. are *never* matched by **, for explosively
|
|
||||||
// exponential reasons.
|
|
||||||
for ( ; fi < fl; fi ++) {
|
|
||||||
if (file[fi] === "." || file[fi] === ".." ||
|
|
||||||
(!options.dot && file[fi].charAt(0) === ".")) return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ok, let's see if we can swallow whatever we can.
|
|
||||||
WHILE: while (fr < fl) {
|
|
||||||
var swallowee = file[fr]
|
|
||||||
|
|
||||||
this.debug('\nglobstar while',
|
|
||||||
file, fr, pattern, pr, swallowee)
|
|
||||||
|
|
||||||
// XXX remove this slice. Just pass the start index.
|
|
||||||
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
|
||||||
this.debug('globstar found match!', fr, fl, swallowee)
|
|
||||||
// found a match.
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
// can't swallow "." or ".." ever.
|
|
||||||
// can only swallow ".foo" when explicitly asked.
|
|
||||||
if (swallowee === "." || swallowee === ".." ||
|
|
||||||
(!options.dot && swallowee.charAt(0) === ".")) {
|
|
||||||
this.debug("dot detected!", file, fr, pattern, pr)
|
|
||||||
break WHILE
|
|
||||||
}
|
|
||||||
|
|
||||||
// ** swallows a segment, and continue.
|
|
||||||
this.debug('globstar swallow a segment, and continue')
|
|
||||||
fr ++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// no match was found.
|
|
||||||
// However, in partial mode, we can't say this is necessarily over.
|
|
||||||
// If there's more *pattern* left, then
|
|
||||||
if (partial) {
|
|
||||||
// ran out of file
|
|
||||||
this.debug("\n>>> no match, partial?", file, fr, pattern, pr)
|
|
||||||
if (fr === fl) return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// something other than **
|
|
||||||
// non-magic patterns just have to match exactly
|
|
||||||
// patterns with magic have been turned into regexps.
|
|
||||||
var hit
|
|
||||||
if (typeof p === "string") {
|
|
||||||
if (options.nocase) {
|
|
||||||
hit = f.toLowerCase() === p.toLowerCase()
|
|
||||||
} else {
|
|
||||||
hit = f === p
|
|
||||||
}
|
|
||||||
this.debug("string match", p, f, hit)
|
|
||||||
} else {
|
|
||||||
hit = f.match(p)
|
|
||||||
this.debug("pattern match", p, f, hit)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hit) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: ending in / means that we'll get a final ""
|
|
||||||
// at the end of the pattern. This can only match a
|
|
||||||
// corresponding "" at the end of the file.
|
|
||||||
// If the file ends in /, then it can only match a
|
|
||||||
// a pattern that ends in /, unless the pattern just
|
|
||||||
// doesn't have any more for it. But, a/b/ should *not*
|
|
||||||
// match "a/b/*", even though "" matches against the
|
|
||||||
// [^/]*? pattern, except in partial mode, where it might
|
|
||||||
// simply not be reached yet.
|
|
||||||
// However, a/b/ should still satisfy a/*
|
|
||||||
|
|
||||||
// now either we fell off the end of the pattern, or we're done.
|
|
||||||
if (fi === fl && pi === pl) {
|
|
||||||
// ran out of pattern and filename at the same time.
|
|
||||||
// an exact hit!
|
|
||||||
return true
|
|
||||||
} else if (fi === fl) {
|
|
||||||
// ran out of file, but still had pattern left.
|
|
||||||
// this is ok if we're doing the match as part of
|
|
||||||
// a glob fs traversal.
|
|
||||||
return partial
|
|
||||||
} else if (pi === pl) {
|
|
||||||
// ran out of pattern, still have file left.
|
|
||||||
// this is only acceptable if we're on the very last
|
|
||||||
// empty segment of a file with a trailing slash.
|
|
||||||
// a/* should match a/b/
|
|
||||||
var emptyFileEnd = (fi === fl - 1) && (file[fi] === "")
|
|
||||||
return emptyFileEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
// should be unreachable.
|
|
||||||
throw new Error("wtf?")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// replace stuff like \* with *
|
|
||||||
function globUnescape (s) {
|
|
||||||
return s.replace(/\\(.)/g, "$1")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function regExpEscape (s) {
|
|
||||||
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
|
|
||||||
}
|
|
||||||
|
|
||||||
})( typeof require === "function" ? require : null,
|
|
||||||
this,
|
|
||||||
typeof module === "object" ? module : null,
|
|
||||||
typeof process === "object" ? process.platform : "win32"
|
|
||||||
)
|
|
|
@ -1 +0,0 @@
|
||||||
/node_modules
|
|
|
@ -1,14 +0,0 @@
|
||||||
# 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>
|
|
|
@ -1,23 +0,0 @@
|
||||||
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.
|
|
|
@ -1,97 +0,0 @@
|
||||||
# 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.
|
|
||||||
|
|
||||||
## 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 `n`
|
|
||||||
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)`
|
|
||||||
* `get(key) => value`
|
|
||||||
|
|
||||||
Both of these will update the "recently used"-ness of the key.
|
|
||||||
They do what you think.
|
|
||||||
|
|
||||||
* `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.
|
|
|
@ -1,252 +0,0 @@
|
||||||
;(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 }
|
|
||||||
|
|
||||||
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;
|
|
||||||
for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
|
|
||||||
i++
|
|
||||||
var hit = this._lruList[k]
|
|
||||||
if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provided for debugging/dev purposes only. No promises whatsoever that
|
|
||||||
// this API stays stable.
|
|
||||||
LRUCache.prototype.dump = function () {
|
|
||||||
return this._cache
|
|
||||||
}
|
|
||||||
|
|
||||||
LRUCache.prototype.dumpLru = function () {
|
|
||||||
return this._lruList
|
|
||||||
}
|
|
||||||
|
|
||||||
LRUCache.prototype.set = function (key, value) {
|
|
||||||
if (hOP(this._cache, key)) {
|
|
||||||
// dispose of the old one before overwriting
|
|
||||||
if (this._dispose) this._dispose(key, this._cache[key].value)
|
|
||||||
if (this._maxAge) this._cache[key].now = Date.now()
|
|
||||||
this._cache[key].value = value
|
|
||||||
this.get(key)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var len = this._lengthCalculator(value)
|
|
||||||
var age = this._maxAge ? Date.now() : 0
|
|
||||||
var hit = new Entry(key, value, this._mru++, len, age)
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
if (!hOP(this._cache, key)) return false
|
|
||||||
var hit = this._cache[key]
|
|
||||||
if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
LRUCache.prototype.get = function (key) {
|
|
||||||
return get(this, key, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
LRUCache.prototype.peek = function (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) {
|
|
||||||
del(this, this._cache[key])
|
|
||||||
}
|
|
||||||
|
|
||||||
function get (self, key, doUse) {
|
|
||||||
var hit = self._cache[key]
|
|
||||||
if (hit) {
|
|
||||||
if (self._maxAge && (Date.now() - hit.now > self._maxAge)) {
|
|
||||||
del(self, hit)
|
|
||||||
if (!self._allowStale) hit = undefined
|
|
||||||
} else {
|
|
||||||
if (doUse) use(self, hit)
|
|
||||||
}
|
|
||||||
if (hit) hit = hit.value
|
|
||||||
}
|
|
||||||
return hit
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
this.key = key
|
|
||||||
this.value = value
|
|
||||||
this.lu = lu
|
|
||||||
this.length = length
|
|
||||||
this.now = now
|
|
||||||
}
|
|
||||||
|
|
||||||
})()
|
|
|
@ -1,50 +0,0 @@
|
||||||
{
|
|
||||||
"name": "lru-cache",
|
|
||||||
"description": "A cache object that deletes the least-recently-used items.",
|
|
||||||
"version": "2.5.0",
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test --gc"
|
|
||||||
},
|
|
||||||
"main": "lib/lru-cache.js",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/node-lru-cache.git"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "",
|
|
||||||
"weak": ""
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/node-lru-cache/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/node-lru-cache",
|
|
||||||
"_id": "lru-cache@2.5.0",
|
|
||||||
"dist": {
|
|
||||||
"shasum": "d82388ae9c960becbea0c73bb9eb79b6c6ce9aeb",
|
|
||||||
"tarball": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz"
|
|
||||||
},
|
|
||||||
"_from": "lru-cache@2",
|
|
||||||
"_npmVersion": "1.3.15",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directories": {},
|
|
||||||
"_shasum": "d82388ae9c960becbea0c73bb9eb79b6c6ce9aeb",
|
|
||||||
"_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
|
@ -1,369 +0,0 @@
|
||||||
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()
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Note: `<cache>.dump()` is a debugging tool only. No guarantees are made
|
|
||||||
// about the format/layout of the response.
|
|
||||||
test("dump", function (t) {
|
|
||||||
var cache = new LRU(10)
|
|
||||||
var d = cache.dump();
|
|
||||||
t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache")
|
|
||||||
cache.set("a", "A")
|
|
||||||
var d = cache.dump() // { a: { key: "a", value: "A", lu: 0 } }
|
|
||||||
t.ok(d.a)
|
|
||||||
t.equal(d.a.key, "a")
|
|
||||||
t.equal(d.a.value, "A")
|
|
||||||
t.equal(d.a.lu, 0)
|
|
||||||
|
|
||||||
cache.set("b", "B")
|
|
||||||
cache.get("b")
|
|
||||||
d = cache.dump()
|
|
||||||
t.ok(d.b)
|
|
||||||
t.equal(d.b.key, "b")
|
|
||||||
t.equal(d.b.value, "B")
|
|
||||||
t.equal(d.b.lu, 2)
|
|
||||||
|
|
||||||
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("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)
|
|
||||||
|
|
||||||
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("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()
|
|
||||||
})
|
|
|
@ -1,52 +0,0 @@
|
||||||
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.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()
|
|
||||||
})
|
|
|
@ -1,50 +0,0 @@
|
||||||
#!/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();
|
|
||||||
})
|
|
|
@ -1,27 +0,0 @@
|
||||||
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.
|
|
|
@ -1,53 +0,0 @@
|
||||||
# sigmund
|
|
||||||
|
|
||||||
Quick and dirty signatures for Objects.
|
|
||||||
|
|
||||||
This is like a much faster `deepEquals` comparison, which returns a
|
|
||||||
string key suitable for caches and the like.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
function doSomething (someObj) {
|
|
||||||
var key = sigmund(someObj, maxDepth) // max depth defaults to 10
|
|
||||||
var cached = cache.get(key)
|
|
||||||
if (cached) return cached)
|
|
||||||
|
|
||||||
var result = expensiveCalculation(someObj)
|
|
||||||
cache.set(key, result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The resulting key will be as unique and reproducible as calling
|
|
||||||
`JSON.stringify` or `util.inspect` on the object, but is much faster.
|
|
||||||
In order to achieve this speed, some differences are glossed over.
|
|
||||||
For example, the object `{0:'foo'}` will be treated identically to the
|
|
||||||
array `['foo']`.
|
|
||||||
|
|
||||||
Also, just as there is no way to summon the soul from the scribblings
|
|
||||||
of a cocain-addled psychoanalyst, there is no way to revive the object
|
|
||||||
from the signature string that sigmund gives you. In fact, it's
|
|
||||||
barely even readable.
|
|
||||||
|
|
||||||
As with `sys.inspect` and `JSON.stringify`, larger objects will
|
|
||||||
produce larger signature strings.
|
|
||||||
|
|
||||||
Because sigmund is a bit less strict than the more thorough
|
|
||||||
alternatives, the strings will be shorter, and also there is a
|
|
||||||
slightly higher chance for collisions. For example, these objects
|
|
||||||
have the same signature:
|
|
||||||
|
|
||||||
var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}
|
|
||||||
var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}
|
|
||||||
|
|
||||||
Like a good Freudian, sigmund is most effective when you already have
|
|
||||||
some understanding of what you're looking for. It can help you help
|
|
||||||
yourself, but you must be willing to do some work as well.
|
|
||||||
|
|
||||||
Cycles are handled, and cyclical objects are silently omitted (though
|
|
||||||
the key is included in the signature output.)
|
|
||||||
|
|
||||||
The second argument is the maximum depth, which defaults to 10,
|
|
||||||
because that is the maximum object traversal depth covered by most
|
|
||||||
insurance carriers.
|
|
|
@ -1,283 +0,0 @@
|
||||||
// different ways to id objects
|
|
||||||
// use a req/res pair, since it's crazy deep and cyclical
|
|
||||||
|
|
||||||
// sparseFE10 and sigmund are usually pretty close, which is to be expected,
|
|
||||||
// since they are essentially the same algorithm, except that sigmund handles
|
|
||||||
// regular expression objects properly.
|
|
||||||
|
|
||||||
|
|
||||||
var http = require('http')
|
|
||||||
var util = require('util')
|
|
||||||
var sigmund = require('./sigmund.js')
|
|
||||||
var sreq, sres, creq, cres, test
|
|
||||||
|
|
||||||
http.createServer(function (q, s) {
|
|
||||||
sreq = q
|
|
||||||
sres = s
|
|
||||||
sres.end('ok')
|
|
||||||
this.close(function () { setTimeout(function () {
|
|
||||||
start()
|
|
||||||
}, 200) })
|
|
||||||
}).listen(1337, function () {
|
|
||||||
creq = http.get({ port: 1337 })
|
|
||||||
creq.on('response', function (s) { cres = s })
|
|
||||||
})
|
|
||||||
|
|
||||||
function start () {
|
|
||||||
test = [sreq, sres, creq, cres]
|
|
||||||
// test = sreq
|
|
||||||
// sreq.sres = sres
|
|
||||||
// sreq.creq = creq
|
|
||||||
// sreq.cres = cres
|
|
||||||
|
|
||||||
for (var i in exports.compare) {
|
|
||||||
console.log(i)
|
|
||||||
var hash = exports.compare[i]()
|
|
||||||
console.log(hash)
|
|
||||||
console.log(hash.length)
|
|
||||||
console.log('')
|
|
||||||
}
|
|
||||||
|
|
||||||
require('bench').runMain()
|
|
||||||
}
|
|
||||||
|
|
||||||
function customWs (obj, md, d) {
|
|
||||||
d = d || 0
|
|
||||||
var to = typeof obj
|
|
||||||
if (to === 'undefined' || to === 'function' || to === null) return ''
|
|
||||||
if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '')
|
|
||||||
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
return obj.map(function (i, _, __) {
|
|
||||||
return customWs(i, md, d + 1)
|
|
||||||
}).reduce(function (a, b) { return a + b }, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
var keys = Object.keys(obj)
|
|
||||||
return keys.map(function (k, _, __) {
|
|
||||||
return k + ':' + customWs(obj[k], md, d + 1)
|
|
||||||
}).reduce(function (a, b) { return a + b }, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
function custom (obj, md, d) {
|
|
||||||
d = d || 0
|
|
||||||
var to = typeof obj
|
|
||||||
if (to === 'undefined' || to === 'function' || to === null) return ''
|
|
||||||
if (d > md || !obj || to !== 'object') return '' + obj
|
|
||||||
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
return obj.map(function (i, _, __) {
|
|
||||||
return custom(i, md, d + 1)
|
|
||||||
}).reduce(function (a, b) { return a + b }, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
var keys = Object.keys(obj)
|
|
||||||
return keys.map(function (k, _, __) {
|
|
||||||
return k + ':' + custom(obj[k], md, d + 1)
|
|
||||||
}).reduce(function (a, b) { return a + b }, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
function sparseFE2 (obj, maxDepth) {
|
|
||||||
var seen = []
|
|
||||||
var soFar = ''
|
|
||||||
function ch (v, depth) {
|
|
||||||
if (depth > maxDepth) return
|
|
||||||
if (typeof v === 'function' || typeof v === 'undefined') return
|
|
||||||
if (typeof v !== 'object' || !v) {
|
|
||||||
soFar += v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (seen.indexOf(v) !== -1 || depth === maxDepth) return
|
|
||||||
seen.push(v)
|
|
||||||
soFar += '{'
|
|
||||||
Object.keys(v).forEach(function (k, _, __) {
|
|
||||||
// pseudo-private values. skip those.
|
|
||||||
if (k.charAt(0) === '_') return
|
|
||||||
var to = typeof v[k]
|
|
||||||
if (to === 'function' || to === 'undefined') return
|
|
||||||
soFar += k + ':'
|
|
||||||
ch(v[k], depth + 1)
|
|
||||||
})
|
|
||||||
soFar += '}'
|
|
||||||
}
|
|
||||||
ch(obj, 0)
|
|
||||||
return soFar
|
|
||||||
}
|
|
||||||
|
|
||||||
function sparseFE (obj, maxDepth) {
|
|
||||||
var seen = []
|
|
||||||
var soFar = ''
|
|
||||||
function ch (v, depth) {
|
|
||||||
if (depth > maxDepth) return
|
|
||||||
if (typeof v === 'function' || typeof v === 'undefined') return
|
|
||||||
if (typeof v !== 'object' || !v) {
|
|
||||||
soFar += v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (seen.indexOf(v) !== -1 || depth === maxDepth) return
|
|
||||||
seen.push(v)
|
|
||||||
soFar += '{'
|
|
||||||
Object.keys(v).forEach(function (k, _, __) {
|
|
||||||
// pseudo-private values. skip those.
|
|
||||||
if (k.charAt(0) === '_') return
|
|
||||||
var to = typeof v[k]
|
|
||||||
if (to === 'function' || to === 'undefined') return
|
|
||||||
soFar += k
|
|
||||||
ch(v[k], depth + 1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ch(obj, 0)
|
|
||||||
return soFar
|
|
||||||
}
|
|
||||||
|
|
||||||
function sparse (obj, maxDepth) {
|
|
||||||
var seen = []
|
|
||||||
var soFar = ''
|
|
||||||
function ch (v, depth) {
|
|
||||||
if (depth > maxDepth) return
|
|
||||||
if (typeof v === 'function' || typeof v === 'undefined') return
|
|
||||||
if (typeof v !== 'object' || !v) {
|
|
||||||
soFar += v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (seen.indexOf(v) !== -1 || depth === maxDepth) return
|
|
||||||
seen.push(v)
|
|
||||||
soFar += '{'
|
|
||||||
for (var k in v) {
|
|
||||||
// pseudo-private values. skip those.
|
|
||||||
if (k.charAt(0) === '_') continue
|
|
||||||
var to = typeof v[k]
|
|
||||||
if (to === 'function' || to === 'undefined') continue
|
|
||||||
soFar += k
|
|
||||||
ch(v[k], depth + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ch(obj, 0)
|
|
||||||
return soFar
|
|
||||||
}
|
|
||||||
|
|
||||||
function noCommas (obj, maxDepth) {
|
|
||||||
var seen = []
|
|
||||||
var soFar = ''
|
|
||||||
function ch (v, depth) {
|
|
||||||
if (depth > maxDepth) return
|
|
||||||
if (typeof v === 'function' || typeof v === 'undefined') return
|
|
||||||
if (typeof v !== 'object' || !v) {
|
|
||||||
soFar += v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (seen.indexOf(v) !== -1 || depth === maxDepth) return
|
|
||||||
seen.push(v)
|
|
||||||
soFar += '{'
|
|
||||||
for (var k in v) {
|
|
||||||
// pseudo-private values. skip those.
|
|
||||||
if (k.charAt(0) === '_') continue
|
|
||||||
var to = typeof v[k]
|
|
||||||
if (to === 'function' || to === 'undefined') continue
|
|
||||||
soFar += k + ':'
|
|
||||||
ch(v[k], depth + 1)
|
|
||||||
}
|
|
||||||
soFar += '}'
|
|
||||||
}
|
|
||||||
ch(obj, 0)
|
|
||||||
return soFar
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function flatten (obj, maxDepth) {
|
|
||||||
var seen = []
|
|
||||||
var soFar = ''
|
|
||||||
function ch (v, depth) {
|
|
||||||
if (depth > maxDepth) return
|
|
||||||
if (typeof v === 'function' || typeof v === 'undefined') return
|
|
||||||
if (typeof v !== 'object' || !v) {
|
|
||||||
soFar += v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (seen.indexOf(v) !== -1 || depth === maxDepth) return
|
|
||||||
seen.push(v)
|
|
||||||
soFar += '{'
|
|
||||||
for (var k in v) {
|
|
||||||
// pseudo-private values. skip those.
|
|
||||||
if (k.charAt(0) === '_') continue
|
|
||||||
var to = typeof v[k]
|
|
||||||
if (to === 'function' || to === 'undefined') continue
|
|
||||||
soFar += k + ':'
|
|
||||||
ch(v[k], depth + 1)
|
|
||||||
soFar += ','
|
|
||||||
}
|
|
||||||
soFar += '}'
|
|
||||||
}
|
|
||||||
ch(obj, 0)
|
|
||||||
return soFar
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.compare =
|
|
||||||
{
|
|
||||||
// 'custom 2': function () {
|
|
||||||
// return custom(test, 2, 0)
|
|
||||||
// },
|
|
||||||
// 'customWs 2': function () {
|
|
||||||
// return customWs(test, 2, 0)
|
|
||||||
// },
|
|
||||||
'JSON.stringify (guarded)': function () {
|
|
||||||
var seen = []
|
|
||||||
return JSON.stringify(test, function (k, v) {
|
|
||||||
if (typeof v !== 'object' || !v) return v
|
|
||||||
if (seen.indexOf(v) !== -1) return undefined
|
|
||||||
seen.push(v)
|
|
||||||
return v
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
'flatten 10': function () {
|
|
||||||
return flatten(test, 10)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 'flattenFE 10': function () {
|
|
||||||
// return flattenFE(test, 10)
|
|
||||||
// },
|
|
||||||
|
|
||||||
'noCommas 10': function () {
|
|
||||||
return noCommas(test, 10)
|
|
||||||
},
|
|
||||||
|
|
||||||
'sparse 10': function () {
|
|
||||||
return sparse(test, 10)
|
|
||||||
},
|
|
||||||
|
|
||||||
'sparseFE 10': function () {
|
|
||||||
return sparseFE(test, 10)
|
|
||||||
},
|
|
||||||
|
|
||||||
'sparseFE2 10': function () {
|
|
||||||
return sparseFE2(test, 10)
|
|
||||||
},
|
|
||||||
|
|
||||||
sigmund: function() {
|
|
||||||
return sigmund(test, 10)
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// 'util.inspect 1': function () {
|
|
||||||
// return util.inspect(test, false, 1, false)
|
|
||||||
// },
|
|
||||||
// 'util.inspect undefined': function () {
|
|
||||||
// util.inspect(test)
|
|
||||||
// },
|
|
||||||
// 'util.inspect 2': function () {
|
|
||||||
// util.inspect(test, false, 2, false)
|
|
||||||
// },
|
|
||||||
// 'util.inspect 3': function () {
|
|
||||||
// util.inspect(test, false, 3, false)
|
|
||||||
// },
|
|
||||||
// 'util.inspect 4': function () {
|
|
||||||
// util.inspect(test, false, 4, false)
|
|
||||||
// },
|
|
||||||
// 'util.inspect Infinity': function () {
|
|
||||||
// util.inspect(test, false, Infinity, false)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** results
|
|
||||||
**/
|
|
|
@ -1,58 +0,0 @@
|
||||||
{
|
|
||||||
"name": "sigmund",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Quick and dirty signatures for Objects.",
|
|
||||||
"main": "sigmund.js",
|
|
||||||
"directories": {
|
|
||||||
"test": "test"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "~0.3.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/*.js",
|
|
||||||
"bench": "node bench.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/sigmund"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"object",
|
|
||||||
"signature",
|
|
||||||
"key",
|
|
||||||
"data",
|
|
||||||
"psychoanalysis"
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me/"
|
|
||||||
},
|
|
||||||
"license": "BSD",
|
|
||||||
"readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n var cached = cache.get(key)\n if (cached) return cached)\n\n var result = expensiveCalculation(someObj)\n cache.set(key, result)\n return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you. In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions. For example, these objects\nhave the same signature:\n\n var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for. It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n",
|
|
||||||
"_id": "sigmund@1.0.0",
|
|
||||||
"dist": {
|
|
||||||
"shasum": "66a2b3a749ae8b5fb89efd4fcc01dc94fbe02296",
|
|
||||||
"tarball": "http://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz"
|
|
||||||
},
|
|
||||||
"_npmVersion": "1.1.48",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"_shasum": "66a2b3a749ae8b5fb89efd4fcc01dc94fbe02296",
|
|
||||||
"_from": "sigmund@~1.0.0",
|
|
||||||
"_resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/sigmund/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/sigmund"
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
module.exports = sigmund
|
|
||||||
function sigmund (subject, maxSessions) {
|
|
||||||
maxSessions = maxSessions || 10;
|
|
||||||
var notes = [];
|
|
||||||
var analysis = '';
|
|
||||||
var RE = RegExp;
|
|
||||||
|
|
||||||
function psychoAnalyze (subject, session) {
|
|
||||||
if (session > maxSessions) return;
|
|
||||||
|
|
||||||
if (typeof subject === 'function' ||
|
|
||||||
typeof subject === 'undefined') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof subject !== 'object' || !subject ||
|
|
||||||
(subject instanceof RE)) {
|
|
||||||
analysis += subject;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notes.indexOf(subject) !== -1 || session === maxSessions) return;
|
|
||||||
|
|
||||||
notes.push(subject);
|
|
||||||
analysis += '{';
|
|
||||||
Object.keys(subject).forEach(function (issue, _, __) {
|
|
||||||
// pseudo-private values. skip those.
|
|
||||||
if (issue.charAt(0) === '_') return;
|
|
||||||
var to = typeof subject[issue];
|
|
||||||
if (to === 'function' || to === 'undefined') return;
|
|
||||||
analysis += issue;
|
|
||||||
psychoAnalyze(subject[issue], session + 1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
psychoAnalyze(subject, 0);
|
|
||||||
return analysis;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vim: set softtabstop=4 shiftwidth=4:
|
|
|
@ -1,24 +0,0 @@
|
||||||
var test = require('tap').test
|
|
||||||
var sigmund = require('../sigmund.js')
|
|
||||||
|
|
||||||
|
|
||||||
// occasionally there are duplicates
|
|
||||||
// that's an acceptable edge-case. JSON.stringify and util.inspect
|
|
||||||
// have some collision potential as well, though less, and collision
|
|
||||||
// detection is expensive.
|
|
||||||
var hash = '{abc/def/g{0h1i2{jkl'
|
|
||||||
var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}
|
|
||||||
var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}
|
|
||||||
|
|
||||||
var obj3 = JSON.parse(JSON.stringify(obj1))
|
|
||||||
obj3.c = /def/
|
|
||||||
obj3.g[2].cycle = obj3
|
|
||||||
var cycleHash = '{abc/def/g{0h1i2{jklcycle'
|
|
||||||
|
|
||||||
test('basic', function (t) {
|
|
||||||
t.equal(sigmund(obj1), hash)
|
|
||||||
t.equal(sigmund(obj2), hash)
|
|
||||||
t.equal(sigmund(obj3), cycleHash)
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
{
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me"
|
|
||||||
},
|
|
||||||
"name": "minimatch",
|
|
||||||
"description": "a glob matcher in javascript",
|
|
||||||
"version": "0.3.0",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/minimatch.git"
|
|
||||||
},
|
|
||||||
"main": "minimatch.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/*.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"lru-cache": "2",
|
|
||||||
"sigmund": "~1.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": ""
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "http://github.com/isaacs/minimatch/raw/master/LICENSE"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/minimatch/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/minimatch",
|
|
||||||
"_id": "minimatch@0.3.0",
|
|
||||||
"_shasum": "275d8edaac4f1bb3326472089e7949c8394699dd",
|
|
||||||
"_from": "minimatch@0.3",
|
|
||||||
"_npmVersion": "1.4.10",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dist": {
|
|
||||||
"shasum": "275d8edaac4f1bb3326472089e7949c8394699dd",
|
|
||||||
"tarball": "http://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz"
|
|
||||||
},
|
|
||||||
"directories": {},
|
|
||||||
"_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
|
@ -1,399 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
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()
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
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()
|
|
||||||
})
|
|
|
@ -1,274 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
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()
|
|
||||||
})
|
|
|
@ -1,58 +0,0 @@
|
||||||
{
|
|
||||||
"author": {
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me/"
|
|
||||||
},
|
|
||||||
"name": "glob",
|
|
||||||
"description": "a little globber",
|
|
||||||
"version": "3.2.11",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/node-glob.git"
|
|
||||||
},
|
|
||||||
"main": "glob.js",
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"inherits": "2",
|
|
||||||
"minimatch": "0.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "~0.4.0",
|
|
||||||
"mkdirp": "0",
|
|
||||||
"rimraf": "1"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/*.js",
|
|
||||||
"test-regen": "TEST_REGEN=1 node test/00-setup.js"
|
|
||||||
},
|
|
||||||
"license": "BSD",
|
|
||||||
"gitHead": "73f57e99510582b2024b762305970ebcf9b70aa2",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/isaacs/node-glob/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/isaacs/node-glob",
|
|
||||||
"_id": "glob@3.2.11",
|
|
||||||
"_shasum": "4a973f635b9190f715d10987d5c00fd2815ebe3d",
|
|
||||||
"_from": "glob@~ 3.2.1",
|
|
||||||
"_npmVersion": "1.4.10",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "isaacs",
|
|
||||||
"email": "i@izs.me"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dist": {
|
|
||||||
"shasum": "4a973f635b9190f715d10987d5c00fd2815ebe3d",
|
|
||||||
"tarball": "http://registry.npmjs.org/glob/-/glob-3.2.11.tgz"
|
|
||||||
},
|
|
||||||
"directories": {},
|
|
||||||
"_resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
|
@ -1,176 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
// 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, '/')
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,351 +0,0 @@
|
||||||
{
|
|
||||||
"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/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/globstar-match.js",
|
|
||||||
"./test/mark.js",
|
|
||||||
"./test/new-glob-optional-options.js",
|
|
||||||
"./test/nocase-nomagic.js",
|
|
||||||
"./test/pause-resume.js",
|
|
||||||
"./test/readme-issue.js",
|
|
||||||
"./test/root-nomount.js",
|
|
||||||
"./test/root.js",
|
|
||||||
"./test/stat.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"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
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()
|
|
||||||
})
|
|
|
@ -1,19 +0,0 @@
|
||||||
var Glob = require("../glob.js").Glob
|
|
||||||
var test = require('tap').test
|
|
||||||
|
|
||||||
test('globstar should not have dupe matches', function(t) {
|
|
||||||
var pattern = 'a/**/[gh]'
|
|
||||||
var g = new Glob(pattern, { cwd: __dirname })
|
|
||||||
var matches = []
|
|
||||||
g.on('match', function(m) {
|
|
||||||
console.error('match %j', m)
|
|
||||||
matches.push(m)
|
|
||||||
})
|
|
||||||
g.on('end', function(set) {
|
|
||||||
console.error('set', set)
|
|
||||||
matches = matches.sort()
|
|
||||||
set = set.sort()
|
|
||||||
t.same(matches, set, 'should have same set of matches')
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,118 +0,0 @@
|
||||||
var test = require("tap").test
|
|
||||||
var glob = require('../')
|
|
||||||
process.chdir(__dirname)
|
|
||||||
|
|
||||||
// expose timing issues
|
|
||||||
var lag = 5
|
|
||||||
glob.Glob.prototype._stat = function(o) { return function(f, cb) {
|
|
||||||
var args = arguments
|
|
||||||
setTimeout(function() {
|
|
||||||
o.call(this, f, cb)
|
|
||||||
}.bind(this), lag += 5)
|
|
||||||
}}(glob.Glob.prototype._stat)
|
|
||||||
|
|
||||||
|
|
||||||
test("mark, with **", function (t) {
|
|
||||||
glob("a/*b*/**", {mark: true}, function (er, results) {
|
|
||||||
if (er)
|
|
||||||
throw er
|
|
||||||
var expect =
|
|
||||||
[ 'a/abcdef/',
|
|
||||||
'a/abcdef/g/',
|
|
||||||
'a/abcdef/g/h',
|
|
||||||
'a/abcfed/',
|
|
||||||
'a/abcfed/g/',
|
|
||||||
'a/abcfed/g/h',
|
|
||||||
'a/b/',
|
|
||||||
'a/b/c/',
|
|
||||||
'a/b/c/d',
|
|
||||||
'a/bc/',
|
|
||||||
'a/bc/e/',
|
|
||||||
'a/bc/e/f',
|
|
||||||
'a/cb/',
|
|
||||||
'a/cb/e/',
|
|
||||||
'a/cb/e/f' ]
|
|
||||||
|
|
||||||
t.same(results, expect)
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
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()
|
|
||||||
}).on('match', function(m) {
|
|
||||||
t.similar(m, /\/$/)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
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()
|
|
||||||
}).on('match', function(m) {
|
|
||||||
t.similar(m, /[^\/]$/)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
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()
|
|
||||||
}).on('match', function(m) {
|
|
||||||
t.similar(m, /\/$/)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
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()
|
|
||||||
}).on('match', function(m) {
|
|
||||||
t.similar(m, /\/$/)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,10 +0,0 @@
|
||||||
var Glob = require('../glob.js').Glob;
|
|
||||||
var test = require('tap').test;
|
|
||||||
|
|
||||||
test('new glob, with cb, and no options', function (t) {
|
|
||||||
new Glob(__filename, function(er, results) {
|
|
||||||
if (er) throw er;
|
|
||||||
t.same(results, [__filename]);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,113 +0,0 @@
|
||||||
var fs = require('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)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,73 +0,0 @@
|
||||||
// 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()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
var test = require("tap").test
|
|
||||||
var glob = require("../")
|
|
||||||
|
|
||||||
var mkdirp = require("mkdirp")
|
|
||||||
var fs = require("fs")
|
|
||||||
var rimraf = require("rimraf")
|
|
||||||
var dir = __dirname + "/package"
|
|
||||||
|
|
||||||
test("setup", function (t) {
|
|
||||||
mkdirp.sync(dir)
|
|
||||||
fs.writeFileSync(dir + "/package.json", "{}", "ascii")
|
|
||||||
fs.writeFileSync(dir + "/README", "x", "ascii")
|
|
||||||
t.pass("setup done")
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("glob", function (t) {
|
|
||||||
var opt = {
|
|
||||||
cwd: dir,
|
|
||||||
nocase: true,
|
|
||||||
mark: true
|
|
||||||
}
|
|
||||||
|
|
||||||
glob("README?(.*)", opt, function (er, files) {
|
|
||||||
if (er)
|
|
||||||
throw er
|
|
||||||
t.same(files, ["README"])
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test("cleanup", function (t) {
|
|
||||||
rimraf.sync(dir)
|
|
||||||
t.pass("clean")
|
|
||||||
t.end()
|
|
||||||
})
|
|
|
@ -1,39 +0,0 @@
|
||||||
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()
|
|
||||||
})
|
|
|
@ -1,46 +0,0 @@
|
||||||
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()
|
|
||||||
})
|
|
|
@ -1,32 +0,0 @@
|
||||||
var glob = require('../')
|
|
||||||
var test = require('tap').test
|
|
||||||
var path = require('path')
|
|
||||||
|
|
||||||
test('stat all the things', function(t) {
|
|
||||||
var g = new glob.Glob('a/*abc*/**', { stat: true, cwd: __dirname })
|
|
||||||
var matches = []
|
|
||||||
g.on('match', function(m) {
|
|
||||||
matches.push(m)
|
|
||||||
})
|
|
||||||
var stats = []
|
|
||||||
g.on('stat', function(m) {
|
|
||||||
stats.push(m)
|
|
||||||
})
|
|
||||||
g.on('end', function(eof) {
|
|
||||||
stats = stats.sort()
|
|
||||||
matches = matches.sort()
|
|
||||||
eof = eof.sort()
|
|
||||||
t.same(stats, matches)
|
|
||||||
t.same(eof, matches)
|
|
||||||
var cache = Object.keys(this.statCache)
|
|
||||||
t.same(cache.map(function (f) {
|
|
||||||
return path.relative(__dirname, f)
|
|
||||||
}).sort(), matches)
|
|
||||||
|
|
||||||
cache.forEach(function(c) {
|
|
||||||
t.equal(typeof this.statCache[c], 'object')
|
|
||||||
}, this)
|
|
||||||
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,11 +0,0 @@
|
||||||
// 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()
|
|
||||||
})
|
|
||||||
})
|
|
73
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/package.json
generated
vendored
73
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/package.json
generated
vendored
|
@ -1,73 +0,0 @@
|
||||||
{
|
|
||||||
"name": "cli",
|
|
||||||
"description": "A tool for rapidly building command line apps",
|
|
||||||
"version": "0.6.6",
|
|
||||||
"homepage": "http://github.com/chriso/cli",
|
|
||||||
"keywords": [
|
|
||||||
"cli",
|
|
||||||
"command line",
|
|
||||||
"opts",
|
|
||||||
"parseopt",
|
|
||||||
"opt",
|
|
||||||
"args",
|
|
||||||
"console",
|
|
||||||
"argsparse",
|
|
||||||
"optparse",
|
|
||||||
"daemon",
|
|
||||||
"autocomplete",
|
|
||||||
"command",
|
|
||||||
"autocompletion"
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "Chris O'Hara",
|
|
||||||
"email": "cohara87@gmail.com"
|
|
||||||
},
|
|
||||||
"main": "cli.js",
|
|
||||||
"bugs": {
|
|
||||||
"url": "http://github.com/chriso/cli/issues"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/chriso/cli.git"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"glob": "~ 3.2.1",
|
|
||||||
"exit": "0.1.2"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Douglas Meyer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.2.5"
|
|
||||||
},
|
|
||||||
"licenses": [
|
|
||||||
{
|
|
||||||
"type": "MIT"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"gitHead": "088e01c2df81b0850ae4ae2daa7827fb6dcf0502",
|
|
||||||
"_id": "cli@0.6.6",
|
|
||||||
"scripts": {},
|
|
||||||
"_shasum": "02ad44a380abf27adac5e6f0cdd7b043d74c53e3",
|
|
||||||
"_from": "cli@0.6.x",
|
|
||||||
"_npmVersion": "2.7.3",
|
|
||||||
"_nodeVersion": "0.12.1",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "cohara87",
|
|
||||||
"email": "cohara87@gmail.com"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "cohara87",
|
|
||||||
"email": "cohara87@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dist": {
|
|
||||||
"shasum": "02ad44a380abf27adac5e6f0cdd7b043d74c53e3",
|
|
||||||
"tarball": "http://registry.npmjs.org/cli/-/cli-0.6.6.tgz"
|
|
||||||
},
|
|
||||||
"directories": {},
|
|
||||||
"_resolved": "https://registry.npmjs.org/cli/-/cli-0.6.6.tgz"
|
|
||||||
}
|
|
11
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/progress.js
generated
vendored
11
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/progress.js
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('./');
|
|
||||||
|
|
||||||
var i = 0, interval = setInterval(function () {
|
|
||||||
cli.progress(++i / 100);
|
|
||||||
if (i === 100) {
|
|
||||||
clearInterval(interval);
|
|
||||||
cli.ok('Finished!');
|
|
||||||
}
|
|
||||||
}, 50);
|
|
9
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/spinner.js
generated
vendored
9
javascript/base/exercices/linting/node_modules/jshint/node_modules/cli/spinner.js
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var cli = require('./');
|
|
||||||
|
|
||||||
cli.spinner('Working..');
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
cli.spinner('Working.. done!', true); //End the spinner
|
|
||||||
}, 3000);
|
|
|
@ -1,14 +0,0 @@
|
||||||
.DS_Store
|
|
||||||
.monitor
|
|
||||||
.*.swp
|
|
||||||
.nodemonignore
|
|
||||||
releases
|
|
||||||
*.log
|
|
||||||
*.err
|
|
||||||
fleet.json
|
|
||||||
public/browserify
|
|
||||||
bin/*.json
|
|
||||||
.bin
|
|
||||||
build
|
|
||||||
compile
|
|
||||||
.lock-wscript
|
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"launchers": {
|
|
||||||
"node": {
|
|
||||||
"command": "npm test"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src_files": [
|
|
||||||
"./**/*.js"
|
|
||||||
],
|
|
||||||
"before_tests": "npm run build",
|
|
||||||
"on_exit": "rm test/static/bundle.js",
|
|
||||||
"test_page": "test/static/index.html",
|
|
||||||
"launch_in_dev": ["node", "phantomjs"]
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.8
|
|
||||||
- 0.9
|
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2012 Raynos.
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,33 +0,0 @@
|
||||||
# console-browserify
|
|
||||||
|
|
||||||
[![build status][1]][2]
|
|
||||||
|
|
||||||
[![browser support][3]][4]
|
|
||||||
|
|
||||||
|
|
||||||
Emulate console for all the browsers
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
var console = require("console-browserify")
|
|
||||||
|
|
||||||
console.log("hello world!")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
`npm install console-browserify`
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
- Raynos
|
|
||||||
|
|
||||||
## MIT Licenced
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[1]: https://secure.travis-ci.org/Raynos/console-browserify.png
|
|
||||||
[2]: http://travis-ci.org/Raynos/console-browserify
|
|
||||||
[3]: http://ci.testling.com/Raynos/console-browserify.png
|
|
||||||
[4]: http://ci.testling.com/Raynos/console-browserify
|
|
|
@ -1,86 +0,0 @@
|
||||||
/*global window, global*/
|
|
||||||
var util = require("util")
|
|
||||||
var assert = require("assert")
|
|
||||||
var now = require("date-now")
|
|
||||||
|
|
||||||
var slice = Array.prototype.slice
|
|
||||||
var console
|
|
||||||
var times = {}
|
|
||||||
|
|
||||||
if (typeof global !== "undefined" && global.console) {
|
|
||||||
console = global.console
|
|
||||||
} else if (typeof window !== "undefined" && window.console) {
|
|
||||||
console = window.console
|
|
||||||
} else {
|
|
||||||
console = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
var functions = [
|
|
||||||
[log, "log"],
|
|
||||||
[info, "info"],
|
|
||||||
[warn, "warn"],
|
|
||||||
[error, "error"],
|
|
||||||
[time, "time"],
|
|
||||||
[timeEnd, "timeEnd"],
|
|
||||||
[trace, "trace"],
|
|
||||||
[dir, "dir"],
|
|
||||||
[consoleAssert, "assert"]
|
|
||||||
]
|
|
||||||
|
|
||||||
for (var i = 0; i < functions.length; i++) {
|
|
||||||
var tuple = functions[i]
|
|
||||||
var f = tuple[0]
|
|
||||||
var name = tuple[1]
|
|
||||||
|
|
||||||
if (!console[name]) {
|
|
||||||
console[name] = f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = console
|
|
||||||
|
|
||||||
function log() {}
|
|
||||||
|
|
||||||
function info() {
|
|
||||||
console.log.apply(console, arguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
function warn() {
|
|
||||||
console.log.apply(console, arguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
function error() {
|
|
||||||
console.warn.apply(console, arguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
function time(label) {
|
|
||||||
times[label] = now()
|
|
||||||
}
|
|
||||||
|
|
||||||
function timeEnd(label) {
|
|
||||||
var time = times[label]
|
|
||||||
if (!time) {
|
|
||||||
throw new Error("No such label: " + label)
|
|
||||||
}
|
|
||||||
|
|
||||||
var duration = now() - time
|
|
||||||
console.log(label + ": " + duration + "ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
function trace() {
|
|
||||||
var err = new Error()
|
|
||||||
err.name = "Trace"
|
|
||||||
err.message = util.format.apply(null, arguments)
|
|
||||||
console.error(err.stack)
|
|
||||||
}
|
|
||||||
|
|
||||||
function dir(object) {
|
|
||||||
console.log(util.inspect(object) + "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
function consoleAssert(expression) {
|
|
||||||
if (!expression) {
|
|
||||||
var arr = slice.call(arguments, 1)
|
|
||||||
assert.ok(false, util.format.apply(null, arr))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
.DS_Store
|
|
||||||
.monitor
|
|
||||||
.*.swp
|
|
||||||
.nodemonignore
|
|
||||||
releases
|
|
||||||
*.log
|
|
||||||
*.err
|
|
||||||
fleet.json
|
|
||||||
public/browserify
|
|
||||||
bin/*.json
|
|
||||||
.bin
|
|
||||||
build
|
|
||||||
compile
|
|
||||||
.lock-wscript
|
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"launchers": {
|
|
||||||
"node": {
|
|
||||||
"command": "npm test"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src_files": [
|
|
||||||
"./**/*.js"
|
|
||||||
],
|
|
||||||
"before_tests": "npm run build",
|
|
||||||
"on_exit": "rm test/static/bundle.js",
|
|
||||||
"test_page": "test/static/index.html",
|
|
||||||
"launch_in_dev": ["node", "phantomjs"]
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.8
|
|
||||||
- 0.9
|
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2012 Colingo.
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,45 +0,0 @@
|
||||||
# date-now
|
|
||||||
|
|
||||||
[![build status][1]][2]
|
|
||||||
|
|
||||||
[![browser support][3]][4]
|
|
||||||
|
|
||||||
A requirable version of Date.now()
|
|
||||||
|
|
||||||
Use-case is to be able to mock out Date.now() using require interception.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
var now = require("date-now")
|
|
||||||
|
|
||||||
var ts = now()
|
|
||||||
var ts2 = Date.now()
|
|
||||||
assert.equal(ts, ts2)
|
|
||||||
```
|
|
||||||
|
|
||||||
## example of seed
|
|
||||||
|
|
||||||
```
|
|
||||||
var now = require("date-now/seed")(timeStampFromServer)
|
|
||||||
|
|
||||||
// ts is in "sync" with the seed value from the server
|
|
||||||
// useful if your users have their local time being a few minutes
|
|
||||||
// out of your server time.
|
|
||||||
var ts = now()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
`npm install date-now`
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
- Raynos
|
|
||||||
|
|
||||||
## MIT Licenced
|
|
||||||
|
|
||||||
[1]: https://secure.travis-ci.org/Colingo/date-now.png
|
|
||||||
[2]: http://travis-ci.org/Colingo/date-now
|
|
||||||
[3]: http://ci.testling.com/Colingo/date-now.png
|
|
||||||
[4]: http://ci.testling.com/Colingo/date-now
|
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = now
|
|
||||||
|
|
||||||
function now() {
|
|
||||||
return new Date().getTime()
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
{
|
|
||||||
"name": "date-now",
|
|
||||||
"version": "0.1.4",
|
|
||||||
"description": "A requirable version of Date.now()",
|
|
||||||
"keywords": [],
|
|
||||||
"author": {
|
|
||||||
"name": "Raynos",
|
|
||||||
"email": "raynos2@gmail.com"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/Colingo/date-now.git"
|
|
||||||
},
|
|
||||||
"main": "index",
|
|
||||||
"homepage": "https://github.com/Colingo/date-now",
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Artem Shoobovych"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/Colingo/date-now/issues",
|
|
||||||
"email": "raynos2@gmail.com"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
|
||||||
"tape": "~0.2.2",
|
|
||||||
"browserify": "https://github.com/raynos/node-browserify/tarball/master",
|
|
||||||
"testem": "~0.2.52"
|
|
||||||
},
|
|
||||||
"licenses": [
|
|
||||||
{
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "http://github.com/Colingo/date-now/raw/master/LICENSE"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"test": "node ./test",
|
|
||||||
"build": "browserify test/index.js -o test/static/bundle.js",
|
|
||||||
"testem": "testem"
|
|
||||||
},
|
|
||||||
"testling": {
|
|
||||||
"files": "test/*.js",
|
|
||||||
"browsers": {
|
|
||||||
"ie": [
|
|
||||||
"8",
|
|
||||||
"9",
|
|
||||||
"10"
|
|
||||||
],
|
|
||||||
"firefox": [
|
|
||||||
"16",
|
|
||||||
"17",
|
|
||||||
"nightly"
|
|
||||||
],
|
|
||||||
"chrome": [
|
|
||||||
"22",
|
|
||||||
"23",
|
|
||||||
"canary"
|
|
||||||
],
|
|
||||||
"opera": [
|
|
||||||
"12",
|
|
||||||
"next"
|
|
||||||
],
|
|
||||||
"safari": [
|
|
||||||
"5.1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"_id": "date-now@0.1.4",
|
|
||||||
"dist": {
|
|
||||||
"shasum": "eaf439fd4d4848ad74e5cc7dbef200672b9e345b",
|
|
||||||
"tarball": "http://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz"
|
|
||||||
},
|
|
||||||
"_from": "date-now@^0.1.4",
|
|
||||||
"_npmVersion": "1.2.3",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "raynos",
|
|
||||||
"email": "raynos2@gmail.com"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "raynos",
|
|
||||||
"email": "raynos2@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directories": {},
|
|
||||||
"_shasum": "eaf439fd4d4848ad74e5cc7dbef200672b9e345b",
|
|
||||||
"_resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
|
|
||||||
"readme": "ERROR: No README data found!"
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
var now = require("./index")
|
|
||||||
|
|
||||||
module.exports = seeded
|
|
||||||
|
|
||||||
/* Returns a Date.now() like function that's in sync with
|
|
||||||
the seed value
|
|
||||||
*/
|
|
||||||
function seeded(seed) {
|
|
||||||
var current = now()
|
|
||||||
|
|
||||||
return time
|
|
||||||
|
|
||||||
function time() {
|
|
||||||
return seed + (now() - current)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
var test = require("tape")
|
|
||||||
var setTimeout = require("timers").setTimeout
|
|
||||||
|
|
||||||
var now = require("../index")
|
|
||||||
var seeded = require("../seed")
|
|
||||||
|
|
||||||
test("date", function (assert) {
|
|
||||||
var ts = now()
|
|
||||||
var ts2 = Date.now()
|
|
||||||
assert.equal(ts, ts2)
|
|
||||||
assert.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("seeded", function (assert) {
|
|
||||||
var time = seeded(40)
|
|
||||||
var ts = time()
|
|
||||||
|
|
||||||
within(assert, time(), 40, 5)
|
|
||||||
setTimeout(function () {
|
|
||||||
within(assert, time(), 90, 10)
|
|
||||||
assert.end()
|
|
||||||
}, 50)
|
|
||||||
})
|
|
||||||
|
|
||||||
function within(assert, a, b, offset) {
|
|
||||||
assert.ok(a + offset > b)
|
|
||||||
assert.ok(a - offset < b)
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue