Patrick Pfeiffer <patrick@buzzle.at>
Paul Miller <paul@paulmillr.com>
seebees <seebees@gmail.com>
+Carl Lange <carl@flax.ie>
+Jan Lehnardt <jan@apache.org>
## SYNOPSIS
var npm = require("npm")
- npm.load(configObject, function (er, npm) {
+ npm.load([configObject,] function (er, npm) {
// use the npm object, now that it's loaded.
npm.config.set(key, val)
To find documentation of the command line
client, see `npm(1)`.
-Prior to using npm's commands,
-`npm.load()` must be called with an object hash of
-top-level configs. In the npm command line client,
-this set of configs is parsed from the command line options. Additional
-configuration params are loaded from two configuration files. See
-`npm-config(1)` for more information.
+Prior to using npm's commands, `npm.load()` must be called.
+If you provide `configObject` as an object hash of top-level
+configs, they override the values stored in the various config
+locations. In the npm command line client, this set of configs
+is parsed from the command line options. Additional configuration
+params are loaded from two configuration files. See `npm-config(1)`
+for more information.
After that, each of the functions are accessible in the
commands object: `npm.commands.<cmd>`. See `npm-index(1)` for a list of
Force npm to always require authentication when accessing the registry,
even for `GET` requests.
+### bin-links
+
+* Default: `true`
+* Type: Boolean
+
+Tells npm to create symlinks (or `.cmd` shims on Windows) for package
+executables.
+
+Set to false to have it not do this. This can be used to work around
+the fact that some file systems don't support symlinks, even on
+ostensibly Unix systems.
+
### browser
* Default: OS X: `"open"`, others: `"google-chrome"`
### cache-min
-* Default: 0
+* Default: 10
* Type: Number
The minimum time (in seconds) to keep items in the registry cache before
`prefix` folder instead of the current working directory. See
`npm-folders(1)` for more on the differences in behavior.
-* packages are installed into the `prefix/node_modules` folder, instead of the
+* packages are installed into the `{prefix}/lib/node_modules` folder, instead of the
current working directory.
-* bin files are linked to `prefix/bin`
-* man pages are linked to `prefix/share/man`
+* bin files are linked to `{prefix}/bin`
+* man pages are linked to `{prefix}/share/man`
### globalconfig
### user-agent
-* Default: npm/{npm.version} node/{process.version}
+* Default: node/{process.version} {process.platform} {process.arch}
* Type: String
Sets a User-Agent to the request header
### prefix
-* Default: node's process.installPrefix
+* Default: see npm-folders(1)
* Type: path
The location to install global items. If set on the command line, then
--- /dev/null
+npm-folders(1) -- Folder Structures Used by npm
+===============================================
+
+## DESCRIPTION
+
+npm puts various things on your computer. That's its job.
+
+This document will tell you what it puts where.
+
+### tl;dr
+
+* Local install (default): puts stuff in `./node_modules` of the current
+ package root.
+* Global install (with `-g`): puts stuff in /usr/local or wherever node
+ is installed.
+* Install it **locally** if you're going to `require()` it.
+* Install it **globally** if you're going to run it on the command line.
+* If you need both, then install it in both places, or use `npm link`.
+
+### prefix Configuration
+
+The `prefix` config defaults to the location where node is installed.
+On most systems, this is `/usr/local`, and most of the time is the same
+as node's `process.installPrefix`.
+
+On windows, this is the exact location of the node.exe binary. On Unix
+systems, it's one level up, since node is typically installed at
+`{prefix}/bin/node` rather than `{prefix}/node.exe`.
+
+When the `global` flag is set, npm installs things into this prefix.
+When it is not set, it uses the root of the current package, or the
+current working directory if not in a package already.
+
+### Node Modules
+
+Packages are dropped into the `node_modules` folder under the `prefix`.
+When installing locally, this means that you can
+`require("packagename")` to load its main module, or
+`require("packagename/lib/path/to/sub/module")` to load other modules.
+
+Global installs on Unix systems go to `{prefix}/lib/node_modules`.
+Global installs on Windows go to `{prefix}/node_modules` (that is, no
+`lib` folder.)
+
+If you wish to `require()` a package, then install it locally.
+
+### Executables
+
+When in global mode, executables are linked into `{prefix}/bin` on Unix,
+or directly into `{prefix}` on Windows.
+
+When in local mode, executables are linked into
+`./node_modules/.bin` so that they can be made available to scripts run
+through npm. (For example, so that a test runner will be in the path
+when you run `npm test`.)
+
+### Man Pages
+
+When in global mode, man pages are linked into `{prefix}/share/man`.
+
+When in local mode, man pages are not installed.
+
+Man pages are not installed on Windows systems.
+
+### Cache
+
+See `npm-cache(1)`. Cache files are stored in `~/.npm` on Posix, or
+`~/npm-cache` on Windows.
+
+This is controlled by the `cache` configuration param.
+
+### Temp Files
+
+Temporary files are stored by default in the folder specified by the
+`tmp` config, which defaults to the TMPDIR, TMP, or TEMP environment
+variables, or `/tmp` on Unix and `c:\windows\temp` on Windows.
+
+Temp files are given a unique folder under this root for each run of the
+program, and are deleted upon successful exit.
+
+## More Information
+
+When installing locally, npm first tries to find an appropriate
+`prefix` folder. This is so that `npm install foo@1.2.3` will install
+to the sensible root of your package, even if you happen to have `cd`ed
+into some other folder.
+
+Starting at the $PWD, npm will walk up the folder tree checking for a
+folder that contains either a `package.json` file, or a `node_modules`
+folder. If such a thing is found, then that is treated as the effective
+"current directory" for the purpose of running npm commands. (This
+behavior is inspired by and similar to git's .git-folder seeking
+logic when running git commands in a working dir.)
+
+If no package root is found, then the current folder is used.
+
+When you run `npm install foo@1.2.3`, then the package is loaded into
+the cache, and then unpacked into `./node_modules/foo`. Then, any of
+foo's dependencies are similarly unpacked into
+`./node_modules/foo/node_modules/...`.
+
+Any bin files are symlinked to `./node_modules/.bin/`, so that they may
+be found by npm scripts when necessary.
+
+### Global Installation
+
+If the `global` configuration is set to true, then npm will
+install packages "globally".
+
+For global installation, packages are installed roughly the same way,
+but using the folders described above.
+
+### Cycles, Conflicts, and Folder Parsimony
+
+Cycles are handled using the property of node's module system that it
+walks up the directories looking for `node_modules` folders. So, at every
+stage, if a package is already installed in an ancestor `node_modules`
+folder, then it is not installed at the current location.
+
+Consider the case above, where `foo -> bar -> baz`. Imagine if, in
+addition to that, baz depended on bar, so you'd have:
+`foo -> bar -> baz -> bar -> baz ...`. However, since the folder
+structure is: `foo/node_modules/bar/node_modules/baz`, there's no need to
+put another copy of bar into `.../baz/node_modules`, since when it calls
+require("bar"), it will get the copy that is installed in
+`foo/node_modules/bar`.
+
+This shortcut is only used if the exact same
+version would be installed in multiple nested `node_modules` folders. It
+is still possible to have `a/node_modules/b/node_modules/a` if the two
+"a" packages are different versions. However, without repeating the
+exact same package multiple times, an infinite regress will always be
+prevented.
+
+Another optimization can be made by installing dependencies at the
+highest level possible, below the localized "target" folder.
+
+#### Example
+
+Consider this dependency graph:
+
+ foo
+ +-- blerg@1.2.5
+ +-- bar@1.2.3
+ | +-- blerg@1.x (latest=1.3.7)
+ | +-- baz@2.x
+ | | `-- quux@3.x
+ | | `-- bar@1.2.3 (cycle)
+ | `-- asdf@*
+ `-- baz@1.2.3
+ `-- quux@3.x
+ `-- bar
+
+In this case, we might expect a folder structure like this:
+
+ foo
+ +-- node_modules
+ +-- blerg (1.2.5) <---[A]
+ +-- bar (1.2.3) <---[B]
+ | +-- node_modules
+ | | `-- baz (2.0.2) <---[C]
+ | | `-- node_modules
+ | | `-- quux (3.2.0)
+ | `-- asdf (2.3.4)
+ `-- baz (1.2.3) <---[D]
+ `-- node_modules
+ `-- quux (3.2.0) <---[E]
+
+Since foo depends directly on bar@1.2.3 and baz@1.2.3, those are
+installed in foo's `node_modules` folder.
+
+Even though the latest copy of blerg is 1.3.7, foo has a specific
+dependency on version 1.2.5. So, that gets installed at [A]. Since the
+parent installation of blerg satisfie's bar's dependency on blerg@1.x,
+it does not install another copy under [B].
+
+Bar [B] also has dependencies on baz and asdf, so those are installed in
+bar's `node_modules` folder. Because it depends on `baz@2.x`, it cannot
+re-use the `baz@1.2.3` installed in the parent `node_modules` folder [D],
+and must install its own copy [C].
+
+Underneath bar, the `baz->quux->bar` dependency creates a cycle.
+However, because `bar` is already in `quux`'s ancestry [B], it does not
+unpack another copy of bar into that folder.
+
+Underneath `foo->baz` [D], quux's [E] folder tree is empty, because its
+dependency on bar is satisfied by the parent folder copy installed at [B].
+
+For a graphical breakdown of what is installed where, use `npm ls`.
+
+### Publishing
+
+Upon publishing, npm will look in the `node_modules` folder. If any of
+the items there are not in the `bundledDependencies` array, then they will
+not be included in the package tarball.
+
+This allows a package maintainer to install all of their dependencies
+(and dev dependencies) locally, but only re-publish those items that
+cannot be found elsewhere. See `npm-json(1)` for more information.
+
+## SEE ALSO
+
+* npm-faq(1)
+* npm-json(1)
+* npm-install(1)
+* npm-pack(1)
+* npm-cache(1)
+* npm-config(1)
+* npm-publish(1)
Folder Structures Used by npm
+## npm-global(1)
+
+ Folder Structures Used by npm
+
## npm-help-search(1)
Search npm help documentation
Start a package
+## npm-rm(1)
+
+ Remove a package
+
## npm-root(1)
Display npm root
The `--link` argument will cause npm to link global installs into the
local space in some cases.
+The `--no-bin-links` argument will prevent npm from creating symlinks for
+any binaries the package might contain.
+
See `npm-config(1)`. Many of the configuration params have some
effect on installation, since that's most of what npm does.
--- /dev/null
+npm-rm(1) -- Remove a package
+=============================
+
+## SYNOPSIS
+
+ npm rm <name>
+ npm uninstall <name>
+
+## DESCRIPTION
+
+This uninstalls a package, completely removing everything npm installed
+on its behalf.
+
+## SEE ALSO
+
+* npm-prune(1)
+* npm-install(1)
+* npm-folders(1)
+* npm-config(1)
<p>This function should not be used programmatically. Instead, just refer
to the <code>npm.bin</code> member.</p>
</div>
-<p id="footer">bin — npm@1.2.2</p>
+<p id="footer">bin — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This command will launch a browser, so this command may not be the most
friendly for programmatic use.</p>
</div>
-<p id="footer">bugs — npm@1.2.2</p>
+<p id="footer">bugs — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/index.html">index(1)</a></li></ul>
</div>
-<p id="footer">commands — npm@1.2.2</p>
+<p id="footer">commands — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/npm.html">npm(3)</a></li></ul>
</div>
-<p id="footer">config — npm@1.2.2</p>
+<p id="footer">config — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/publish.html">publish(3)</a></li><li><a href="../api/unpublish.html">unpublish(3)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">deprecate — npm@1.2.2</p>
+<p id="footer">deprecate — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This command will launch a browser, so this command may not be the most
friendly for programmatic use.</p>
</div>
-<p id="footer">docs — npm@1.2.2</p>
+<p id="footer">docs — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Since this command opens an editor in a new process, be careful about where
and how this is used.</p>
</div>
-<p id="footer">edit — npm@1.2.2</p>
+<p id="footer">edit — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>The first element in the 'args' parameter must be a package name. After that is the optional command, which can be any number of strings. All of the strings will be combined into one, space-delimited command.</p>
</div>
-<p id="footer">explore — npm@1.2.2</p>
+<p id="footer">explore — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>The silent parameter is not neccessary not used, but it may in the future.</p>
</div>
-<p id="footer">help-search — npm@1.2.2</p>
+<p id="footer">help-search — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p><a href="../doc/json.html">json(1)</a></p>
</div>
-<p id="footer">init — npm@1.2.2</p>
+<p id="footer">init — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Finally, 'callback' is a function that will be called when all packages have been
installed or when an error has been encountered.</p>
</div>
-<p id="footer">install — npm@1.2.2</p>
+<p id="footer">install — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Now, any changes to the redis package will be reflected in
the package in the current working directory</p>
</div>
-<p id="footer">link — npm@1.2.2</p>
+<p id="footer">link — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>For a list of all the available command-line configs, see <code>npm help config</code></p>
</div>
-<p id="footer">load — npm@1.2.2</p>
+<p id="footer">load — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
This means that if a submodule a same dependency as a parent module, then the
dependency will only be output once.</p>
</div>
-<p id="footer">ls — npm@1.2.2</p>
+<p id="footer">ls — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<h2 id="SYNOPSIS">SYNOPSIS</h2>
<pre><code>var npm = require("npm")
-npm.load(configObject, function (er, npm) {
+npm.load([configObject,] function (er, npm) {
// use the npm object, now that it's loaded.
npm.config.set(key, val)
<h2 id="VERSION">VERSION</h2>
-<p>1.2.2</p>
+<p>1.2.10</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
To find documentation of the command line
client, see <code><a href="../doc/npm.html">npm(1)</a></code>.</p>
-<p>Prior to using npm's commands,
-<code>npm.load()</code> must be called with an object hash of
-top-level configs. In the npm command line client,
-this set of configs is parsed from the command line options. Additional
-configuration params are loaded from two configuration files. See
-<code><a href="../doc/config.html">config(1)</a></code> for more information.</p>
+<p>Prior to using npm's commands, <code>npm.load()</code> must be called.
+If you provide <code>configObject</code> as an object hash of top-level
+configs, they override the values stored in the various config
+locations. In the npm command line client, this set of configs
+is parsed from the command line options. Additional configuration
+params are loaded from two configuration files. See <code><a href="../doc/config.html">config(1)</a></code>
+for more information.</p>
<p>After that, each of the functions are accessible in the
commands object: <code>npm.commands.<cmd></code>. See <code><a href="../doc/index.html">index(1)</a></code> for a list of
<pre><code>var cmd = npm.deref("unp") // cmd === "unpublish"</code></pre>
</div>
-<p id="footer">npm — npm@1.2.2</p>
+<p id="footer">npm — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>If the 'packages' parameter is left out, npm will check all packages.</p>
</div>
-<p id="footer">outdated — npm@1.2.2</p>
+<p id="footer">outdated — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/publish.html">publish(3)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">owner — npm@1.2.2</p>
+<p id="footer">owner — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>If no arguments are supplied, then npm packs the current package folder.</p>
</div>
-<p id="footer">pack — npm@1.2.2</p>
+<p id="footer">pack — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This function is not useful programmatically</p>
</div>
-<p id="footer">prefix — npm@1.2.2</p>
+<p id="footer">prefix — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Extraneous packages are packages that are not listed on the parent
package's dependencies list.</p>
</div>
-<p id="footer">prune — npm@1.2.2</p>
+<p id="footer">prune — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../api/owner.html">owner(3)</a></li></ul>
</div>
-<p id="footer">publish — npm@1.2.2</p>
+<p id="footer">publish — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>See <code>npm help build</code></p>
</div>
-<p id="footer">rebuild — npm@1.2.2</p>
+<p id="footer">rebuild — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/start.html">start(3)</a></li><li><a href="../api/stop.html">stop(3)</a></li></ul>
</div>
-<p id="footer">restart — npm@1.2.2</p>
+<p id="footer">restart — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This function is not useful programmatically.</p>
</div>
-<p id="footer">root — npm@1.2.2</p>
+<p id="footer">root — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../api/test.html">test(3)</a></li><li><a href="../api/start.html">start(3)</a></li><li><a href="../api/restart.html">restart(3)</a></li><li><a href="../api/stop.html">stop(3)</a></li></ul>
</div>
-<p id="footer">run-script — npm@1.2.2</p>
+<p id="footer">run-script — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
and doesn't try to read your mind (it doesn't do any verb tense matching or the
like).</p>
</div>
-<p id="footer">search — npm@1.2.2</p>
+<p id="footer">search — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Finally, 'callback' is a function that will be called when the shrinkwrap has
been saved.</p>
</div>
-<p id="footer">shrinkwrap — npm@1.2.2</p>
+<p id="footer">shrinkwrap — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>npm can run tests on multiple packages. Just specify multiple packages
in the <code>packages</code> parameter.</p>
</div>
-<p id="footer">start — npm@1.2.2</p>
+<p id="footer">start — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>npm can run stop on multiple packages. Just specify multiple packages
in the <code>packages</code> parameter.</p>
</div>
-<p id="footer">stop — npm@1.2.2</p>
+<p id="footer">stop — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li>npm help json</li><li>git help submodule</li></ul>
</div>
-<p id="footer">submodule — npm@1.2.2</p>
+<p id="footer">submodule — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
used. For more information about how to set this config, check
<code>man 3 npm-config</code> for programmatic usage or <code>man npm-config</code> for cli usage.</p>
</div>
-<p id="footer">tag — npm@1.2.2</p>
+<p id="footer">tag — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>npm can run tests on multiple packages. Just specify multiple packages
in the <code>packages</code> parameter.</p>
</div>
-<p id="footer">test — npm@1.2.2</p>
+<p id="footer">test — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Finally, 'callback' is a function that will be called when all packages have been
uninstalled or when an error has been encountered.</p>
</div>
-<p id="footer">uninstall — npm@1.2.2</p>
+<p id="footer">uninstall — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>If no version is specified, or if all versions are removed then
the root package entry is removed from the registry entirely.</p>
</div>
-<p id="footer">unpublish — npm@1.2.2</p>
+<p id="footer">unpublish — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>The 'packages' argument is an array of packages to update. The 'callback' parameter will be called when done or when an error occurs.</p>
</div>
-<p id="footer">update — npm@1.2.2</p>
+<p id="footer">update — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
parameter. The difference, however, is this function will fail if it does
not have exactly one element. The only element should be a version number.</p>
</div>
-<p id="footer">version — npm@1.2.2</p>
+<p id="footer">version — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>corresponding to the list of fields selected.</p>
</div>
-<p id="footer">view — npm@1.2.2</p>
+<p id="footer">view — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This function is not useful programmatically</p>
</div>
-<p id="footer">whoami — npm@1.2.2</p>
+<p id="footer">whoami — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/help.html">help(1)</a></li><li><a href="../doc/index.html">index(1)</a></li></ul>
</div>
-<p id="footer"><a href="../doc/README.html">README</a> — npm@1.2.2</p>
+<p id="footer"><a href="../doc/README.html">README</a> — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li><li><a href="../doc/whoami.html">whoami(1)</a></li></ul>
</div>
-<p id="footer">adduser — npm@1.2.2</p>
+<p id="footer">adduser — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/prefix.html">prefix(1)</a></li><li><a href="../doc/root.html">root(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">bin — npm@1.2.2</p>
+<p id="footer">bin — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/docs.html">docs(1)</a></li><li><a href="../doc/view.html">view(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">bugs — npm@1.2.2</p>
+<p id="footer">bugs — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/link.html">link(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">build — npm@1.2.2</p>
+<p id="footer">build — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">bundle — npm@1.2.2</p>
+<p id="footer">bundle — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/pack.html">pack(1)</a></li></ul>
</div>
-<p id="footer">cache — npm@1.2.2</p>
+<p id="footer">cache — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li></ul>
</div>
-<p id="footer">changelog — npm@1.2.2</p>
+<p id="footer">changelog — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li></ul>
</div>
-<p id="footer">coding-style — npm@1.2.2</p>
+<p id="footer">coding-style — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li></ul>
</div>
-<p id="footer">completion — npm@1.2.2</p>
+<p id="footer">completion — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Force npm to always require authentication when accessing the registry,
even for <code>GET</code> requests.</p>
+<h3 id="bin-links">bin-links</h3>
+
+<ul><li>Default: <code>true</code></li><li>Type: Boolean</li></ul>
+
+<p>Tells npm to create symlinks (or <code>.cmd</code> shims on Windows) for package
+executables.</p>
+
+<p>Set to false to have it not do this. This can be used to work around
+the fact that some file systems don't support symlinks, even on
+ostensibly Unix systems.</p>
+
<h3 id="browser">browser</h3>
<ul><li>Default: OS X: <code>"open"</code>, others: <code>"google-chrome"</code></li><li>Type: String</li></ul>
<h3 id="cache-min">cache-min</h3>
-<ul><li>Default: 0</li><li>Type: Number</li></ul>
+<ul><li>Default: 10</li><li>Type: Number</li></ul>
<p>The minimum time (in seconds) to keep items in the registry cache before
re-checking against the registry.</p>
<code>prefix</code> folder instead of the current working directory. See
<code><a href="../doc/folders.html">folders(1)</a></code> for more on the differences in behavior.</p>
-<ul><li>packages are installed into the <code>prefix/node_modules</code> folder, instead of the
-current working directory.</li><li>bin files are linked to <code>prefix/bin</code></li><li>man pages are linked to <code>prefix/share/man</code></li></ul>
+<ul><li>packages are installed into the <code>{prefix}/lib/node_modules</code> folder, instead of the
+current working directory.</li><li>bin files are linked to <code>{prefix}/bin</code></li><li>man pages are linked to <code>{prefix}/share/man</code></li></ul>
<h3 id="globalconfig">globalconfig</h3>
<h3 id="user-agent">user-agent</h3>
-<ul><li>Default: npm/{npm.version} node/{process.version}</li><li>Type: String</li></ul>
+<ul><li>Default: node/{process.version} {process.platform} {process.arch}</li><li>Type: String</li></ul>
<p>Sets a User-Agent to the request header</p>
<h3 id="prefix">prefix</h3>
-<ul><li>Default: node's process.installPrefix</li><li>Type: path</li></ul>
+<ul><li>Default: see <a href="../doc/folders.html">folders(1)</a></li><li>Type: path</li></ul>
<p>The location to install global items. If set on the command line, then
it forces non-global commands to run in the specified folder.</p>
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li></ul>
</div>
-<p id="footer">config — npm@1.2.2</p>
+<p id="footer">config — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/ls.html">ls(1)</a></li><li><a href="../doc/update.html">update(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">dedupe — npm@1.2.2</p>
+<p id="footer">dedupe — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">deprecate — npm@1.2.2</p>
+<p id="footer">deprecate — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/init.html">init(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">developers — npm@1.2.2</p>
+<p id="footer">developers — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li></ul>
</div>
-<p id="footer">disputes — npm@1.2.2</p>
+<p id="footer">disputes — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/view.html">view(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">docs — npm@1.2.2</p>
+<p id="footer">docs — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/explore.html">explore(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">edit — npm@1.2.2</p>
+<p id="footer">edit — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/submodule.html">submodule(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/edit.html">edit(1)</a></li><li><a href="../doc/rebuild.html">rebuild(1)</a></li><li><a href="../doc/build.html">build(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">explore — npm@1.2.2</p>
+<p id="footer">explore — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li></ul>
</div>
-<p id="footer">faq — npm@1.2.2</p>
+<p id="footer">faq — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/pack.html">pack(1)</a></li><li><a href="../doc/cache.html">cache(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li></ul>
</div>
-<p id="footer">folders — npm@1.2.2</p>
+<p id="footer">folders — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
--- /dev/null
+<!doctype html>
+<html>
+ <title>global</title>
+ <meta http-equiv="content-type" value="text/html;utf-8">
+ <link rel="stylesheet" type="text/css" href="../static/style.css">
+
+ <body>
+ <div id="wrapper">
+<h1><a href="../doc/folders.html">folders</a></h1> <p>Folder Structures Used by npm</p>
+
+<h2 id="DESCRIPTION">DESCRIPTION</h2>
+
+<p>npm puts various things on your computer. That's its job.</p>
+
+<p>This document will tell you what it puts where.</p>
+
+<h3 id="tl-dr">tl;dr</h3>
+
+<ul><li>Local install (default): puts stuff in <code>./node_modules</code> of the current
+package root.</li><li>Global install (with <code>-g</code>): puts stuff in /usr/local or wherever node
+is installed.</li><li>Install it <strong>locally</strong> if you're going to <code>require()</code> it.</li><li>Install it <strong>globally</strong> if you're going to run it on the command line.</li><li>If you need both, then install it in both places, or use <code>npm link</code>.</li></ul>
+
+<h3 id="prefix-Configuration">prefix Configuration</h3>
+
+<p>The <code>prefix</code> config defaults to the location where node is installed.
+On most systems, this is <code>/usr/local</code>, and most of the time is the same
+as node's <code>process.installPrefix</code>.</p>
+
+<p>On windows, this is the exact location of the node.exe binary. On Unix
+systems, it's one level up, since node is typically installed at
+<code>{prefix}/bin/node</code> rather than <code>{prefix}/node.exe</code>.</p>
+
+<p>When the <code>global</code> flag is set, npm installs things into this prefix.
+When it is not set, it uses the root of the current package, or the
+current working directory if not in a package already.</p>
+
+<h3 id="Node-Modules">Node Modules</h3>
+
+<p>Packages are dropped into the <code>node_modules</code> folder under the <code>prefix</code>.
+When installing locally, this means that you can
+<code>require("packagename")</code> to load its main module, or
+<code>require("packagename/lib/path/to/sub/module")</code> to load other modules.</p>
+
+<p>Global installs on Unix systems go to <code>{prefix}/lib/node_modules</code>.
+Global installs on Windows go to <code>{prefix}/node_modules</code> (that is, no
+<code>lib</code> folder.)</p>
+
+<p>If you wish to <code>require()</code> a package, then install it locally.</p>
+
+<h3 id="Executables">Executables</h3>
+
+<p>When in global mode, executables are linked into <code>{prefix}/bin</code> on Unix,
+or directly into <code>{prefix}</code> on Windows.</p>
+
+<p>When in local mode, executables are linked into
+<code>./node_modules/.bin</code> so that they can be made available to scripts run
+through npm. (For example, so that a test runner will be in the path
+when you run <code>npm test</code>.)</p>
+
+<h3 id="Man-Pages">Man Pages</h3>
+
+<p>When in global mode, man pages are linked into <code>{prefix}/share/man</code>.</p>
+
+<p>When in local mode, man pages are not installed.</p>
+
+<p>Man pages are not installed on Windows systems.</p>
+
+<h3 id="Cache">Cache</h3>
+
+<p>See <code><a href="../doc/cache.html">cache(1)</a></code>. Cache files are stored in <code>~/.npm</code> on Posix, or
+<code>~/npm-cache</code> on Windows.</p>
+
+<p>This is controlled by the <code>cache</code> configuration param.</p>
+
+<h3 id="Temp-Files">Temp Files</h3>
+
+<p>Temporary files are stored by default in the folder specified by the
+<code>tmp</code> config, which defaults to the TMPDIR, TMP, or TEMP environment
+variables, or <code>/tmp</code> on Unix and <code>c:\windows\temp</code> on Windows.</p>
+
+<p>Temp files are given a unique folder under this root for each run of the
+program, and are deleted upon successful exit.</p>
+
+<h2 id="More-Information">More Information</h2>
+
+<p>When installing locally, npm first tries to find an appropriate
+<code>prefix</code> folder. This is so that <code>npm install foo@1.2.3</code> will install
+to the sensible root of your package, even if you happen to have <code>cd</code>ed
+into some other folder.</p>
+
+<p>Starting at the $PWD, npm will walk up the folder tree checking for a
+folder that contains either a <code>package.json</code> file, or a <code>node_modules</code>
+folder. If such a thing is found, then that is treated as the effective
+"current directory" for the purpose of running npm commands. (This
+behavior is inspired by and similar to git's .git-folder seeking
+logic when running git commands in a working dir.)</p>
+
+<p>If no package root is found, then the current folder is used.</p>
+
+<p>When you run <code>npm install foo@1.2.3</code>, then the package is loaded into
+the cache, and then unpacked into <code>./node_modules/foo</code>. Then, any of
+foo's dependencies are similarly unpacked into
+<code>./node_modules/foo/node_modules/...</code>.</p>
+
+<p>Any bin files are symlinked to <code>./node_modules/.bin/</code>, so that they may
+be found by npm scripts when necessary.</p>
+
+<h3 id="Global-Installation">Global Installation</h3>
+
+<p>If the <code>global</code> configuration is set to true, then npm will
+install packages "globally".</p>
+
+<p>For global installation, packages are installed roughly the same way,
+but using the folders described above.</p>
+
+<h3 id="Cycles-Conflicts-and-Folder-Parsimony">Cycles, Conflicts, and Folder Parsimony</h3>
+
+<p>Cycles are handled using the property of node's module system that it
+walks up the directories looking for <code>node_modules</code> folders. So, at every
+stage, if a package is already installed in an ancestor <code>node_modules</code>
+folder, then it is not installed at the current location.</p>
+
+<p>Consider the case above, where <code>foo -> bar -> baz</code>. Imagine if, in
+addition to that, baz depended on bar, so you'd have:
+<code>foo -> bar -> baz -> bar -> baz ...</code>. However, since the folder
+structure is: <code>foo/node_modules/bar/node_modules/baz</code>, there's no need to
+put another copy of bar into <code>.../baz/node_modules</code>, since when it calls
+require("bar"), it will get the copy that is installed in
+<code>foo/node_modules/bar</code>.</p>
+
+<p>This shortcut is only used if the exact same
+version would be installed in multiple nested <code>node_modules</code> folders. It
+is still possible to have <code>a/node_modules/b/node_modules/a</code> if the two
+"a" packages are different versions. However, without repeating the
+exact same package multiple times, an infinite regress will always be
+prevented.</p>
+
+<p>Another optimization can be made by installing dependencies at the
+highest level possible, below the localized "target" folder.</p>
+
+<h4 id="Example">Example</h4>
+
+<p>Consider this dependency graph:</p>
+
+<pre><code>foo
++-- blerg@1.2.5
++-- bar@1.2.3
+| +-- blerg@1.x (latest=1.3.7)
+| +-- baz@2.x
+| | `-- quux@3.x
+| | `-- bar@1.2.3 (cycle)
+| `-- asdf@*
+`-- baz@1.2.3
+ `-- quux@3.x
+ `-- bar</code></pre>
+
+<p>In this case, we might expect a folder structure like this:</p>
+
+<pre><code>foo
++-- node_modules
+ +-- blerg (1.2.5) <---[A]
+ +-- bar (1.2.3) <---[B]
+ | +-- node_modules
+ | | `-- baz (2.0.2) <---[C]
+ | | `-- node_modules
+ | | `-- quux (3.2.0)
+ | `-- asdf (2.3.4)
+ `-- baz (1.2.3) <---[D]
+ `-- node_modules
+ `-- quux (3.2.0) <---[E]</code></pre>
+
+<p>Since foo depends directly on bar@1.2.3 and baz@1.2.3, those are
+installed in foo's <code>node_modules</code> folder.</p>
+
+<p>Even though the latest copy of blerg is 1.3.7, foo has a specific
+dependency on version 1.2.5. So, that gets installed at [A]. Since the
+parent installation of blerg satisfie's bar's dependency on blerg@1.x,
+it does not install another copy under [B].</p>
+
+<p>Bar [B] also has dependencies on baz and asdf, so those are installed in
+bar's <code>node_modules</code> folder. Because it depends on <code>baz@2.x</code>, it cannot
+re-use the <code>baz@1.2.3</code> installed in the parent <code>node_modules</code> folder [D],
+and must install its own copy [C].</p>
+
+<p>Underneath bar, the <code>baz->quux->bar</code> dependency creates a cycle.
+However, because <code>bar</code> is already in <code>quux</code>'s ancestry [B], it does not
+unpack another copy of bar into that folder.</p>
+
+<p>Underneath <code>foo->baz</code> [D], quux's [E] folder tree is empty, because its
+dependency on bar is satisfied by the parent folder copy installed at [B].</p>
+
+<p>For a graphical breakdown of what is installed where, use <code>npm ls</code>.</p>
+
+<h3 id="Publishing">Publishing</h3>
+
+<p>Upon publishing, npm will look in the <code>node_modules</code> folder. If any of
+the items there are not in the <code>bundledDependencies</code> array, then they will
+not be included in the package tarball.</p>
+
+<p>This allows a package maintainer to install all of their dependencies
+(and dev dependencies) locally, but only re-publish those items that
+cannot be found elsewhere. See <code><a href="../doc/json.html">json(1)</a></code> for more information.</p>
+
+<h2 id="SEE-ALSO">SEE ALSO</h2>
+
+<ul><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/pack.html">pack(1)</a></li><li><a href="../doc/cache.html">cache(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li></ul>
+</div>
+<p id="footer">global — npm@1.2.10</p>
+<script>
+;(function () {
+var wrapper = document.getElementById("wrapper")
+var els = Array.prototype.slice.call(wrapper.getElementsByTagName("*"), 0)
+ .filter(function (el) {
+ return el.parentNode === wrapper
+ && el.tagName.match(/H[1-6]/)
+ && el.id
+ })
+var l = 2
+ , toc = document.createElement("ul")
+toc.innerHTML = els.map(function (el) {
+ var i = el.tagName.charAt(1)
+ , out = ""
+ while (i > l) {
+ out += "<ul>"
+ l ++
+ }
+ while (i < l) {
+ out += "</ul>"
+ l --
+ }
+ out += "<li><a href='#" + el.id + "'>" +
+ ( el.innerText || el.text || el.innerHTML)
+ + "</a>"
+ return out
+}).join("\n")
+toc.id = "toc"
+document.body.appendChild(toc)
+})()
+</script>
+</body></html>
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/help.html">help(1)</a></li></ul>
</div>
-<p id="footer">help-search — npm@1.2.2</p>
+<p id="footer">help-search — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/README.html">README</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/help-search.html">help-search(1)</a></li><li><a href="../doc/index.html">index(1)</a></li></ul>
</div>
-<p id="footer">help — npm@1.2.2</p>
+<p id="footer">help — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p> Folder Structures Used by npm</p>
+<h2 id="npm-global-1"><a href="../doc/global.html">global(1)</a></h2>
+
+<p> Folder Structures Used by npm</p>
+
<h2 id="npm-help-search-1"><a href="../doc/help-search.html">help-search(1)</a></h2>
<p> Search npm help documentation</p>
<p> Start a package</p>
+<h2 id="npm-rm-1"><a href="../doc/rm.html">rm(1)</a></h2>
+
+<p> Remove a package</p>
+
<h2 id="npm-root-1"><a href="../doc/root.html">root(1)</a></h2>
<p> Display npm root</p>
<p> Display npm username</p>
</div>
-<p id="footer">index — npm@1.2.2</p>
+<p id="footer">index — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="https://github.com/isaacs/init-package-json">https://github.com/isaacs/init-package-json</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/version.html">version(1)</a></li></ul>
</div>
-<p id="footer">init — npm@1.2.2</p>
+<p id="footer">init — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>The <code>--link</code> argument will cause npm to link global installs into the
local space in some cases.</p>
+<p>The <code>--no-bin-links</code> argument will prevent npm from creating symlinks for
+any binaries the package might contain.</p>
+
<p>See <code><a href="../doc/config.html">config(1)</a></code>. Many of the configuration params have some
effect on installation, since that's most of what npm does.</p>
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/update.html">update(1)</a></li><li><a href="../doc/link.html">link(1)</a></li><li><a href="../doc/rebuild.html">rebuild(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/build.html">build(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/tag.html">tag(1)</a></li><li><a href="../doc/rm.html">rm(1)</a></li><li><a href="../doc/shrinkwrap.html">shrinkwrap(1)</a></li></ul>
</div>
-<p id="footer">install — npm@1.2.2</p>
+<p id="footer">install — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/semver.html">semver(1)</a></li><li><a href="../doc/init.html">init(1)</a></li><li><a href="../doc/version.html">version(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/help.html">help(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/rm.html">rm(1)</a></li></ul>
</div>
-<p id="footer">json — npm@1.2.2</p>
+<p id="footer">json — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">link — npm@1.2.2</p>
+<p id="footer">link — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
nested packages will <em>also</em> show the paths to the specified packages.
For example, running <code>npm ls promzard</code> in npm's source tree will show:</p>
-<pre><code>npm@1.2.2 /path/to/npm
+<pre><code>npm@1.2.10 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5</code></pre>
<ul><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/link.html">link(1)</a></li><li><a href="../doc/prune.html">prune(1)</a></li><li><a href="../doc/outdated.html">outdated(1)</a></li><li><a href="../doc/update.html">update(1)</a></li></ul>
</div>
-<p id="footer">ls — npm@1.2.2</p>
+<p id="footer">ls — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<h2 id="VERSION">VERSION</h2>
-<p>1.2.2</p>
+<p>1.2.10</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
<ul><li><a href="../doc/help.html">help(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/README.html">README</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/index.html">index(1)</a></li><li><a href="../api/npm.html">npm(3)</a></li></ul>
</div>
-<p id="footer">npm — npm@1.2.2</p>
+<p id="footer">npm — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/update.html">update(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li></ul>
</div>
-<p id="footer">outdated — npm@1.2.2</p>
+<p id="footer">outdated — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/disputes.html">disputes(1)</a></li></ul>
</div>
-<p id="footer">owner — npm@1.2.2</p>
+<p id="footer">owner — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/cache.html">cache(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">pack — npm@1.2.2</p>
+<p id="footer">pack — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/root.html">root(1)</a></li><li><a href="../doc/bin.html">bin(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">prefix — npm@1.2.2</p>
+<p id="footer">prefix — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/rm.html">rm(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/list.html">list(1)</a></li></ul>
</div>
-<p id="footer">prune — npm@1.2.2</p>
+<p id="footer">prune — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li><li><a href="../doc/deprecate.html">deprecate(1)</a></li><li><a href="../doc/tag.html">tag(1)</a></li></ul>
</div>
-<p id="footer">publish — npm@1.2.2</p>
+<p id="footer">publish — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/build.html">build(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">rebuild — npm@1.2.2</p>
+<p id="footer">rebuild — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/disputes.html">disputes(1)</a></li></ul>
</div>
-<p id="footer">registry — npm@1.2.2</p>
+<p id="footer">registry — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/README.html">README</a></li><li><a href="../doc/rm.html">rm(1)</a></li><li><a href="../doc/prune.html">prune(1)</a></li></ul>
</div>
-<p id="footer">removing-npm — npm@1.2.2</p>
+<p id="footer">removing-npm — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">restart — npm@1.2.2</p>
+<p id="footer">restart — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
--- /dev/null
+<!doctype html>
+<html>
+ <title>rm</title>
+ <meta http-equiv="content-type" value="text/html;utf-8">
+ <link rel="stylesheet" type="text/css" href="../static/style.css">
+
+ <body>
+ <div id="wrapper">
+<h1><a href="../doc/rm.html">rm</a></h1> <p>Remove a package</p>
+
+<h2 id="SYNOPSIS">SYNOPSIS</h2>
+
+<pre><code>npm rm <name>
+npm uninstall <name></code></pre>
+
+<h2 id="DESCRIPTION">DESCRIPTION</h2>
+
+<p>This uninstalls a package, completely removing everything npm installed
+on its behalf.</p>
+
+<h2 id="SEE-ALSO">SEE ALSO</h2>
+
+<ul><li><a href="../doc/prune.html">prune(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
+</div>
+<p id="footer">rm — npm@1.2.10</p>
+<script>
+;(function () {
+var wrapper = document.getElementById("wrapper")
+var els = Array.prototype.slice.call(wrapper.getElementsByTagName("*"), 0)
+ .filter(function (el) {
+ return el.parentNode === wrapper
+ && el.tagName.match(/H[1-6]/)
+ && el.id
+ })
+var l = 2
+ , toc = document.createElement("ul")
+toc.innerHTML = els.map(function (el) {
+ var i = el.tagName.charAt(1)
+ , out = ""
+ while (i > l) {
+ out += "<ul>"
+ l ++
+ }
+ while (i < l) {
+ out += "</ul>"
+ l --
+ }
+ out += "<li><a href='#" + el.id + "'>" +
+ ( el.innerText || el.text || el.innerHTML)
+ + "</a>"
+ return out
+}).join("\n")
+toc.id = "toc"
+document.body.appendChild(toc)
+})()
+</script>
+</body></html>
<ul><li><a href="../doc/prefix.html">prefix(1)</a></li><li><a href="../doc/bin.html">bin(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">root — npm@1.2.2</p>
+<p id="footer">root — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">run-script — npm@1.2.2</p>
+<p id="footer">run-script — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">scripts — npm@1.2.2</p>
+<p id="footer">scripts — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/view.html">view(1)</a></li></ul>
</div>
-<p id="footer">search — npm@1.2.2</p>
+<p id="footer">search — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">semver — npm@1.2.2</p>
+<p id="footer">semver — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/list.html">list(1)</a></li></ul>
</div>
-<p id="footer">shrinkwrap — npm@1.2.2</p>
+<p id="footer">shrinkwrap — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/view.html">view(1)</a></li><li><a href="../doc/whoami.html">whoami(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li></ul>
</div>
-<p id="footer">star — npm@1.2.2</p>
+<p id="footer">star — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">start — npm@1.2.2</p>
+<p id="footer">start — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li></ul>
</div>
-<p id="footer">stop — npm@1.2.2</p>
+<p id="footer">stop — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/json.html">json(1)</a></li><li>git help submodule</li></ul>
</div>
-<p id="footer">submodule — npm@1.2.2</p>
+<p id="footer">submodule — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">tag — npm@1.2.2</p>
+<p id="footer">tag — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">test — npm@1.2.2</p>
+<p id="footer">test — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/prune.html">prune(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">uninstall — npm@1.2.2</p>
+<p id="footer">uninstall — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/deprecate.html">deprecate(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li></ul>
</div>
-<p id="footer">unpublish — npm@1.2.2</p>
+<p id="footer">unpublish — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/outdated.html">outdated(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/list.html">list(1)</a></li></ul>
</div>
-<p id="footer">update — npm@1.2.2</p>
+<p id="footer">update — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/init.html">init(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/semver.html">semver(1)</a></li></ul>
</div>
-<p id="footer">version — npm@1.2.2</p>
+<p id="footer">version — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/search.html">search(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/docs.html">docs(1)</a></li></ul>
</div>
-<p id="footer">view — npm@1.2.2</p>
+<p id="footer">view — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li></ul>
</div>
-<p id="footer">whoami — npm@1.2.2</p>
+<p id="footer">whoami — npm@1.2.10</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
}
function linkStuff (pkg, folder, global, didRB, cb) {
+ // allow to opt out of linking binaries.
+ if (npm.config.get("bin-links") === false) return cb()
+
// if it's global, and folder is in {prefix}/node_modules,
// then bins are in {prefix}/bin
// otherwise, then bins are in folder/../.bin
chain(files.filter(function (file) {
// rebuild if:
// not a .folder, like .bin or .hooks
- return file.charAt(0) !== "."
+ return !file.match(/^[\._-]/)
// not some old 0.x style bundle
&& file.indexOf("@") === -1
// either not a dep, or explicitly bundled
}
readJson(jsonFile, function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) return addNamed(name, ver, c)
deprCheck(data)
c(er, data)
// it needs the ssh://
// If the path is like ssh://foo:some/path then it works, but
// only if you remove the ssh://
+ var origUrl = u
u = u.replace(/^git\+/, "")
.replace(/#.*$/, "")
p = path.join(npm.config.get("cache"), "_git-remotes", v)
- checkGitDir(p, u, co, cb)
+ checkGitDir(p, u, co, origUrl, cb)
})
}
-function checkGitDir (p, u, co, cb) {
+function checkGitDir (p, u, co, origUrl, cb) {
fs.stat(p, function (er, s) {
- if (er) return cloneGitRemote(p, u, co, cb)
+ if (er) return cloneGitRemote(p, u, co, origUrl, cb)
if (!s.isDirectory()) return rm(p, function (er){
if (er) return cb(er)
- cloneGitRemote(p, u, co, cb)
+ cloneGitRemote(p, u, co, origUrl, cb)
})
var git = npm.config.get("git")
+ "wrong result ("+u+")", stdoutTrimmed )
return rm(p, function (er){
if (er) return cb(er)
- cloneGitRemote(p, u, co, cb)
+ cloneGitRemote(p, u, co, origUrl, cb)
})
}
log.verbose("git remote.origin.url", stdoutTrimmed)
- archiveGitRemote(p, u, co, cb)
+ archiveGitRemote(p, u, co, origUrl, cb)
})
})
}
-function cloneGitRemote (p, u, co, cb) {
+function cloneGitRemote (p, u, co, origUrl, cb) {
mkdir(p, function (er) {
if (er) return cb(er)
exec( npm.config.get("git"), ["clone", "--mirror", u, p], gitEnv(), false
return cb(er)
}
log.verbose("git clone " + u, stdout)
- archiveGitRemote(p, u, co, cb)
+ archiveGitRemote(p, u, co, origUrl, cb)
})
})
}
-function archiveGitRemote (p, u, co, cb) {
+function archiveGitRemote (p, u, co, origUrl, cb) {
var git = npm.config.get("git")
var archive = ["fetch", "-a", "origin"]
var resolve = ["rev-list", "-n1", co]
return next(er)
}
log.verbose("git rev-list -n1 " + co, stdout)
- var parsed = url.parse(u)
+ var parsed = url.parse(origUrl)
parsed.hash = stdout
resolved = url.format(parsed)
+ log.verbose('resolved git url', resolved)
next()
})
if (!er) readJson( path.join( npm.cache, name, ver
, "package", "package.json" )
, function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) return fetchit()
return cb(null, data)
})
}
var madeCache = false
+var myLocks = {}
function lock (u, cb) {
// the cache dir needs to exist already for this.
if (madeCache) then()
, wait: npm.config.get("cache-lock-wait") }
var lf = lockFileName(u)
log.verbose("lock", u, lf)
- lockFile.lock(lf, opts, cb)
+ lockFile.lock(lf, opts, function(er) {
+ if (!er) myLocks[lf] = true
+ cb(er)
+ })
}
}
function unlock (u, cb) {
+ var lf = lockFileName(u)
+ if (!myLocks[lf]) return process.nextTick(cb)
+ myLocks[lf] = false
lockFile.unlock(lockFileName(u), cb)
}
function dedupe_ (dir, filter, unavoidable, dryrun, silent, cb) {
readInstalled(path.resolve(dir), {}, null, function (er, data, counter) {
+ if (er) {
+ return cb(er)
+ }
+
+ if (!data) {
+ return cb()
+ }
+
// find out which things are dupes
- var dupes = Object.keys(counter).filter(function (k) {
+ var dupes = Object.keys(counter || {}).filter(function (k) {
if (filter.length && -1 === filter.indexOf(k)) return false
return counter[k] > 1 && !unavoidable[k]
}).reduce(function (s, k) {
})
readJson(path.resolve(dir, "package.json"), function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) return cb() // not a package, probably.
counter[data.name] = counter[data.name] || 0
counter[data.name]++
fs.readdir(path.resolve(dir, "node_modules"), function (er, c) {
children = c || [] // error is ok, just means no children.
+ children = children.filter(function (p) {
+ return !p.match(/^[\._-]/)
+ })
next()
})
var npm = require("./npm.js")
, semver = require("semver")
, readJson = require("read-package-json")
+ , readInstalled = require("read-installed")
, log = require("npmlog")
, path = require("path")
, fs = require("graceful-fs")
function cb (er, installed) {
if (er) return cb_(er)
- var tree = treeify(installed || [])
- , pretty = prettify(tree, installed).trim()
+ findPeerInvalid(where, function (er, problem) {
+ if (er) return cb_(er)
- if (pretty) console.log(pretty)
- if (er) return cb_(er)
- save(where, installed, tree, pretty, cb_)
+ if (problem) {
+ var peerInvalidError = new Error("The package " + problem.name +
+ " does not satisfy its siblings' peerDependencies requirements!")
+ peerInvalidError.code = "EPEERINVALID"
+ peerInvalidError.packageName = problem.name
+ peerInvalidError.peersDepending = problem.peersDepending
+ return cb(peerInvalidError)
+ }
+
+ var tree = treeify(installed || [])
+ , pretty = prettify(tree, installed).trim()
+
+ if (pretty) console.log(pretty)
+ save(where, installed, tree, pretty, cb_)
+ })
}
// the /path/to/node_modules/..
// initial "family" is the name:version of the root, if it's got
// a package.json file.
readJson(path.resolve(where, "package.json"), function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) data = null
var context = { family: {}
, ancestors: {}
})
}
+function findPeerInvalid (where, cb) {
+ readInstalled(where, function (er, data) {
+ if (er) return cb(er)
+
+ cb(null, findPeerInvalid_(data.dependencies, []))
+ })
+}
+
+function findPeerInvalid_ (packageMap, fpiList) {
+ if (fpiList.indexOf(packageMap) !== -1)
+ return
+
+ fpiList.push(packageMap)
+
+ for (var packageName in packageMap) {
+ var pkg = packageMap[packageName]
+
+ if (pkg.peerInvalid) {
+ var peersDepending = {};
+ for (peerName in packageMap) {
+ var peer = packageMap[peerName]
+ if (peer.peerDependencies && peer.peerDependencies[packageName]) {
+ peersDepending[peer.name + "@" + peer.version] =
+ peer.peerDependencies[packageName]
+ }
+ }
+ return { name: pkg.name, peersDepending: peersDepending }
+ }
+
+ if (pkg.dependencies) {
+ var invalid = findPeerInvalid_(pkg.dependencies, fpiList)
+ if (invalid)
+ return invalid
+ }
+ }
+
+ return null
+}
+
// reads dependencies for the package at "where". There are several cases,
// depending on our current state and the package's configuration:
//
if (er) return cb(er)
if (opts && opts.dev) {
- if (!data.dependencies) data.dependencies = {};
+ if (!data.dependencies) data.dependencies = {}
Object.keys(data.devDependencies || {}).forEach(function (k) {
data.dependencies[k] = data.devDependencies[k]
})
return path.resolve(nm, p, "package.json")
}), function (jsonfile, cb) {
readJson(jsonfile, function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) return cb(null, [])
return cb(null, [[data.name, data.version]])
})
if (!context.explicit) fs.readdir(nm, function (er, inst) {
if (er) return alreadyInstalledManually = []
+
+ // don't even mess with non-package looking things
+ inst = inst.filter(function (p) {
+ return !p.match(/^[\._-]/)
+ })
+
asyncMap(inst, function (pkg, cb) {
readJson(path.resolve(nm, pkg, "package.json"), function (er, d) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
// error means it's not a package, most likely.
if (er) return cb(null, [])
, parent = context.parent
readJson(jsonFile, function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er || data._id === target._id) {
if (er) {
install( path.resolve(npm.globalDir, "..")
, target._from ]
}
+// name => install locations
+var installOnesInProgress = Object.create(null)
+
+function isIncompatibleInstallOneInProgress(target, where) {
+ return target.name in installOnesInProgress &&
+ installOnesInProgress[target.name].indexOf(where) !== -1
+}
+
function installOne_ (target, where, context, cb) {
var nm = path.resolve(where, "node_modules")
, targetFolder = path.resolve(nm, target.name)
- , prettyWhere = path.relative(process.cwd, where)
+ , prettyWhere = path.relative(process.cwd(), where)
, parent = context.parent
if (prettyWhere === ".") prettyWhere = null
+ if (isIncompatibleInstallOneInProgress(target, where)) {
+ var prettyTarget = path.relative(process.cwd(), targetFolder)
+
+ // just call back, with no error. the error will be detected in the
+ // final check for peer-invalid dependencies
+ return cb()
+ }
+
+ if (!(target.name in installOnesInProgress)) {
+ installOnesInProgress[target.name] = []
+ }
+ installOnesInProgress[target.name].push(where)
+ var indexOfIOIP = installOnesInProgress[target.name].length - 1
+
chain
( [ [checkEngine, target]
, [checkPlatform, target]
, [checkGit, targetFolder]
, [write, target, targetFolder, context] ]
, function (er, d) {
+ installOnesInProgress[target.name].splice(indexOfIOIP, 1)
+
if (er) return cb(er)
+
d.push(resultList(target, where, parent && parent._id))
cb(er, d)
}
list = [list]
}
if (list.length === 1 && list[0] === "any") {
- return true;
+ return true
}
for (var i = 0; i < list.length; ++i) {
tmp = list[i]
if (tmp[0] === '!') {
tmp = tmp.slice(1)
if (tmp === value) {
- return false;
+ return false
}
++blc
} else {
if (peerDeps.length > 0) {
actions.push(
- [ installManyAndBuild, peerDeps, pdTargetFolder, pdContext ]
+ [ installMany, peerDeps, pdTargetFolder, pdContext ]
)
}
var dir = npm.globalDir
fs.readdir(dir, function (er, files) {
cb(er, files.filter(function (f) {
- return f.charAt(0) !== "."
+ return !f.match(/^[\._-]/)
}))
})
}
var deps = null
readJson(path.resolve(dir, "package.json"), function (er, d) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
deps = (er) ? true : (d.dependencies || {})
return next()
})
has = Object.create(parentHas)
return next()
}
+ pkgs = pkgs.filter(function (p) {
+ return !p.match(/^[\._-]/)
+ })
asyncMap(pkgs, function (pkg, cb) {
var jsonFile = path.resolve(dir, "node_modules", pkg, "package.json")
readJson(jsonFile, function (er, d) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
cb(null, er ? [] : [[d.name, d.version]])
})
}, function (er, pvs) {
var arg = args[0]
// if it's a local folder, then run the prepublish there, first.
readJson(path.resolve(arg, "package.json"), function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
// error is ok. could be publishing a url or tarball
// however, that means that we will not have automatically run
// the prepublish script, since that gets run when adding a folder
// or a package, in which case, complete against its scripts
var json = path.join(npm.prefix, "package.json")
return readJson(json, function (er, d) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) d = {}
var scripts = Object.keys(d.scripts || {})
console.error("local scripts", scripts)
var pkgDir = path.resolve( pref, "node_modules"
, argv[2], "package.json" )
readJson(pkgDir, function (er, d) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) d = {}
var scripts = Object.keys(d.scripts || {})
return cb(null, scripts)
if (npm.config.get("global")) scripts = [], next()
else readJson(path.join(npm.prefix, "package.json"), function (er, d) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
d = d || {}
scripts = Object.keys(d.scripts || {})
next()
// remove this package from the global space, if it's installed there
if (npm.config.get("global")) return cb(uninstall.usage)
readJson(path.resolve(npm.prefix, "package.json"), function (er, pkg) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) return cb(uninstall.usage)
uninstall_( [pkg.name]
, npm.dir
// read the package name and version out of that.
var cwdJson = path.join(process.cwd(), "package.json")
return readJson(cwdJson, function (er, data) {
- if (er && er.code !== "ENOENT") return cb(er)
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) return cb("Usage:\n"+unpublish.usage)
gotProject(data.name, data.version, cb)
})
].join("\n"))
break
+ case "EPEERINVALID":
+ var peerErrors = Object.keys(er.peersDepending).map(function (peer) {
+ return "Peer " + peer + " wants " + er.packageName + "@"
+ + er.peersDepending[peer]
+ })
+ log.error("peerinvalid", [er.message].concat(peerErrors).join("\n"))
+ break
+
case "ENOTSUP":
if (er.required) {
log.error("notsup", [er.message
for (var i in data) if (i.charAt(0) !== "_") {
var envKey = (prefix+i).replace(/[^a-zA-Z0-9_]/g, '_')
+ if (i === "readme") {
+ continue
+ }
if (data[i] && typeof(data[i]) === "object") {
try {
// quick and dirty detection for cyclical structures
exports.pack = pack
exports.unpack = unpack
-function pack (targetTarball, folder, pkg, dfc, cb) {
- log.verbose("tar pack", [targetTarball, folder])
+function pack (tarball, folder, pkg, dfc, cb) {
+ log.verbose("tar pack", [tarball, folder])
if (typeof cb !== "function") cb = dfc, dfc = false
- log.verbose("tarball", targetTarball)
+ log.verbose("tarball", tarball)
log.verbose("folder", folder)
if (dfc) {
// do fancy crap
return lifecycle(pkg, "prepublish", folder, function (er) {
if (er) return cb(er)
- pack_(targetTarball, folder, pkg, cb)
+ pack_(tarball, folder, pkg, cb)
})
} else {
- pack_(targetTarball, folder, pkg, cb)
+ pack_(tarball, folder, pkg, cb)
}
}
-function pack_ (targetTarball, folder, pkg, cb_) {
+function pack_ (tarball, folder, pkg, cb_) {
+ var tarballLock = false
+ , folderLock = false
+
function cb (er) {
- unlock(targetTarball, function () {
- return cb_(er)
- })
+ if (folderLock)
+ unlock(folder, function() {
+ folderLock = false
+ cb(er)
+ })
+ else if (tarballLock)
+ unlock(tarball, function() {
+ tarballLock = false
+ cb(er)
+ })
+ else
+ cb_(er)
}
- lock(targetTarball, function (er) {
+
+ lock(folder, function(er) {
if (er) return cb(er)
+ folderLock = true
+ next()
+ })
+
+ lock(tarball, function (er) {
+ if (er) return cb(er)
+ tarballLock = true
+ next()
+ })
+
+ function next () {
+ if (!tarballLock || !folderLock) return
new Packer({ path: folder, type: "Directory", isDirectory: true })
.on("error", function (er) {
// non-compliant tar implementations.
.pipe(tar.Pack({ noProprietary: !npm.config.get("proprietary-attribs") }))
.on("error", function (er) {
- if (er) log.error("tar.pack", "tar creation error", targetTarball)
+ if (er) log.error("tar.pack", "tar creation error", tarball)
cb(er)
})
.pipe(zlib.Gzip())
.on("error", function (er) {
- if (er) log.error("tar.pack", "gzip error "+targetTarball)
+ if (er) log.error("tar.pack", "gzip error "+tarball)
cb(er)
})
- .pipe(fstream.Writer({ type: "File", path: targetTarball }))
+ .pipe(fstream.Writer({ type: "File", path: tarball }))
.on("error", function (er) {
- if (er) log.error("tar.pack", "Could not write "+targetTarball)
+ if (er) log.error("tar.pack", "Could not write "+tarball)
cb(er)
})
.on("close", cb)
- })
+ }
}
function unpack_ ( tarball, unpackTarget, dMode, fMode, uid, gid, cb_ ) {
var parent = path.dirname(unpackTarget)
, base = path.basename(unpackTarget)
+ , folderLock
+ , tarballLock
function cb (er) {
- unlock(unpackTarget, function () {
- return cb_(er)
- })
+ if (folderLock)
+ unlock(unpackTarget, function() {
+ folderLock = false
+ cb(er)
+ })
+ else if (tarballLock)
+ unlock(tarball, function() {
+ tarballLock = false
+ cb(er)
+ })
+ else
+ cb_(er)
}
lock(unpackTarget, function (er) {
if (er) return cb(er)
- rmGunz()
+ folderLock = true
+ next()
})
+ lock(tarball, function (er) {
+ if (er) return cb(er)
+ tarballLock = true
+ next()
+ })
+
+ function next() {
+ if (!tarballLock || !folderLock) return
+ rmGunz()
+ }
+
function rmGunz () {
rm(unpackTarget, function (er) {
if (er) return cb(er)
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM" "1" "January 2013" "" ""
+.TH "NPM" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm\fR \-\- node package manager
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-ADDUSER" "1" "January 2013" "" ""
+.TH "NPM\-ADDUSER" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-adduser\fR \-\- Add a registry user account
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-BIN" "1" "January 2013" "" ""
+.TH "NPM\-BIN" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-bin\fR \-\- Display npm bin folder
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-BUGS" "1" "January 2013" "" ""
+.TH "NPM\-BUGS" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-bugs\fR \-\- Bugs for a package in a web browser maybe
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-BUILD" "1" "January 2013" "" ""
+.TH "NPM\-BUILD" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-build\fR \-\- Build a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-BUNDLE" "1" "January 2013" "" ""
+.TH "NPM\-BUNDLE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-bundle\fR \-\- REMOVED
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-CACHE" "1" "January 2013" "" ""
+.TH "NPM\-CACHE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-cache\fR \-\- Manipulates packages cache
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-CHANGELOG" "1" "January 2013" "" ""
+.TH "NPM\-CHANGELOG" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-changelog\fR \-\- Changes
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-CODING\-STYLE" "1" "January 2013" "" ""
+.TH "NPM\-CODING\-STYLE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-coding-style\fR \-\- npm\'s "funny" coding style
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-COMPLETION" "1" "January 2013" "" ""
+.TH "NPM\-COMPLETION" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-completion\fR \-\- Tab Completion for npm
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-CONFIG" "1" "January 2013" "" ""
+.TH "NPM\-CONFIG" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-config\fR \-\- Manage the npm configuration file
Force npm to always require authentication when accessing the registry,
even for \fBGET\fR requests\.
.
+.SS "bin\-links"
+.
+.IP "\(bu" 4
+Default: \fBtrue\fR
+.
+.IP "\(bu" 4
+Type: Boolean
+.
+.IP "" 0
+.
+.P
+Tells npm to create symlinks (or \fB\|\.cmd\fR shims on Windows) for package
+executables\.
+.
+.P
+Set to false to have it not do this\. This can be used to work around
+the fact that some file systems don\'t support symlinks, even on
+ostensibly Unix systems\.
+.
.SS "browser"
.
.IP "\(bu" 4
.SS "cache\-min"
.
.IP "\(bu" 4
-Default: 0
+Default: 10
.
.IP "\(bu" 4
Type: Number
Operates in "global" mode, so that packages are installed into the \fBprefix\fR folder instead of the current working directory\. See \fBnpm help folders\fR for more on the differences in behavior\.
.
.IP "\(bu" 4
-packages are installed into the \fBprefix/node_modules\fR folder, instead of the
+packages are installed into the \fB{prefix}/lib/node_modules\fR folder, instead of the
current working directory\.
.
.IP "\(bu" 4
-bin files are linked to \fBprefix/bin\fR
+bin files are linked to \fB{prefix}/bin\fR
.
.IP "\(bu" 4
-man pages are linked to \fBprefix/share/man\fR
+man pages are linked to \fB{prefix}/share/man\fR
.
.IP "" 0
.
.SS "user\-agent"
.
.IP "\(bu" 4
-Default: npm/{npm\.version} node/{process\.version}
+Default: node/{process\.version} {process\.platform} {process\.arch}
.
.IP "\(bu" 4
Type: String
.SS "prefix"
.
.IP "\(bu" 4
-Default: node\'s process\.installPrefix
+Default: see npm help folders
.
.IP "\(bu" 4
Type: path
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-DEDUPE" "1" "January 2013" "" ""
+.TH "NPM\-DEDUPE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-dedupe\fR \-\- Reduce duplication
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-DEPRECATE" "1" "January 2013" "" ""
+.TH "NPM\-DEPRECATE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-deprecate\fR \-\- Deprecate a version of a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-DEVELOPERS" "1" "January 2013" "" ""
+.TH "NPM\-DEVELOPERS" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-developers\fR \-\- Developer Guide
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-DISPUTES" "1" "January 2013" "" ""
+.TH "NPM\-DISPUTES" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-disputes\fR \-\- Handling Module Name Disputes
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-DOCS" "1" "January 2013" "" ""
+.TH "NPM\-DOCS" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-docs\fR \-\- Docs for a package in a web browser maybe
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-EDIT" "1" "January 2013" "" ""
+.TH "NPM\-EDIT" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-edit\fR \-\- Edit an installed package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-EXPLORE" "1" "January 2013" "" ""
+.TH "NPM\-EXPLORE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-explore\fR \-\- Browse an installed package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-FAQ" "1" "January 2013" "" ""
+.TH "NPM\-FAQ" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-faq\fR \-\- Frequently Asked Questions
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-FOLDERS" "1" "January 2013" "" ""
+.TH "NPM\-FOLDERS" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-folders\fR \-\- Folder Structures Used by npm
-.\" Generated with Ronnjs/v0.1
+.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-FOLDERS" "1" "November 2011" "" ""
+.TH "NPM\-FOLDERS" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-folders\fR \-\- Folder Structures Used by npm
Another optimization can be made by installing dependencies at the
highest level possible, below the localized "target" folder\.
.
-.TP
-Example
-.Consider this dependency graph:
+.SS "\fIExample\fR"
+Consider this dependency graph:
.
.IP "" 4
.
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-HELP\-SEARCH" "1" "January 2013" "" ""
+.TH "NPM\-HELP\-SEARCH" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-help-search\fR \-\- Search npm help documentation
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-HELP" "1" "January 2013" "" ""
+.TH "NPM\-HELP" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-help\fR \-\- Get help on npm
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-INDEX" "1" "January 2013" "" ""
+.TH "NPM\-INDEX" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-index\fR \-\- Index of all npm documentation
.SH "npm help folders"
Folder Structures Used by npm
.
+.SH "npm help global"
+ Folder Structures Used by npm
+.
.SH "npm help help\-search"
Search npm help documentation
.
.SH "npm help restart"
Start a package
.
+.SH "npm help rm"
+ Remove a package
+.
.SH "npm help root"
Display npm root
.
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-INIT" "1" "January 2013" "" ""
+.TH "NPM\-INIT" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-init\fR \-\- Interactively create a package\.json file
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-INSTALL" "1" "January 2013" "" ""
+.TH "NPM\-INSTALL" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-install\fR \-\- Install a package
local space in some cases\.
.
.P
+The \fB\-\-no\-bin\-links\fR argument will prevent npm from creating symlinks for
+any binaries the package might contain\.
+.
+.P
See \fBnpm help config\fR\|\. Many of the configuration params have some
effect on installation, since that\'s most of what npm does\.
.
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-JSON" "1" "January 2013" "" ""
+.TH "NPM\-JSON" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-json\fR \-\- Specifics of npm\'s package\.json handling
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-LINK" "1" "January 2013" "" ""
+.TH "NPM\-LINK" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-link\fR \-\- Symlink a package folder
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-LS" "1" "January 2013" "" ""
+.TH "NPM\-LS" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-ls\fR \-\- List installed packages
.IP "" 4
.
.nf
-npm@1.2.2 /path/to/npm
+npm@1.2.10 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM" "1" "January 2013" "" ""
+.TH "NPM" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm\fR \-\- node package manager
.fi
.
.SH "VERSION"
-1.2.2
+1.2.10
.
.SH "DESCRIPTION"
npm is the package manager for the Node JavaScript platform\. It puts
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-OUTDATED" "1" "January 2013" "" ""
+.TH "NPM\-OUTDATED" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-outdated\fR \-\- Check for outdated packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-OWNER" "1" "January 2013" "" ""
+.TH "NPM\-OWNER" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-owner\fR \-\- Manage package owners
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PACK" "1" "January 2013" "" ""
+.TH "NPM\-PACK" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-pack\fR \-\- Create a tarball from a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PREFIX" "1" "January 2013" "" ""
+.TH "NPM\-PREFIX" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-prefix\fR \-\- Display prefix
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PRUNE" "1" "January 2013" "" ""
+.TH "NPM\-PRUNE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-prune\fR \-\- Remove extraneous packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PUBLISH" "1" "January 2013" "" ""
+.TH "NPM\-PUBLISH" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-publish\fR \-\- Publish a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-REBUILD" "1" "January 2013" "" ""
+.TH "NPM\-REBUILD" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-rebuild\fR \-\- Rebuild a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-REGISTRY" "1" "January 2013" "" ""
+.TH "NPM\-REGISTRY" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-registry\fR \-\- The JavaScript Package Registry
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-REMOVAL" "1" "January 2013" "" ""
+.TH "NPM\-REMOVAL" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-removal\fR \-\- Cleaning the Slate
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-RESTART" "1" "January 2013" "" ""
+.TH "NPM\-RESTART" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-restart\fR \-\- Start a package
-.\" Generated with Ronnjs/v0.1
+.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-RM" "1" "November 2011" "" ""
+.TH "NPM\-RM" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-rm\fR \-\- Remove a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-ROOT" "1" "January 2013" "" ""
+.TH "NPM\-ROOT" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-root\fR \-\- Display npm root
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-RUN\-SCRIPT" "1" "January 2013" "" ""
+.TH "NPM\-RUN\-SCRIPT" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-run-script\fR \-\- Run arbitrary package scripts
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SCRIPTS" "1" "January 2013" "" ""
+.TH "NPM\-SCRIPTS" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-scripts\fR \-\- How npm handles the "scripts" field
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SEARCH" "1" "January 2013" "" ""
+.TH "NPM\-SEARCH" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-search\fR \-\- Search for packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SEMVER" "1" "January 2013" "" ""
+.TH "NPM\-SEMVER" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-semver\fR \-\- The semantic versioner for npm
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SHRINKWRAP" "1" "January 2013" "" ""
+.TH "NPM\-SHRINKWRAP" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-shrinkwrap\fR \-\- Lock down dependency versions
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-STAR" "1" "January 2013" "" ""
+.TH "NPM\-STAR" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-star\fR \-\- Mark your favorite packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-START" "1" "January 2013" "" ""
+.TH "NPM\-START" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-start\fR \-\- Start a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-STOP" "1" "January 2013" "" ""
+.TH "NPM\-STOP" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-stop\fR \-\- Stop a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SUBMODULE" "1" "January 2013" "" ""
+.TH "NPM\-SUBMODULE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-submodule\fR \-\- Add a package as a git submodule
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-TAG" "1" "January 2013" "" ""
+.TH "NPM\-TAG" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-tag\fR \-\- Tag a published version
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-TEST" "1" "January 2013" "" ""
+.TH "NPM\-TEST" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-test\fR \-\- Test a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-RM" "1" "January 2013" "" ""
+.TH "NPM\-RM" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-rm\fR \-\- Remove a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-UNPUBLISH" "1" "January 2013" "" ""
+.TH "NPM\-UNPUBLISH" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-unpublish\fR \-\- Remove a package from the registry
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-UPDATE" "1" "January 2013" "" ""
+.TH "NPM\-UPDATE" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-update\fR \-\- Update a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-VERSION" "1" "January 2013" "" ""
+.TH "NPM\-VERSION" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-version\fR \-\- Bump a package version
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-VIEW" "1" "January 2013" "" ""
+.TH "NPM\-VIEW" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-view\fR \-\- View registry info
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-WHOAMI" "1" "January 2013" "" ""
+.TH "NPM\-WHOAMI" "1" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-whoami\fR \-\- Display npm username
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-BIN" "3" "January 2013" "" ""
+.TH "NPM\-BIN" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-bin\fR \-\- Display npm bin folder
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-BUGS" "3" "January 2013" "" ""
+.TH "NPM\-BUGS" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-bugs\fR \-\- Bugs for a package in a web browser maybe
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-COMMANDS" "3" "January 2013" "" ""
+.TH "NPM\-COMMANDS" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-commands\fR \-\- npm commands
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-CONFIG" "3" "January 2013" "" ""
+.TH "NPM\-CONFIG" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-config\fR \-\- Manage the npm configuration files
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-DEPRECATE" "3" "January 2013" "" ""
+.TH "NPM\-DEPRECATE" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-deprecate\fR \-\- Deprecate a version of a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-DOCS" "3" "January 2013" "" ""
+.TH "NPM\-DOCS" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-docs\fR \-\- Docs for a package in a web browser maybe
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-EDIT" "3" "January 2013" "" ""
+.TH "NPM\-EDIT" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-edit\fR \-\- Edit an installed package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-EXPLORE" "3" "January 2013" "" ""
+.TH "NPM\-EXPLORE" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-explore\fR \-\- Browse an installed package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-HELP\-SEARCH" "3" "January 2013" "" ""
+.TH "NPM\-HELP\-SEARCH" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-help-search\fR \-\- Search the help pages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "INIT" "3" "January 2013" "" ""
+.TH "INIT" "3" "February 2013" "" ""
.
.SH "NAME"
\fBinit\fR \-\- Interactively create a package\.json file
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-INSTALL" "3" "January 2013" "" ""
+.TH "NPM\-INSTALL" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-install\fR \-\- install a package programmatically
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-LINK" "3" "January 2013" "" ""
+.TH "NPM\-LINK" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-link\fR \-\- Symlink a package folder
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-LOAD" "3" "January 2013" "" ""
+.TH "NPM\-LOAD" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-load\fR \-\- Load config settings
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-LS" "3" "January 2013" "" ""
+.TH "NPM\-LS" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-ls\fR \-\- List installed packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM" "3" "January 2013" "" ""
+.TH "NPM" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm\fR \-\- node package manager
.
.nf
var npm = require("npm")
-npm\.load(configObject, function (er, npm) {
+npm\.load([configObject,] function (er, npm) {
// use the npm object, now that it\'s loaded\.
npm\.config\.set(key, val)
val = npm\.config\.get(key)
.fi
.
.SH "VERSION"
-1.2.2
+1.2.10
.
.SH "DESCRIPTION"
This is the API documentation for npm\.
client, see \fBnpm help npm\fR\|\.
.
.P
-Prior to using npm\'s commands, \fBnpm\.load()\fR must be called with an object hash of
-top\-level configs\. In the npm command line client,
-this set of configs is parsed from the command line options\. Additional
-configuration params are loaded from two configuration files\. See \fBnpm help config\fR for more information\.
+Prior to using npm\'s commands, \fBnpm\.load()\fR must be called\.
+If you provide \fBconfigObject\fR as an object hash of top\-level
+configs, they override the values stored in the various config
+locations\. In the npm command line client, this set of configs
+is parsed from the command line options\. Additional configuration
+params are loaded from two configuration files\. See \fBnpm help config\fR
+for more information\.
.
.P
After that, each of the functions are accessible in the
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-OUTDATED" "3" "January 2013" "" ""
+.TH "NPM\-OUTDATED" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-outdated\fR \-\- Check for outdated packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-OWNER" "3" "January 2013" "" ""
+.TH "NPM\-OWNER" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-owner\fR \-\- Manage package owners
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PACK" "3" "January 2013" "" ""
+.TH "NPM\-PACK" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-pack\fR \-\- Create a tarball from a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PREFIX" "3" "January 2013" "" ""
+.TH "NPM\-PREFIX" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-prefix\fR \-\- Display prefix
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PRUNE" "3" "January 2013" "" ""
+.TH "NPM\-PRUNE" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-prune\fR \-\- Remove extraneous packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-PUBLISH" "3" "January 2013" "" ""
+.TH "NPM\-PUBLISH" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-publish\fR \-\- Publish a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-REBUILD" "3" "January 2013" "" ""
+.TH "NPM\-REBUILD" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-rebuild\fR \-\- Rebuild a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-RESTART" "3" "January 2013" "" ""
+.TH "NPM\-RESTART" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-restart\fR \-\- Start a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-ROOT" "3" "January 2013" "" ""
+.TH "NPM\-ROOT" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-root\fR \-\- Display npm root
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-RUN\-SCRIPT" "3" "January 2013" "" ""
+.TH "NPM\-RUN\-SCRIPT" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-run-script\fR \-\- Run arbitrary package scripts
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SEARCH" "3" "January 2013" "" ""
+.TH "NPM\-SEARCH" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-search\fR \-\- Search for packages
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SHRINKWRAP" "3" "January 2013" "" ""
+.TH "NPM\-SHRINKWRAP" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-shrinkwrap\fR \-\- programmatically generate package shrinkwrap file
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-START" "3" "January 2013" "" ""
+.TH "NPM\-START" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-start\fR \-\- Start a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-STOP" "3" "January 2013" "" ""
+.TH "NPM\-STOP" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-stop\fR \-\- Stop a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-SUBMODULE" "3" "January 2013" "" ""
+.TH "NPM\-SUBMODULE" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-submodule\fR \-\- Add a package as a git submodule
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-TAG" "3" "January 2013" "" ""
+.TH "NPM\-TAG" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-tag\fR \-\- Tag a published version
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-TEST" "3" "January 2013" "" ""
+.TH "NPM\-TEST" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-test\fR \-\- Test a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-UNINSTALL" "3" "January 2013" "" ""
+.TH "NPM\-UNINSTALL" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-uninstall\fR \-\- uninstall a package programmatically
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-UNPUBLISH" "3" "January 2013" "" ""
+.TH "NPM\-UNPUBLISH" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-unpublish\fR \-\- Remove a package from the registry
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-UPDATE" "3" "January 2013" "" ""
+.TH "NPM\-UPDATE" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-update\fR \-\- Update a package
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-VERSION" "3" "January 2013" "" ""
+.TH "NPM\-VERSION" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-version\fR \-\- Bump a package version
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-VIEW" "3" "January 2013" "" ""
+.TH "NPM\-VIEW" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-view\fR \-\- View registry info
.\" Generated with Ronnjs 0.3.8
.\" http://github.com/kapouer/ronnjs/
.
-.TH "NPM\-WHOAMI" "3" "January 2013" "" ""
+.TH "NPM\-WHOAMI" "3" "February 2013" "" ""
.
.SH "NAME"
\fBnpm-whoami\fR \-\- Display npm username
},
"name": "fstream",
"description": "Advanced file system stream things",
- "version": "0.1.21",
+ "version": "0.1.22",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/fstream.git"
"dependencies": {
"rimraf": "2",
"mkdirp": "0.3",
- "graceful-fs": "~1.1.2",
+ "graceful-fs": "~1.2.0",
"inherits": "~1.0.0"
},
"devDependencies": {
"license": "BSD",
"readme": "Like FS streams, but with stat on them, and supporting directories and\nsymbolic links, as well as normal files. Also, you can use this to set\nthe stats on a file, even if you don't change its contents, or to create\na symlink, etc.\n\nSo, for example, you can \"write\" a directory, and it'll call `mkdir`. You\ncan specify a uid and gid, and it'll call `chown`. You can specify a\n`mtime` and `atime`, and it'll call `utimes`. You can call it a symlink\nand provide a `linkpath` and it'll call `symlink`.\n\nNote that it won't automatically resolve symbolic links. So, if you\ncall `fstream.Reader('/some/symlink')` then you'll get an object\nthat stats and then ends immediately (since it has no data). To follow\nsymbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:\ntrue })`.\n\nThere are various checks to make sure that the bytes emitted are the\nsame as the intended size, if the size is set.\n\n## Examples\n\n```javascript\nfstream\n .Writer({ path: \"path/to/file\"\n , mode: 0755\n , size: 6\n })\n .write(\"hello\\n\")\n .end()\n```\n\nThis will create the directories if they're missing, and then write\n`hello\\n` into the file, chmod it to 0755, and assert that 6 bytes have\nbeen written when it's done.\n\n```javascript\nfstream\n .Writer({ path: \"path/to/file\"\n , mode: 0755\n , size: 6\n , flags: \"a\"\n })\n .write(\"hello\\n\")\n .end()\n```\n\nYou can pass flags in, if you want to append to a file.\n\n```javascript\nfstream\n .Writer({ path: \"path/to/symlink\"\n , linkpath: \"./file\"\n , SymbolicLink: true\n , mode: \"0755\" // octal strings supported\n })\n .end()\n```\n\nIf isSymbolicLink is a function, it'll be called, and if it returns\ntrue, then it'll treat it as a symlink. If it's not a function, then\nany truish value will make a symlink, or you can set `type:\n'SymbolicLink'`, which does the same thing.\n\nNote that the linkpath is relative to the symbolic link location, not\nthe parent dir or cwd.\n\n```javascript\nfstream\n .Reader(\"path/to/dir\")\n .pipe(fstream.Writer(\"path/to/other/dir\"))\n```\n\nThis will do like `cp -Rp path/to/dir path/to/other/dir`. If the other\ndir exists and isn't a directory, then it'll emit an error. It'll also\nset the uid, gid, mode, etc. to be identical. In this way, it's more\nlike `rsync -a` than simply a copy.\n",
"readmeFilename": "README.md",
- "_id": "fstream@0.1.21",
+ "_id": "fstream@0.1.22",
"_from": "fstream@latest"
}
//
// else // not globstar
// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
-// Test ENTRY against pattern[n+1]
+// Test ENTRY against pattern[n]
// If fails, continue
// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
//
if (typeof cb === "function") {
this.on("error", cb)
this.on("end", function (matches) {
- // console.error("cb with matches", matches)
cb(null, matches)
})
}
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
pattern = "**/" + pattern
}
+ this.strict = options.strict !== false
this.dot = !!options.dot
this.mark = !!options.mark
this.sync = !!options.sync
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)
}
}
+Glob.prototype.log = function () {}
+
Glob.prototype._finish = function () {
assert(this instanceof Glob)
for (var i = 0, l = this.matches.length; i < l; i ++) {
var matches = this.matches[i]
- if (this.debug) console.error("matches[%d] =", i, matches)
+ this.log("matches[%d] =", i, matches)
// do like the shell, and spit out the literal glob
if (!matches) {
if (this.nonull) {
}, this)
}
- if (this.debug) console.error("emitting end", all)
+ this.log("emitting end", all)
this.EOF = this.found = all
this.emitMatch(this.EOF)
this._processingEmitQueue = false
break
}
- if (this.debug) {
- console.error('emit!', m === this.EOF ? "end" : "match")
- }
+
+ this.log('emit!', m === this.EOF ? "end" : "match")
+
this.emit(m === this.EOF ? "end" : "match", m)
this._processingEmitQueue = false
}
// either it's there, or it isn't.
// nothing more to do, either way.
if (exists) {
- if (prefix.charAt(0) === "/" && !this.nomount) {
- prefix = path.join(this.root, prefix)
+ if (prefix && isAbsolute(prefix) && !this.nomount) {
+ if (prefix.charAt(0) === "/") {
+ console.error('JOIN 0', this.root, prefix)
+ prefix = path.join(this.root, prefix)
+ console.error('JOIN 1', 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)
// get the list of entries.
var read
if (prefix === null) read = "."
- else if (isAbsolute(prefix)) {
- read = prefix = path.resolve("/", prefix)
- if (this.debug) console.error('absolute: ', prefix, this.root, pattern)
- } else read = prefix
+ else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) {
+ if (!prefix || !isAbsolute(prefix)) {
+ console.error('JOIN 1', "/", prefix)
+ prefix = path.join("/", prefix)
+ console.error('JOIN 2', "/", 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)
- if (this.debug) console.error('readdir(%j)', read, this.cwd, this.root)
return this._readdir(read, function (er, entries) {
if (er) {
// not a directory!
else e = prefix + e
}
if (e.charAt(0) === "/" && !this.nomount) {
+ console.error('JOIN 3', this.root, e)
e = path.join(this.root, e)
+ console.error('JOIN 4', 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)
assert(this instanceof Glob)
var abs = f
if (f.charAt(0) === "/") {
+ console.error('JOIN 5', this.root, f)
abs = path.join(this.root, f)
+ console.error('JOIN 6', this.root, f)
} else if (this.changedCwd) {
abs = path.resolve(this.cwd, f)
}
- if (this.debug) console.error('stat', [this.cwd, f, '=', abs])
+ this.log('stat', [this.cwd, f, '=', abs])
if (f.length > this.maxLength) {
var er = new Error("Path name too long")
er.code = "ENAMETOOLONG"
Glob.prototype._afterStat = function (f, abs, cb, er, stat) {
var exists
assert(this instanceof Glob)
+
+ if (abs.slice(-1) === "/" && stat && !stat.isDirectory()) {
+ this.log("should be ENOTDIR, fake it")
+
+ er = new Error("ENOTDIR, not a directory '" + abs + "'")
+ er.path = abs
+ er.code = "ENOTDIR"
+ stat = null
+ }
+
if (er || !stat) {
exists = false
} else {
assert(this instanceof Glob)
var abs = f
if (f.charAt(0) === "/") {
+ console.error('JOIN 5', this.root, f)
abs = path.join(this.root, f)
+ console.error('JOIN 5', abs)
} else if (isAbsolute(f)) {
abs = f
} else if (this.changedCwd) {
abs = path.resolve(this.cwd, f)
}
- if (this.debug) console.error('readdir', [this.cwd, f, abs])
+ this.log('readdir', [this.cwd, f, abs])
if (f.length > this.maxLength) {
var er = new Error("Path name too long")
er.code = "ENAMETOOLONG"
, er = new Error((c ? "Not a directory" : "Not found") + ": " + f)
er.path = f
er.code = code
- if (this.debug) console.error(f, er)
+ this.log(f, er)
if (this.sync) return cb.call(this, er)
return process.nextTick(cb.bind(this, er))
}
// pull off the device/UNC bit from a windows path.
// from node's lib/path.js
var splitDeviceRe =
- /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
+ /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/
, result = splitDeviceRe.exec(p)
, device = result[1] || ''
, isUnc = device && device.charAt(1) !== ':'
},
"name": "glob",
"description": "a little globber",
- "version": "3.1.14",
+ "version": "3.1.19",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-glob.git"
},
"dependencies": {
"minimatch": "0.2",
- "graceful-fs": "~1.1.2",
+ "graceful-fs": "~1.2.0",
"inherits": "1"
},
"devDependencies": {
- "tap": "~0.3",
+ "tap": "~0.4.0",
"mkdirp": "0",
"rimraf": "1"
},
"license": "BSD",
"readme": "# Glob\n\nThis is a glob implementation in JavaScript. It uses the `minimatch`\nlibrary to do its matching.\n\n## Attention: node-glob users!\n\nThe API has changed dramatically between 2.x and 3.x. This library is\nnow 100% JavaScript, and the integer flags have been replaced with an\noptions object.\n\nAlso, there's an event emitter class, proper tests, and all the other\nthings you've come to expect from node modules.\n\nAnd best of all, no compilation!\n\n## Usage\n\n```javascript\nvar glob = require(\"glob\")\n\n// options is optional\nglob(\"**/*.js\", options, function (er, files) {\n // files is an array of filenames.\n // If the `nonull` option is set, and nothing\n // was found, then files is [\"**/*.js\"]\n // er is an error object or null.\n})\n```\n\n## Features\n\nPlease see the [minimatch\ndocumentation](https://github.com/isaacs/minimatch) for more details.\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n* [minimatch documentation](https://github.com/isaacs/minimatch)\n\n## glob(pattern, [options], cb)\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* `cb` {Function}\n * `err` {Error | null}\n * `matches` {Array<String>} filenames found matching the pattern\n\nPerform an asynchronous glob search.\n\n## glob.sync(pattern, [options]\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* return: {Array<String>} filenames found matching the pattern\n\nPerform a synchronous glob search.\n\n## Class: glob.Glob\n\nCreate a Glob object by instanting the `glob.Glob` class.\n\n```javascript\nvar Glob = require(\"glob\").Glob\nvar mg = new Glob(pattern, options, cb)\n```\n\nIt's an EventEmitter, and starts walking the filesystem to find matches\nimmediately.\n\n### new glob.Glob(pattern, [options], [cb])\n\n* `pattern` {String} pattern to search for\n* `options` {Object}\n* `cb` {Function} Called when an error occurs, or matches are found\n * `err` {Error | null}\n * `matches` {Array<String>} filenames found matching the pattern\n\nNote that if the `sync` flag is set in the options, then matches will\nbe immediately available on the `g.found` member.\n\n### Properties\n\n* `minimatch` The minimatch object that the glob uses.\n* `options` The options object passed in.\n* `error` The error encountered. When an error is encountered, the\n glob object is in an undefined state, and should be discarded.\n* `aborted` Boolean which is set to true when calling `abort()`. There\n is no way at this time to continue a glob search after aborting, but\n you can re-use the statCache to avoid having to duplicate syscalls.\n\n### Events\n\n* `end` When the matching is finished, this is emitted with all the\n matches found. If the `nonull` option is set, and no match was found,\n then the `matches` list contains the original pattern. The matches\n are sorted, unless the `nosort` flag is set.\n* `match` Every time a match is found, this is emitted with the matched.\n* `error` Emitted when an unexpected error is encountered, or whenever\n any fs error occurs if `options.strict` is set.\n* `abort` When `abort()` is called, this event is raised.\n\n### Methods\n\n* `abort` Stop the search.\n\n### Options\n\nAll the options that can be passed to Minimatch can also be passed to\nGlob to change pattern matching behavior. Also, some have been added,\nor have glob-specific ramifications.\n\nAll options are false by default, unless otherwise noted.\n\nAll options are added to the glob object, as well.\n\n* `cwd` The current working directory in which to search. Defaults\n to `process.cwd()`.\n* `root` The place where patterns starting with `/` will be mounted\n onto. Defaults to `path.resolve(options.cwd, \"/\")` (`/` on Unix\n systems, and `C:\\` or some such on Windows.)\n* `nomount` By default, a pattern starting with a forward-slash will be\n \"mounted\" onto the root setting, so that a valid filesystem path is\n returned. Set this flag to disable that behavior.\n* `mark` Add a `/` character to directory matches. Note that this\n requires additional stat calls.\n* `nosort` Don't sort the results.\n* `stat` Set to true to stat *all* results. This reduces performance\n somewhat, and is completely unnecessary, unless `readdir` is presumed\n to be an untrustworthy indicator of file existence. It will cause\n ELOOP to be triggered one level sooner in the case of cyclical\n symbolic links.\n* `silent` When an unusual error is encountered\n when attempting to read a directory, a warning will be printed to\n stderr. Set the `silent` option to true to suppress these warnings.\n* `strict` When an unusual error is encountered\n when attempting to read a directory, the process will just continue on\n in search of other matches. Set the `strict` option to raise an error\n in these cases.\n* `statCache` A cache of results of filesystem information, to prevent\n unnecessary stat calls. While it should not normally be necessary to\n set this, you may pass the statCache from one glob() call to the\n options object of another, if you know that the filesystem will not\n change between calls. (See \"Race Conditions\" below.)\n* `sync` Perform a synchronous glob search.\n* `nounique` In some cases, brace-expanded patterns can result in the\n same file showing up multiple times in the result set. By default,\n this implementation prevents duplicates in the result set.\n Set this flag to disable that behavior.\n* `nonull` Set to never return an empty set, instead returning a set\n containing the pattern itself. This is the default in glob(3).\n* `nocase` Perform a case-insensitive match. Note that case-insensitive\n filesystems will sometimes result in glob returning results that are\n case-insensitively matched anyway, since readdir and stat will not\n raise an error.\n* `debug` Set to enable debug logging in minimatch and glob.\n* `globDebug` Set to enable debug logging in glob, but not minimatch.\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between node-glob and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not. **Note that this is different from the way that `**` is\nhandled by ruby's `Dir` class.**\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen glob returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`glob.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n## Windows\n\n**Please only use forward-slashes in glob expressions.**\n\nThough windows uses either `/` or `\\` as its path separator, only `/`\ncharacters are used by this glob implementation. You must use\nforward-slashes **only** in glob expressions. Back-slashes will always\nbe interpreted as escape characters, not path separators.\n\nResults from absolute patterns such as `/foo/*` are mounted onto the\nroot setting using `path.join`. On windows, this will by default result\nin `/foo/*` matching `C:\\foo\\bar.txt`.\n\n## Race Conditions\n\nGlob searching, by its very nature, is susceptible to race conditions,\nsince it relies on directory walking and such.\n\nAs a result, it is possible that a file that exists when glob looks for\nit may have been deleted or modified by the time it returns the result.\n\nAs part of its internal implementation, this program caches all stat\nand readdir calls that it makes, in order to cut down on system\noverhead. However, this also makes it even more susceptible to races,\nespecially if the statCache object is reused between glob calls.\n\nUsers are thus advised not to use a glob result as a\nguarantee of filesystem state in the face of rapid changes.\nFor the vast majority of operations, this is never a problem.\n",
"readmeFilename": "README.md",
- "_id": "glob@3.1.14",
- "dist": {
- "shasum": "f97a731c41da6695dc83944bbb2177e9a29b363d"
- },
- "_from": "glob@3.1.14"
+ "_id": "glob@3.1.19",
+ "_from": "glob@~3.1.18"
}
})
})
-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, function (er) {
- t.ifError(er, "make symlink")
+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
+}
// show that it does the same thing by default as the shell.
var tap = require("tap")
, child_process = require("child_process")
-
-// put more patterns here.
-, globs =
- ["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/**"
- ,"{./*/*,/usr/local/*}"
- ,"{/*,*}" // evil owl face! how you taunt me!
- ]
+, bashResults = require("./bash-results.json")
+, globs = Object.keys(bashResults)
, glob = require("../")
, path = require("path")
}
globs.forEach(function (pattern) {
- var echoOutput
- tap.test(pattern, function (t) {
- var bashPattern = pattern
- , cmd = "shopt -s globstar && " +
- "shopt -s extglob && " +
- "shopt -s nullglob && " +
- // "shopt >&2; " +
- "eval \'for i in " + bashPattern + "; do echo $i; done\'"
- , cp = child_process.spawn("bash", ["-c",cmd])
- , out = []
- , globResult
- cp.stdout.on("data", function (c) {
- out.push(c)
- })
- cp.stderr.on("data", function (c) {
- process.stderr.write(c)
- })
- cp.on("close", function () {
- echoOutput = flatten(out)
- if (!echoOutput) echoOutput = []
- else {
- echoOutput = echoOutput.split(/\r*\n/).map(function (m) {
- // Bash is a oddly inconsistent with slashes in the
- // the results. This implementation is a bit more
- // normalized. Account for this in the test results.
- return m.replace(/\/+/g, "/").replace(/\/$/, "")
- }).sort(alphasort).reduce(function (set, f) {
- if (f !== set[set.length - 1]) set.push(f)
- return set
- }, []).sort(alphasort)
- }
- next()
- })
+ 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) {
- // sort and unpark, just to match the shell results
- matches = matches.map(function (m) {
- return m.replace(/\/+/g, "/").replace(/\/$/, "")
- }).sort(alphasort).reduce(function (set, f) {
- if (f !== set[set.length - 1]) set.push(f)
- return set
- }, []).sort(alphasort)
-
- t.ifError(er, pattern + " should not error")
- globResult = matches
- next()
- })
+ if (er)
+ throw er
- function next () {
- if (!echoOutput || !globResult) return
+ // sort and unmark, just to match the shell results
+ matches = cleanResults(matches)
- t.deepEqual(globResult, echoOutput, "should match shell")
+ t.deepEqual(matches, expect, pattern)
t.end()
- }
+ })
})
tap.test(pattern + " sync", function (t) {
- var matches = glob.sync(pattern).map(function (m) {
- return m.replace(/\/+/g, "/").replace(/\/$/, "")
- }).sort(alphasort).reduce(function (set, f) {
- if (f !== set[set.length - 1]) set.push(f)
- return set
- }, []).sort(alphasort)
+ var matches = cleanResults(glob.sync(pattern))
- t.deepEqual(matches, echoOutput, "should match shell")
+ t.deepEqual(matches, expect, "should match shell")
t.end()
})
})
-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
+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, '/')
})
-
- return out.toString().trim()
}
--- /dev/null
+{
+ "test/a/*/+(c|g)/./d": [
+ "test/a/b/c/./d"
+ ],
+ "test/a/**/[cg]/../[cg]": [
+ "test/a/abcdef/g/../g",
+ "test/a/abcfed/g/../g",
+ "test/a/b/c/../c",
+ "test/a/c/../c",
+ "test/a/c/d/c/../c",
+ "test/a/symlink/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/../c"
+ ],
+ "test/a/{b,c,d,e,f}/**/g": [],
+ "test/a/b/**": [
+ "test/a/b",
+ "test/a/b/c",
+ "test/a/b/c/d"
+ ],
+ "test/**/g": [
+ "test/a/abcdef/g",
+ "test/a/abcfed/g"
+ ],
+ "test/a/abc{fed,def}/g/h": [
+ "test/a/abcdef/g/h",
+ "test/a/abcfed/g/h"
+ ],
+ "test/a/abc{fed/g,def}/**/": [
+ "test/a/abcdef",
+ "test/a/abcdef/g",
+ "test/a/abcfed/g"
+ ],
+ "test/a/abc{fed/g,def}/**///**/": [
+ "test/a/abcdef",
+ "test/a/abcdef/g",
+ "test/a/abcfed/g"
+ ],
+ "test/**/a/**/": [
+ "test/a",
+ "test/a/abcdef",
+ "test/a/abcdef/g",
+ "test/a/abcfed",
+ "test/a/abcfed/g",
+ "test/a/b",
+ "test/a/b/c",
+ "test/a/bc",
+ "test/a/bc/e",
+ "test/a/c",
+ "test/a/c/d",
+ "test/a/c/d/c",
+ "test/a/cb",
+ "test/a/cb/e",
+ "test/a/symlink",
+ "test/a/symlink/a",
+ "test/a/symlink/a/b",
+ "test/a/symlink/a/b/c",
+ "test/a/symlink/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b"
+ ],
+ "test/+(a|b|c)/a{/,bc*}/**": [
+ "test/a/abcdef",
+ "test/a/abcdef/g",
+ "test/a/abcdef/g/h",
+ "test/a/abcfed",
+ "test/a/abcfed/g",
+ "test/a/abcfed/g/h"
+ ],
+ "test/*/*/*/f": [
+ "test/a/bc/e/f",
+ "test/a/cb/e/f"
+ ],
+ "test/**/f": [
+ "test/a/bc/e/f",
+ "test/a/cb/e/f"
+ ],
+ "test/a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**": [
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b",
+ "test/a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c"
+ ],
+ "{./*/*,/tmp/glob-test/*}": [
+ "./examples/g.js",
+ "./examples/usr-local.js",
+ "./node_modules/graceful-fs",
+ "./node_modules/inherits",
+ "./node_modules/minimatch",
+ "./node_modules/mkdirp",
+ "./node_modules/rimraf",
+ "./node_modules/tap",
+ "./test/00-setup.js",
+ "./test/a",
+ "./test/bash-comparison.js",
+ "./test/bash-results.json",
+ "./test/cwd-test.js",
+ "./test/mark.js",
+ "./test/pause-resume.js",
+ "./test/root-nomount.js",
+ "./test/root.js",
+ "./test/zz-cleanup.js",
+ "/tmp/glob-test/asdf",
+ "/tmp/glob-test/bar",
+ "/tmp/glob-test/baz",
+ "/tmp/glob-test/foo",
+ "/tmp/glob-test/quux",
+ "/tmp/glob-test/qwer",
+ "/tmp/glob-test/rewq"
+ ],
+ "{/tmp/glob-test/*,*}": [
+ "/tmp/glob-test/asdf",
+ "/tmp/glob-test/bar",
+ "/tmp/glob-test/baz",
+ "/tmp/glob-test/foo",
+ "/tmp/glob-test/quux",
+ "/tmp/glob-test/qwer",
+ "/tmp/glob-test/rewq",
+ "examples",
+ "glob.js",
+ "LICENSE",
+ "node_modules",
+ "package.json",
+ "README.md",
+ "test"
+ ],
+ "test/a/!(symlink)/**": [
+ "test/a/abcdef",
+ "test/a/abcdef/g",
+ "test/a/abcdef/g/h",
+ "test/a/abcfed",
+ "test/a/abcfed/g",
+ "test/a/abcfed/g/h",
+ "test/a/b",
+ "test/a/b/c",
+ "test/a/b/c/d",
+ "test/a/bc",
+ "test/a/bc/e",
+ "test/a/bc/e/f",
+ "test/a/c",
+ "test/a/c/d",
+ "test/a/c/d/c",
+ "test/a/c/d/c/b",
+ "test/a/cb",
+ "test/a/cb/e",
+ "test/a/cb/e/f"
+ ]
+}
glob("a/*", {mark: true}, function (er, results) {
if (er)
throw er
- t.same(results, [ 'a/abcdef/',
- 'a/abcfed/',
- 'a/b/',
- 'a/bc/',
- 'a/c/',
- 'a/cb/',
- 'a/symlink/' ])
+ 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()
})
})
glob("a/*", function (er, results) {
if (er)
throw er
- t.same(results, [ 'a/abcdef',
- 'a/abcfed',
- 'a/b',
- 'a/bc',
- 'a/c',
- 'a/cb',
- 'a/symlink' ])
+ 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()
})
})
glob("a/*/", {mark: true}, function (er, results) {
if (er)
throw er
- t.same(results, [ 'a/abcdef/',
- 'a/abcfed/',
- 'a/b/',
- 'a/bc/',
- 'a/c/',
- 'a/cb/',
- 'a/symlink/' ])
+ 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()
})
})
glob("a/*/", function (er, results) {
if (er)
throw er
- t.same(results, [ 'a/abcdef/',
- 'a/abcfed/',
- 'a/b/',
- 'a/bc/',
- 'a/c/',
- 'a/cb/',
- 'a/symlink/' ])
+ 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()
})
})
, 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")
}).sort(alphasort).reduce(function (set, f) {
if (f !== set[set.length - 1]) set.push(f)
return set
- }, []).sort(alphasort)
-}
-
-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
+ }, []).sort(alphasort).map(function (f) {
+ // de-windows
+ return (process.platform !== 'win32') ? f
+ : f.replace(/^[a-zA-Z]:\\\\/, '/').replace(/\\/g, '/')
})
-
- return out.toString().trim()
}
-var bashResults
-tap.test("get bash output", function (t) {
- var bashPattern = pattern
- , cmd = "shopt -s globstar && " +
- "shopt -s extglob && " +
- "shopt -s nullglob && " +
- // "shopt >&2; " +
- "eval \'for i in " + bashPattern + "; do echo $i; done\'"
- , cp = child_process.spawn("bash", ["-c",cmd])
- , out = []
- , globResult
- cp.stdout.on("data", function (c) {
- out.push(c)
- })
- cp.stderr.on("data", function (c) {
- process.stderr.write(c)
- })
- cp.on("close", function () {
- bashResults = flatten(out)
- if (!bashResults) return t.fail("Didn't get results from bash")
- else {
- bashResults = cleanResults(bashResults.split(/\r*\n/))
- }
- t.ok(bashResults.length, "got some results")
- t.end()
- })
-})
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")
t.deepEqual(matches, globResults,
"end event matches should be the same as match events")
- t.deepEqual(matches, bashResults,
+ t.deepEqual(matches, expect,
"glob matches should be the same as bash results")
t.end()
-var tap = require("tap")
+var t = 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: '.' }, function (er, matches) {
- t.ifError(er)
- t.like(matches, [])
- t.end()
- })
- })
+var glob = require('../')
+var path = require('path')
- t.test('a', function (t) {
- glob('/b*/**', { globDebug: true, root: path.resolve('a') }, function (er, matches) {
- t.ifError(er)
- t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
- return path.join(path.resolve('a'), m)
- }))
- t.end()
- })
+t.test('.', function (t) {
+ glob('/b*/**', { globDebug: true, root: '.' }, function (er, matches) {
+ t.ifError(er)
+ t.like(matches, [])
+ t.end()
})
+})
+
- t.test('root=a, cwd=a/b', function (t) {
- glob('/b*/**', { globDebug: true, root: 'a', cwd: path.resolve('a/b') }, function (er, matches) {
- t.ifError(er)
- t.like(matches, [ '/b', '/b/c', '/b/c/d', '/bc', '/bc/e', '/bc/e/f' ].map(function (m) {
- return path.join(path.resolve('a'), m)
- }))
- t.end()
- })
+t.test('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('cd -', function (t) {
- process.chdir(origCwd)
+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()
})
// this keeps a queue of opened file descriptors, and will make
// fs operations wait until some have closed before trying to open more.
-var fs = require("fs")
+var fs_ = require("fs")
-// there is such a thing as TOO graceful.
-if (fs.open === gracefulOpen) return
+var fs = module.exports = {}
+
+Object.getOwnPropertyNames(fs_).forEach(function(prop) {
+ var desc = Object.getOwnPropertyDescriptor(fs_, prop)
+ Object.defineProperty(fs, prop, desc)
+})
var queue = []
, constants = require("constants")
},
"name": "graceful-fs",
"description": "fs monkey-patching to avoid EMFILE and other problems",
- "version": "1.1.14",
+ "version": "1.2.0",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-graceful-fs.git"
],
"license": "BSD",
"readme": "Just like node's `fs` module, but it does an incremental back-off when\nEMFILE is encountered.\n\nUseful in asynchronous situations where one needs to try to open lots\nand lots of files.\n",
- "_id": "graceful-fs@1.1.14",
- "_from": "graceful-fs@~1.1.1"
+ "readmeFilename": "README.md",
+ "_id": "graceful-fs@1.2.0",
+ "_from": "graceful-fs@latest"
}
var test = require('tap').test
var fs = require('../graceful-fs.js')
+test('graceful fs is not fs', function (t) {
+ t.notEqual(fs, require('fs'))
+ t.end()
+})
+
test('open an existing file works', function (t) {
var start = fs._curOpen
var fd = fs.openSync(__filename, 'r')
[paths.default]
datadir = /var/lib/data
+ array[] = first value
+ array[] = second value
+ array[] = third value
You can read, manipulate and write the ini-file like so:
config.database.database = 'use_another_database'
config.paths.default.tmpdir = '/tmp'
delete config.paths.default.datadir
+ config.paths.default.array.push('fourth value')
fs.writeFileSync('./config_modified.ini', ini.stringify(config, 'section'))
database = use_another_database
[section.paths.default]
tmpdir = /tmp
+ array[] = first value
+ array[] = second value
+ array[] = third value
+ array[] = fourth value
+
## API
### unsafe(val)
Unescapes the string `val`
-
Object.keys(obj).forEach(function (k, _, __) {
var val = obj[k]
- if (val && typeof val === "object") {
+ if (val && Array.isArray(val)) {
+ val.forEach(function(item) {
+ out += safe(k + "[]") + " = " + safe(item) + "\n"
+ })
+ }
+ else if (val && typeof val === "object") {
children.push(k)
} else {
out += safe(k) + " = " + safe(val) + eol
case 'false':
case 'null': value = JSON.parse(value)
}
- p[key] = value
+
+ // Convert keys with '[]' suffix to an array
+ if (key.length > 2 && key.slice(-2) === "[]") {
+ key = key.substring(0, key.length - 2)
+ if (!p[key]) {
+ p[key] = []
+ }
+ else if (!Array.isArray(p[key])) {
+ p[key] = [p[key]]
+ }
+ }
+
+ // safeguard against resetting a previously defined
+ // array by accidentally forgetting the brackets
+ if (Array.isArray(p[key])) {
+ p[key].push(value)
+ }
+ else {
+ p[key] = value
+ }
})
// {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
// use a filter to return the keys that have to be deleted.
Object.keys(out).filter(function (k, _, __) {
- if (!out[k] || typeof out[k] !== "object") return false
+ if (!out[k] || typeof out[k] !== "object" || Array.isArray(out[k])) return false
// see if the parent section is also an object.
// if so, add it to that, and mark this one for deletion
var parts = dotSplit(k)
},
"name": "ini",
"description": "An ini encoder/decoder for node",
- "version": "1.0.5",
+ "version": "1.1.0",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/ini.git"
"devDependencies": {
"tap": "~0.0.9"
},
- "readme": "An ini format parser and serializer for node.\n\nSections are treated as nested objects. Items before the first heading\nare saved on the object directly.\n\n## Usage\n\nConsider an ini-file `config.ini` that looks like this:\n\n ; this comment is being ignored\n scope = global\n\n [database]\n user = dbuser\n password = dbpassword\n database = use_this_database\n\n [paths.default]\n datadir = /var/lib/data\n\nYou can read, manipulate and write the ini-file like so:\n\n var fs = require('fs')\n , ini = require('ini')\n\n var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'))\n\n config.scope = 'local'\n config.database.database = 'use_another_database'\n config.paths.default.tmpdir = '/tmp'\n delete config.paths.default.datadir\n\n fs.writeFileSync('./config_modified.ini', ini.stringify(config, 'section'))\n\nThis will result in a file called `config_modified.ini` being written to the filesystem with the following content:\n\n [section]\n scope = local\n [section.database]\n user = dbuser\n password = dbpassword\n database = use_another_database\n [section.paths.default]\n tmpdir = /tmp\n\n## API\n\n### decode(inistring)\nDecode the ini-style formatted `inistring` into a nested object.\n\n### parse(inistring)\nAlias for `decode(inistring)`\n\n### encode(object, [section])\nEncode the object `object` into an ini-style formatted string. If the optional parameter `section` is given, then all top-level properties of the object are put into this section and the `section`-string is prepended to all sub-sections, see the usage example above.\n\n### stringify(object, [section])\nAlias for `encode(object, [section])`\n\n### safe(val)\nEscapes the string `val` such that it is safe to be used as a key or value in an ini-file. Basically escapes quotes. For example\n\n ini.safe('\"unsafe string\"')\n\nwould result in\n\n \"\\\"unsafe string\\\"\"\n\n### unsafe(val)\nUnescapes the string `val`\n\n",
- "_id": "ini@1.0.5",
+ "readme": "An ini format parser and serializer for node.\n\nSections are treated as nested objects. Items before the first heading\nare saved on the object directly.\n\n## Usage\n\nConsider an ini-file `config.ini` that looks like this:\n\n ; this comment is being ignored\n scope = global\n\n [database]\n user = dbuser\n password = dbpassword\n database = use_this_database\n\n [paths.default]\n datadir = /var/lib/data\n array[] = first value\n array[] = second value\n array[] = third value\n\nYou can read, manipulate and write the ini-file like so:\n\n var fs = require('fs')\n , ini = require('ini')\n\n var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'))\n\n config.scope = 'local'\n config.database.database = 'use_another_database'\n config.paths.default.tmpdir = '/tmp'\n delete config.paths.default.datadir\n config.paths.default.array.push('fourth value')\n\n fs.writeFileSync('./config_modified.ini', ini.stringify(config, 'section'))\n\nThis will result in a file called `config_modified.ini` being written to the filesystem with the following content:\n\n [section]\n scope = local\n [section.database]\n user = dbuser\n password = dbpassword\n database = use_another_database\n [section.paths.default]\n tmpdir = /tmp\n array[] = first value\n array[] = second value\n array[] = third value\n array[] = fourth value\n\n\n## API\n\n### decode(inistring)\nDecode the ini-style formatted `inistring` into a nested object.\n\n### parse(inistring)\nAlias for `decode(inistring)`\n\n### encode(object, [section])\nEncode the object `object` into an ini-style formatted string. If the optional parameter `section` is given, then all top-level properties of the object are put into this section and the `section`-string is prepended to all sub-sections, see the usage example above.\n\n### stringify(object, [section])\nAlias for `encode(object, [section])`\n\n### safe(val)\nEscapes the string `val` such that it is safe to be used as a key or value in an ini-file. Basically escapes quotes. For example\n\n ini.safe('\"unsafe string\"')\n\nwould result in\n\n \"\\\"unsafe string\\\"\"\n\n### unsafe(val)\nUnescapes the string `val`\n",
+ "readmeFilename": "README.md",
+ "_id": "ini@1.1.0",
"_from": "ini@latest"
}
; wrap in quotes to get a key with a bracket, not a section.
"[disturbing]" = hey you never know
+; Test arrays
+zr[] = deedee
+ar[] = one
+ar[] = three
+; This should be included in the array
+ar = this is included
+
+; Test resetting of a value (and not turn it into an array)
+br = cold
+br = warm
+
; a section
[a]
av = a val
j = "{ o: "p", a: { av: "a val", b: { c: { e: "this [value]" } } } }"
"[]" = a square?
+; Nested array
+cr[] = four
+cr[] = eight
+
; nested child without middle parent
; should create otherwise-empty a.b
[a.b.c]
+ 'a with spaces = b c\n'
+ '" xa n p " = "\\"\\r\\nyoyoyo\\r\\r\\n"\n'
+ '"[disturbing]" = hey you never know\n'
+ + 'zr[] = deedee\n'
+ + 'ar[] = one\n'
+ + 'ar[] = three\n'
+ + 'ar[] = this is included\n'
+ + 'br = warm\n'
+ '\n'
+ '[a]\n'
+ 'av = a val\n'
+ '{ av: a val, b: { c: { e: "this [value]" '
+ '} } } }\nj = "\\"{ o: \\"p\\", a: { av:'
+ ' \\"a val\\", b: { c: { e: \\"this [value]'
- + '\\" } } } }\\""\n"[]" = a square?\n\n[a.b.c]\ne = 1\n'
+ + '\\" } } } }\\""\n"[]" = a square?\n'
+ + 'cr[] = four\ncr[] = eight\n\n'
+ +'[a.b.c]\ne = 1\n'
+ 'j = 2\n\n[x\\.y\\.z]\nx.y.z = xyz\n\n'
- + '[x\\.y\\.z.a\\.b\\.c]\n'
- + 'a.b.c = abc\n'
+ + '[x\\.y\\.z.a\\.b\\.c]\na.b.c = abc\n'
+ 'nocomment = this\\; this is not a comment\n'
, expectD =
{ o: 'p',
'a with spaces': 'b c',
" xa n p ":'"\r\nyoyoyo\r\r\n',
'[disturbing]': 'hey you never know',
+ 'zr': ['deedee'],
+ 'ar': ['one', 'three', 'this is included'],
+ 'br': 'warm',
a:
{ av: 'a val',
e: '{ o: p, a: { av: a val, b: { c: { e: "this [value]" } } } }',
j: '"{ o: "p", a: { av: "a val", b: { c: { e: "this [value]" } } } }"',
"[]": "a square?",
+ cr: ['four', 'eight'],
b: { c: { e: '1', j: '2' } } },
'x.y.z': {
'x.y.z': 'xyz',
-Copyright (c) Isaac Z. Schlueter
+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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+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.
+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.
var locks = {}
+function hasOwnProperty (obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop)
+}
+
process.on('exit', function () {
// cleanup
Object.keys(locks).forEach(exports.unlockSync)
})
if (!l.length) {
// cleanup
- Object.keys(locks).forEach(exports.unlockSync)
+ try { Object.keys(locks).forEach(exports.unlockSync) } catch (e) {}
process.removeListener('uncaughtException', H)
throw er
}
exports.unlock = function (path, cb) {
// best-effort. unlocking an already-unlocked lock is a noop
- fs.unlink(path, function (unlinkEr) {
- if (!locks.hasOwnProperty(path)) return cb()
- fs.close(locks[path], function (closeEr) {
- delete locks[path]
- cb()
- })
- })
+ if (hasOwnProperty(locks, path))
+ fs.close(locks[path], unlink)
+ else
+ unlink()
+
+ function unlink () {
+ delete locks[path]
+ fs.unlink(path, function (unlinkEr) { cb() })
+ }
}
exports.unlockSync = function (path) {
- try { fs.unlinkSync(path) } catch (er) {}
- if (!locks.hasOwnProperty(path)) return
// best-effort. unlocking an already-unlocked lock is a noop
- try { fs.close(locks[path]) } catch (er) {}
+ try { fs.closeSync(locks[path]) } catch (er) {}
+ try { fs.unlinkSync(path) } catch (er) {}
delete locks[path]
}
}
function notStale (er, path, opts, cb) {
- if (typeof opts.wait === 'number' && opts.wait > 0) {
- // wait for some ms for the lock to clear
- var start = Date.now()
-
- var retried = false
- function retry () {
- if (retried) return
- retried = true
- // maybe already closed.
- try { watcher.close() } catch (e) {}
- clearTimeout(timer)
- var newWait = Date.now() - start
- var opts_ = Object.create(opts, { wait: { value: newWait }})
- exports.lock(path, opts_, cb)
- }
+ // if we can't wait, then just call it a failure
+ if (typeof opts.wait !== 'number' || opts.wait <= 0)
+ return cb(er)
- try {
- var watcher = fs.watch(path, function (change) {
- if (change === 'rename') {
- // ok, try and get it now.
- // if this fails, then continue waiting, maybe.
- retry()
- }
- })
- watcher.on('error', function (er) {
- // usually means it expired before the watcher spotted it
- retry()
- })
- } catch (er) {
- retry()
- }
+ // console.error('wait', path, opts.wait)
+ // wait for some ms for the lock to clear
+ var start = Date.now()
+ var end = start + opts.wait
- var timer = setTimeout(function () {
- try { watcher.close() } catch (e) {}
- cb(er)
- }, opts.wait)
- } else {
- // failed to lock!
- return cb(er)
+ function retry () {
+ var now = Date.now()
+ var newWait = end - now
+ var newOpts = Object.create(opts, { wait: { value: newWait }})
+ exports.lock(path, newOpts, cb)
}
+
+ var timer = setTimeout(retry, 10)
}
exports.lockSync = function (path, opts) {
{
"name": "lockfile",
- "version": "0.2.1",
+ "version": "0.3.0",
"main": "lockfile.js",
"directories": {
"test": "test"
"license": "BSD",
"description": "A very polite lock file utility, which endeavors to not litter, and to wait patiently for others.",
"readme": "# lockfile\n\nA very polite lock file utility, which endeavors to not litter, and to\nwait patiently for others.\n\n## Usage\n\n```javascript\nvar lockFile = require('lockfile')\n\n// opts is optional, and defaults to {}\nlockFile.lock('some-file.lock', opts, function (er, fd) {\n // if the er happens, then it failed to acquire a lock.\n // if there was not an error, then the fd is opened in\n // wx mode. If you want to write something to it, go ahead.\n\n // do my stuff, free of interruptions\n // then, some time later, do:\n lockFile.unlock('some-file.lock', function (er) {\n // er means that an error happened, and is probably bad.\n })\n})\n```\n\n## Methods\n\nSync methods return the value/throw the error, others don't. Standard\nnode fs stuff.\n\nAll known locks are removed when the process exits. Of course, it's\npossible for certain types of failures to cause this to fail, but a best\neffort is made to not be a litterbug.\n\n### lockFile.lock(path, [opts], cb)\n\nAcquire a file lock on the specified path. Returns the FD.\n\n### lockFile.lockSync(path, [opts])\n\nAcquire a file lock on the specified path\n\n### lockFile.unlock(path, cb)\n\nClose and unlink the lockfile.\n\n### lockFile.unlockSync(path)\n\nClose and unlink the lockfile.\n\n### lockFile.check(path, [opts], cb)\n\nCheck if the lockfile is locked and not stale.\n\nReturns boolean.\n\n### lockFile.checkSync(path, [opts], cb)\n\nCheck if the lockfile is locked and not stale.\n\nCallback is called with `cb(error, isLocked)`.\n\n## Options\n\n### opts.wait\n\nA number of milliseconds to wait for locks to expire before giving up.\nOnly used by lockFile.lock. Relies on fs.watch. If the lock is not\ncleared by the time the wait expires, then it returns with the original\nerror.\n\n### opts.stale\n\nA number of milliseconds before locks are considered to have expired.\n\n### opts.retries\n\nUsed by lock and lockSync. Retry `n` number of times before giving up.\n\n### opts.retryWait\n\nUsed by lock. Wait `n` milliseconds before retrying.\n",
- "_id": "lockfile@0.2.1",
- "_from": "lockfile@>=0.2"
+ "readmeFilename": "README.md",
+ "_id": "lockfile@0.3.0",
+ "_from": "lockfile@~0.3.0"
}
try { lockFile.unlockSync('stale-lock') } catch (er) {}
try { lockFile.unlockSync('watch-lock') } catch (er) {}
try { lockFile.unlockSync('retry-lock') } catch (er) {}
+ try { lockFile.unlockSync('contentious-lock') } catch (er) {}
t.end()
})
+test('lock contention', function (t) {
+ var gotlocks = 0;
+ var N = 200
+ var delay = 10
+ // allow for some time for each lock acquisition and release.
+ // note that raising N higher will mean that the overhead
+ // increases, because we're creating more and more watchers.
+ // irl, you should never have several hundred contenders for a
+ // single lock, so this situation is somewhat pathological.
+ var overhead = 200
+ var wait = N * overhead + delay
+
+ // first make it locked, so that everyone has to wait
+ lockFile.lock('contentious-lock', function(er, lock) {
+ t.ifError(er, 'acquiring starter')
+ if (er) throw er;
+ t.pass('acquired starter lock')
+ setTimeout(function() {
+ lockFile.unlock('contentious-lock', function (er) {
+ t.ifError(er, 'unlocking starter')
+ if (er) throw er
+ t.pass('unlocked starter')
+ })
+ }, delay)
+ })
+
+ for (var i=0; i < N; i++)
+ lockFile.lock('contentious-lock', { wait: wait }, function(er, lock) {
+ if (er) throw er;
+ lockFile.unlock('contentious-lock', function(er) {
+ if (er) throw er
+ gotlocks++
+ t.pass('locked and unlocked #' + gotlocks)
+ if (gotlocks === N) {
+ t.pass('got all locks')
+ t.end()
+ }
+ })
+ })
+})
+
test('basic test', function (t) {
lockFile.check('basic-lock', function (er, locked) {
if (er) throw er
try { lockFile.unlockSync('stale-lock') } catch (er) {}
try { lockFile.unlockSync('watch-lock') } catch (er) {}
try { lockFile.unlockSync('retry-lock') } catch (er) {}
+ try { lockFile.unlockSync('contentious-lock') } catch (er) {}
t.end()
})
* Windows XP/Vista/7:
* Microsoft Visual Studio C++ 2010 ([Express][msvc2010] version works well)
* For 64-bit builds of node and native modules you will _**also**_ need the [Windows 7 64-bit SDK][win7sdk]
+ * If the install fails, try uninstalling any C++ 2010 x64&x86 Redistributable that you have installed first.
* If you get errors that the 64-bit compilers are not installed you may also need the [compiler update for the Windows SDK 7.1]
* Windows 8:
* Microsoft Visual Studio C++ 2012 for Windows Desktop ([Express][msvc2012] version works well)
+Note that OS X is just a flavour of Unix and so needs `python`, `make`, and C/C++.
+An easy way to obtain these is to install XCode from Apple,
+and then use it to install the command line tools (under Preferences -> Downloads).
+
How to Use
----------
'conditions': [
[ 'OS=="mac"', {
+ 'defines': [ '_DARWIN_USE_64_BIT_INODE=1' ],
'libraries': [ '-undefined dynamic_lookup' ],
'xcode_settings': {
'DYLIB_INSTALL_NAME_BASE': '@rpath'
# warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent<T>'
# needs to have dll-interface to be used by clients of class 'node::ObjectWrap'
'msvs_disabled_warnings': [ 4251 ],
+ }, {
+ # OS!="win"
+ 'defines': [ '_LARGEFILE_SOURCE', '_FILE_OFFSET_BITS=64' ],
}],
[ 'OS=="freebsd" or OS=="openbsd" or OS=="solaris" or (OS=="linux" and target_arch!="ia32")', {
'cflags': [ '-fPIC' ],
*/
function findMsbuild () {
- log.verbose('could not find "msbuild.exe". guessing location')
+ log.verbose('could not find "msbuild.exe" in PATH - finding location in registry')
var notfoundErr = new Error('Can\'t find "msbuild.exe". Do you have Microsoft Visual Studio C++ 2008+ installed?')
- exec('reg query HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions /s /f MSBuildToolsPath /e /t REG_SZ', function (err, stdout, stderr) {
+ exec('reg query "HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions" /s', function (err, stdout, stderr) {
var reVers = /Software\\Microsoft\\MSBuild\\ToolsVersions\\([^\r]+)\r\n\s+MSBuildToolsPath\s+REG_SZ\s+([^\r]+)/gi
, msbuilds = []
, r
, defaults = config.target_defaults
, variables = config.variables
- if (!defaults) {
- defaults = config.target_defaults = {}
- }
- if (!variables) {
- variables = config.variables = {}
- }
- if (!defaults.cflags) {
- defaults.cflags = []
- }
- if (!defaults.defines) {
- defaults.defines = []
- }
- if (!defaults.include_dirs) {
- defaults.include_dirs = []
- }
- if (!defaults.libraries) {
- defaults.libraries = []
- }
+ // default "config.variables"
+ if (!variables) variables = config.variables = {}
+
+ // default "config.defaults"
+ if (!defaults) defaults = config.target_defaults = {}
+
+ // don't inherit the "defaults" from node's `process.config` object.
+ // doing so could cause problems in cases where the `node` executable was
+ // compiled on a different machine (with different lib/include paths) than
+ // the machine where the addon is being built to
+ defaults.cflags = []
+ defaults.defines = []
+ defaults.include_dirs = []
+ defaults.libraries = []
// set the default_configuration prop
if ('debug' in gyp.opts) {
"bindings",
"gyp"
],
- "version": "0.8.2",
+ "version": "0.8.4",
"installVersion": 9,
"author": {
"name": "Nathan Rajlich",
"engines": {
"node": ">= 0.6.0"
},
- "readme": "node-gyp\n=========\n### Node.js native addon build tool\n\n`node-gyp` is a cross-platform command-line tool written in Node.js for compiling\nnative addon modules for Node.js, which takes away the pain of dealing with the\nvarious differences in build platforms. It is the replacement to the `node-waf`\nprogram which is removed for node `v0.8`. If you have a native addon for node that\nstill has a `wscript` file, then you should definitely add a `binding.gyp` file\nto support the latest versions of node.\n\nMultiple target versions of node are supported (i.e. `0.6`, `0.7`,..., `1.0`,\netc.), regardless of what version of node is actually installed on your system\n(`node-gyp` downloads the necessary development files for the target version).\n\n#### Features:\n\n * Easy to use, consistent interface\n * Same commands to build your module on every platform\n * Supports multiple target versions of Node\n\n\nInstallation\n------------\n\nYou can install with `npm`:\n\n``` bash\n$ npm install -g node-gyp\n```\n\nYou will also need to install:\n\n * On Unix:\n * `python`\n * `make`\n * A proper C/C++ compiler toolchain, like GCC\n * On Windows:\n * [Python][windows-python] ([`v2.7.3`][windows-python-v2.7.3] recommended, `v3.x.x` is __*not*__ supported)\n * Windows XP/Vista/7:\n * Microsoft Visual Studio C++ 2010 ([Express][msvc2010] version works well)\n * For 64-bit builds of node and native modules you will _**also**_ need the [Windows 7 64-bit SDK][win7sdk]\n * If you get errors that the 64-bit compilers are not installed you may also need the [compiler update for the Windows SDK 7.1]\n * Windows 8:\n * Microsoft Visual Studio C++ 2012 for Windows Desktop ([Express][msvc2012] version works well)\n\nHow to Use\n----------\n\nTo compile your native addon, first go to its root directory:\n\n``` bash\n$ cd my_node_addon\n```\n\nThe next step is to generate the appropriate project build files for the current\nplatform. Use `configure` for that:\n\n``` bash\n$ node-gyp configure\n```\n\n__Note__: The `configure` step looks for the `binding.gyp` file in the current\ndirectory to processs. See below for instructions on creating the `binding.gyp` file.\n\nNow you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file\n(on Windows) in the `build/` directory. Next invoke the `build` command:\n\n``` bash\n$ node-gyp build\n```\n\nNow you have your compiled `.node` bindings file! The compiled bindings end up\nin `build/Debug/` or `build/Release/`, depending on the build mode. At this point\nyou can require the `.node` file with Node and run your tests!\n\n__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or\n`-d`) switch when running the either `configure` or `build` command.\n\n\nThe \"binding.gyp\" file\n----------------------\n\nPreviously when node had `node-waf` you had to write a `wscript` file. The\nreplacement for that is the `binding.gyp` file, which describes the configuration\nto build your module in a JSON-like format. This file gets placed in the root of\nyour package, alongside the `package.json` file.\n\nA barebones `gyp` file appropriate for building a node addon looks like:\n\n``` json\n{\n \"targets\": [\n {\n \"target_name\": \"binding\",\n \"sources\": [ \"src/binding.cc\" ]\n }\n ]\n}\n```\n\nSome additional resources for writing `gyp` files:\n\n * [\"Hello World\" node addon example](https://github.com/joyent/node/tree/master/test/addons/hello-world)\n * [gyp user documentation](http://code.google.com/p/gyp/wiki/GypUserDocumentation)\n * [gyp input format reference](http://code.google.com/p/gyp/wiki/InputFormatReference)\n * [*\"binding.gyp\" files out in the wild* wiki page](https://github.com/TooTallNate/node-gyp/wiki/%22binding.gyp%22-files-out-in-the-wild)\n\n\nCommands\n--------\n\n`node-gyp` responds to the following commands:\n\n| **Command** | **Description**\n|:--------------|:---------------------------------------------------------------\n| `build` | Invokes `make`/`msbuild.exe` and builds the native addon\n| `clean` | Removes any the `build` dir if it exists\n| `configure` | Generates project build files for the current platform\n| `rebuild` | Runs \"clean\", \"configure\" and \"build\" all in a row\n| `install` | Installs node development header files for the given version\n| `list` | Lists the currently installed node development file versions\n| `remove` | Removes the node development header files for the given version\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n[windows-python]: http://www.python.org/getit/windows\n[windows-python-v2.7.3]: http://www.python.org/download/releases/2.7.3#download\n[msvc2010]: http://go.microsoft.com/?linkid=9709949\n[msvc2012]: http://go.microsoft.com/?linkid=9816758\n[win7sdk]: http://www.microsoft.com/en-us/download/details.aspx?id=8279\n[compiler update for the Windows SDK 7.1]: http://www.microsoft.com/en-us/download/details.aspx?id=4422\n",
+ "readme": "node-gyp\n=========\n### Node.js native addon build tool\n\n`node-gyp` is a cross-platform command-line tool written in Node.js for compiling\nnative addon modules for Node.js, which takes away the pain of dealing with the\nvarious differences in build platforms. It is the replacement to the `node-waf`\nprogram which is removed for node `v0.8`. If you have a native addon for node that\nstill has a `wscript` file, then you should definitely add a `binding.gyp` file\nto support the latest versions of node.\n\nMultiple target versions of node are supported (i.e. `0.6`, `0.7`,..., `1.0`,\netc.), regardless of what version of node is actually installed on your system\n(`node-gyp` downloads the necessary development files for the target version).\n\n#### Features:\n\n * Easy to use, consistent interface\n * Same commands to build your module on every platform\n * Supports multiple target versions of Node\n\n\nInstallation\n------------\n\nYou can install with `npm`:\n\n``` bash\n$ npm install -g node-gyp\n```\n\nYou will also need to install:\n\n * On Unix:\n * `python`\n * `make`\n * A proper C/C++ compiler toolchain, like GCC\n * On Windows:\n * [Python][windows-python] ([`v2.7.3`][windows-python-v2.7.3] recommended, `v3.x.x` is __*not*__ supported)\n * Windows XP/Vista/7:\n * Microsoft Visual Studio C++ 2010 ([Express][msvc2010] version works well)\n * For 64-bit builds of node and native modules you will _**also**_ need the [Windows 7 64-bit SDK][win7sdk]\n * If the install fails, try uninstalling any C++ 2010 x64&x86 Redistributable that you have installed first.\n * If you get errors that the 64-bit compilers are not installed you may also need the [compiler update for the Windows SDK 7.1]\n * Windows 8:\n * Microsoft Visual Studio C++ 2012 for Windows Desktop ([Express][msvc2012] version works well)\n\nNote that OS X is just a flavour of Unix and so needs `python`, `make`, and C/C++.\nAn easy way to obtain these is to install XCode from Apple,\nand then use it to install the command line tools (under Preferences -> Downloads).\n\nHow to Use\n----------\n\nTo compile your native addon, first go to its root directory:\n\n``` bash\n$ cd my_node_addon\n```\n\nThe next step is to generate the appropriate project build files for the current\nplatform. Use `configure` for that:\n\n``` bash\n$ node-gyp configure\n```\n\n__Note__: The `configure` step looks for the `binding.gyp` file in the current\ndirectory to processs. See below for instructions on creating the `binding.gyp` file.\n\nNow you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file\n(on Windows) in the `build/` directory. Next invoke the `build` command:\n\n``` bash\n$ node-gyp build\n```\n\nNow you have your compiled `.node` bindings file! The compiled bindings end up\nin `build/Debug/` or `build/Release/`, depending on the build mode. At this point\nyou can require the `.node` file with Node and run your tests!\n\n__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or\n`-d`) switch when running the either `configure` or `build` command.\n\n\nThe \"binding.gyp\" file\n----------------------\n\nPreviously when node had `node-waf` you had to write a `wscript` file. The\nreplacement for that is the `binding.gyp` file, which describes the configuration\nto build your module in a JSON-like format. This file gets placed in the root of\nyour package, alongside the `package.json` file.\n\nA barebones `gyp` file appropriate for building a node addon looks like:\n\n``` json\n{\n \"targets\": [\n {\n \"target_name\": \"binding\",\n \"sources\": [ \"src/binding.cc\" ]\n }\n ]\n}\n```\n\nSome additional resources for writing `gyp` files:\n\n * [\"Hello World\" node addon example](https://github.com/joyent/node/tree/master/test/addons/hello-world)\n * [gyp user documentation](http://code.google.com/p/gyp/wiki/GypUserDocumentation)\n * [gyp input format reference](http://code.google.com/p/gyp/wiki/InputFormatReference)\n * [*\"binding.gyp\" files out in the wild* wiki page](https://github.com/TooTallNate/node-gyp/wiki/%22binding.gyp%22-files-out-in-the-wild)\n\n\nCommands\n--------\n\n`node-gyp` responds to the following commands:\n\n| **Command** | **Description**\n|:--------------|:---------------------------------------------------------------\n| `build` | Invokes `make`/`msbuild.exe` and builds the native addon\n| `clean` | Removes any the `build` dir if it exists\n| `configure` | Generates project build files for the current platform\n| `rebuild` | Runs \"clean\", \"configure\" and \"build\" all in a row\n| `install` | Installs node development header files for the given version\n| `list` | Lists the currently installed node development file versions\n| `remove` | Removes the node development header files for the given version\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n[windows-python]: http://www.python.org/getit/windows\n[windows-python-v2.7.3]: http://www.python.org/download/releases/2.7.3#download\n[msvc2010]: http://go.microsoft.com/?linkid=9709949\n[msvc2012]: http://go.microsoft.com/?linkid=9816758\n[win7sdk]: http://www.microsoft.com/en-us/download/details.aspx?id=8279\n[compiler update for the Windows SDK 7.1]: http://www.microsoft.com/en-us/download/details.aspx?id=4422\n",
"readmeFilename": "README.md",
- "_id": "node-gyp@0.8.2",
+ "_id": "node-gyp@0.8.4",
"dist": {
- "shasum": "d1a72a944a16a97b91ed3ea2f2ec6e7c0826c294"
+ "shasum": "018dce69cd55f6bc5bf370c2aff3c869ddde8a30"
},
- "_from": "node-gyp@~0.8.1"
+ "_from": "node-gyp@0.8.4",
+ "_resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-0.8.4.tgz"
}
* `strict-ssl` {Boolean} Whether or not to be strict with SSL
certificates. Default = `true`
* `user-agent` {String} User agent header to send. Default =
- `"node/{process.version}"`
+ `"node/{process.version} {process.platform} {process.arch}"`
* `log` {Object} The logger to use. Defaults to `require("npmlog")` if
that works, otherwise logs are disabled.
* `fetch-retries` {Number} Number of times to retry on GET failures.
"readme": "# couch-login\n\nThis module lets you log into couchdb to get a session token, then make\nrequests using that session. It is basically just a thin wrapper around\n[@mikeal's request module](https://github.com/mikeal/request).\n\nThis is handy if you want a user to take actions in a couchdb database\non behalf of a user, without having to store their couchdb username and\npassword anywhere. (You do need to store the AuthSession token\nsomewhere, though.)\n\n## Usage\n\n```javascript\nvar CouchLogin = require('couch-login')\n\n// Nothing about this module is http-server specific of course.\n// You could also use it to do authenticated requests against\n// a couchdb using sessions and storing the token somewhere else.\n\nhttp.createServer(function (req, res) {\n var couch = new CouchLogin('http://my-couch.iriscouch.com:5984/')\n\n // .. look up the token in the user's session or whatever ..\n // Look at couch.decorate(req, res) for more on doing that\n // automatically, below.\n\n if (sessionToken) {\n // this user already logged in.\n couch.token = sessionToken\n\n // now we can do things on their behalf, like:\n // 1. View their session info.\n // like doing request.get({ uri: couch + '/_session', ... })\n // but with the cookie and whatnot\n\n couch.get('/_session', function (er, resp, data) {\n // er = some kind of communication error.\n // resp = response object from the couchdb request.\n // data = parsed JSON response body.\n if (er || resp.statusCode !== 200) {\n res.statusCode = resp.statusCode || 403\n return res.end('Invalid login or something')\n }\n\n // now we have the session info, we know who this user is.\n // hitting couchdb for this on every request is kinda costly,\n // so maybe you should store the username wherever you're storing\n // the sessionToken. RedSess is a good util for this, if you're\n // into redis. And if you're not into redis, you're crazy,\n // because it is awesome.\n\n // now let's get the user record.\n // note that this will 404 for anyone other than the user,\n // unless they're a server admin.\n couch.get('/_users/org.couchdb.user:' + data.userCtx.name, etc)\n\n // PUTs and DELETEs will also use their session, of course, so\n // your validate_doc_update's will see their info in userCtx\n })\n\n } else {\n // don't have a sessionToken.\n // get a username and password from the post body or something.\n // maybe redirect to a /login page or something to ask for that.\n var login = { name: name, password: password }\n couch.login(login, function (er, resp, data) {\n // again, er is an error, resp is the response obj, data is the json\n if (er || resp.statusCode !== 200) {\n res.statusCode = resp.statusCode || 403\n return res.end('Invalid login or something')\n }\n\n // the data is something like\n // {\"ok\":true,\"name\":\"testuser\",\"roles\":[]}\n // and couch.token is the token you'll need to save somewhere.\n\n // at this point, you can start making authenticated requests to\n // couchdb, or save data in their session, or do whatever it is\n // that you need to do.\n\n res.statusCode = 200\n res.write(\"Who's got two thumbs and just logged you into couch?\\n\")\n setTimeout(function () {\n res.end(\"THIS GUY!\")\n }, 500)\n })\n }\n})\n```\n\n## Class: CouchLogin\n### new CouchLogin(couchdbUrl, token)\n\nCreate a new CouchLogin object bound to the couchdb url.\n\nIn addition to these, the `get`, `post`, `put`, and `del` methods all\nproxy to the associated method on [request](https://github.com/mikeal/request).\n\nHowever, as you'll note in the example above, only the pathname portion\nof the url is required. Urls will be appended to the couchdb url passed\ninto the constructor.\n\nIf you have to talk to more than one couchdb, then you'll need more than\none CouchLogin object, for somewhat obvious reasons.\n\nAll callbacks get called with the following arguments, which are exactly\nidentical to the arguments passed to a `request` callback.\n\n* `er` {Error | null} Set if a communication error happens.\n* `resp` {HTTP Response} The response from the request to couchdb\n* `data` {Object} The parsed JSON data from couch\n\nIf the token is the string \"anonymous\", then it will not attempt to log\nin before making requests. If the token is not \"anonymous\", then it\nmust be an object with the appropriate fields.\n\n### couch.token\n\n* {Object}\n\nAn object representing the couchdb session token. (Basically just a\ncookie and a timeout.)\n\nIf the token has already timed out, then setting it will have no effect.\n\n### couch.tokenSet\n\nIf set, this method is called whenever the token is saved.\n\nFor example, you could assign a function to this method to save the\ntoken into a redis session, a cookie, or in some other database.\n\nTakes a callback which should be called when the token is saved.\n\n### couch.tokenGet\n\nIf set, this method is called to look up the token on demand.\n\nThe inverse of couch.tokenSet. Takes a callback which is called with\nthe `cb(er || null, token)`.\n\n### couch.tokenDel\n\nIf set, this method is called to delete the token when it should be\ndiscarded.\n\nRelated to tokenGet and tokenSet. Takes a callback which should be\ncalled when the token is deleted.\n\n### couch.ca\n\n* {String | Array | null}\n\nA certificate authority string, or an array of CA strings. Only\nrelevant for HTTPS couches, of course.\n\nLeave as `null` to use the default ca settings built into node.\n\n### couch.strictSSL\n\n* {Boolean | null}\n\nWhether or not to be strict about SSL connections. If left as null,\nthen use the default setting in node, which is true in node versions\n0.9.x and above, and false prior to 0.8.x.\n\nOnly relevant for HTTPS couches, of course.\n\n### couch.anonymous()\n\nReturn a new CouchLogin object that points at the same couchdb server,\nbut doesn't try to log in before making requests.\n\nThis is handy for situations where the user is not logged in at the\nmoment, but a request needs to be made anyway, and does not require\nauthorization.\n\n### couch.login(auth, callback)\n\n* `auth` {Object} The login details\n * `name` {String}\n * `password` {String}\n* `callback` {Function}\n\nWhen the callback is called, the `couch.token` will already have been\nset (assuming it worked!), so subsequent requests will be done as that\nuser.\n\n### couch.get(path, callback)\n\nGET the supplied path from the couchdb using the credentials on the\ntoken.\n\nFails if the token is invalid or expired.\n\n### couch.del(path, callback)\n\nDELETE the supplied path from the couchdb using the credentials on the\ntoken.\n\nFails if the token is invalid or expired.\n\n### couch.post(path, data, callback)\n\nPOST the data to the supplied path in the couchdb, using the credentials\non the token.\n\nFails if the token is invalid or expired.\n\n### couch.put(path, data, callback)\n\nPUT the data to the supplied path in the couchdb, using the credentials\non the token.\n\nFails if the token is invalid or expired.\n\n### couch.changePass(newAuth, callback)\n\nMust already be logged in. Updates the `_users` document with new salt\nand hash, and re-logs in with the new credentials. Callback is called\nwith the same arguments as login, or the first step of the process that\nfailed.\n\n### couch.signup(userData, callback)\n\nCreate a new user account. The userData must contain at least a `name`\nand `password` field. Any additional data will be copied to the user\nrecord. The `_id`, `name`, `roles`, `type`, `password_sha`, `salt`, and\n`date` fields are generated.\n\nAlso signs in as the newly created user, on successful account creation.\n\n### couch.deleteAccount(name, callback)\n\nDeletes a user account. If not logged in as the user, or a server\nadmin, then the request will fail.\n\nNote that this immediately invalidates any session tokens for the\ndeleted user account. If you are deleting the user's record, then you\nought to follow this with `couch.logout(callback)` so that it won't try\nto re-use the invalid session.\n\n### couch.logout(callback)\n\nDelete the session out of couchdb. This makes the token permanently\ninvalid, and deletes it.\n\n### couch.decorate(req, res)\n\nSet up `req.couch` and `res.couch` as references to this couch login\ninstance.\n\nAdditionall, if `req.session` or `res.session` is set, then it'll call\n`session.get('couch_token', cb)` as the tokenGet method,\n`session.set('couch_token', token, cb)` as the tokenSet method, and\n`session.del('couch_token', cb)` as the tokenDel method.\n\nThis works really nice with\n[RedSess](https://github.com/isaacs/redsess).\n",
"readmeFilename": "README.md",
"_id": "couch-login@0.1.15",
- "_from": "couch-login@~0.1.15"
+ "dist": {
+ "shasum": "5239feb4080aacfc736d539bf9ebafbd1c381f38"
+ },
+ "_from": "couch-login@~0.1.15",
+ "_resolved": "https://registry.npmjs.org/couch-login/-/couch-login-0.1.15.tgz"
}
},
"name": "npm-registry-client",
"description": "Client for the npm registry",
- "version": "0.2.11",
+ "version": "0.2.13",
"repository": {
"url": "git://github.com/isaacs/npm-registry-client"
},
},
"dependencies": {
"request": "~2.9.202",
- "graceful-fs": "~1.1.8",
+ "graceful-fs": "~1.2.0",
"semver": "~1.1.0",
"slide": "~1.1.3",
"chownr": "0",
"npmlog": ""
},
"license": "BSD",
- "readme": "# npm-registry-client\n\nThe code that npm uses to talk to the registry.\n\nIt handles all the caching and HTTP calls.\n\n## Usage\n\n```javascript\nvar RegClient = require('npm-registry-client')\nvar client = new RegClient(config)\n\nclient.get(\"npm\", \"latest\", 1000, function (er, data, raw, res) {\n // error is an error if there was a problem.\n // data is the parsed data object\n // raw is the json string\n // res is the response from couch\n})\n```\n\n# Configuration\n\nThis program is designed to work with\n[npmconf](https://npmjs.org/package/npmconf), but you can also pass in\na plain-jane object with the appropriate configs, and it'll shim it\nfor you. Any configuration thingie that has get/set/del methods will\nalso be accepted.\n\n* `registry` **Required** {String} URL to the registry\n* `cache` **Required** {String} Path to the cache folder\n* `always-auth` {Boolean} Auth even for GET requests.\n* `auth` {String} A base64-encoded `username:password`\n* `email` {String} User's email address\n* `tag` {String} The default tag to use when publishing new packages.\n Default = `\"latest\"`\n* `ca` {String} Cerficate signing authority certificates to trust.\n* `strict-ssl` {Boolean} Whether or not to be strict with SSL\n certificates. Default = `true`\n* `user-agent` {String} User agent header to send. Default =\n `\"node/{process.version}\"`\n* `log` {Object} The logger to use. Defaults to `require(\"npmlog\")` if\n that works, otherwise logs are disabled.\n* `fetch-retries` {Number} Number of times to retry on GET failures.\n Default=2\n* `fetch-retry-factor` {Number} `factor` setting for `node-retry`. Default=10\n* `fetch-retry-mintimeout` {Number} `minTimeout` setting for `node-retry`.\n Default=10000 (10 seconds)\n* `fetch-retry-maxtimeout` {Number} `maxTimeout` setting for `node-retry`.\n Default=60000 (60 seconds)\n* `proxy` {URL} The url to proxy requests through.\n* `https-proxy` {URL} The url to proxy https requests through.\n Defaults to be the same as `proxy` if unset.\n* `_auth` {String} The base64-encoded authorization header.\n* `username` `_password` {String} Username/password to use to generate\n `_auth` if not supplied.\n* `_token` {Object} A token for use with\n [couch-login](https://npmjs.org/package/couch-login)\n\n# client.request(method, where, [what], [etag], [nofollow], cb)\n\n* `method` {String} HTTP method\n* `where` {String} Path to request on the server\n* `what` {Stream | Buffer | String | Object} The request body. Objects\n that are not Buffers or Streams are encoded as JSON.\n* `etag` {String} The cached ETag\n* `nofollow` {Boolean} Prevent following 302/301 responses\n* `cb` {Function}\n * `error` {Error | null}\n * `data` {Object} the parsed data object\n * `raw` {String} the json\n * `res` {Response Object} response from couch\n\nMake a request to the registry. All the other methods are wrappers\naround this. one.\n\n# client.adduser(username, password, email, cb)\n\n* `username` {String}\n* `password` {String}\n* `email` {String}\n* `cb` {Function}\n\nAdd a user account to the registry, or verify the credentials.\n\n# client.get(url, [timeout], [nofollow], [staleOk], cb)\n\n* `url` {String} The url path to fetch\n* `timeout` {Number} Number of seconds old that a cached copy must be\n before a new request will be made.\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `staleOk` {Boolean} If there's cached data available, then return that\n to the callback quickly, and update the cache the background.\n\nFetches data from the registry via a GET request, saving it in\nthe cache folder with the ETag.\n\n# client.publish(data, tarball, [readme], cb)\n\n* `data` {Object} Package data\n* `tarball` {String | Stream} Filename or stream of the package tarball\n* `readme` {String} Contents of the README markdown file\n* `cb` {Function}\n\nPublish a package to the registry.\n\nNote that this does not create the tarball from a folder. However, it\ncan accept a gzipped tar stream or a filename to a tarball.\n\n# client.star(package, starred, cb)\n\n* `package` {String} Name of the package to star\n* `starred` {Boolean} True to star the package, false to unstar it.\n* `cb` {Function}\n\nStar or unstar a package.\n\nNote that the user does not have to be the package owner to star or\nunstar a package, though other writes do require that the user be the\npackage owner.\n\n# client.tag(project, version, tag, cb)\n\n* `project` {String} Project name\n* `version` {String} Version to tag\n* `tag` {String} Tag name to apply\n* `cb` {Function}\n\nMark a version in the `dist-tags` hash, so that `pkg@tag`\nwill fetch the specified version.\n\n# client.unpublish(name, [ver], cb)\n\n* `name` {String} package name\n* `ver` {String} version to unpublish. Leave blank to unpublish all\n versions.\n* `cb` {Function}\n\nRemove a version of a package (or all versions) from the registry. When\nthe last version us unpublished, the entire document is removed from the\ndatabase.\n\n# client.upload(where, file, [etag], [nofollow], cb)\n\n* `where` {String} URL path to upload to\n* `file` {String | Stream} Either the filename or a readable stream\n* `etag` {String} Cache ETag\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `cb` {Function}\n\nUpload an attachment. Mostly used by `client.publish()`.\n",
+ "readme": "# npm-registry-client\n\nThe code that npm uses to talk to the registry.\n\nIt handles all the caching and HTTP calls.\n\n## Usage\n\n```javascript\nvar RegClient = require('npm-registry-client')\nvar client = new RegClient(config)\n\nclient.get(\"npm\", \"latest\", 1000, function (er, data, raw, res) {\n // error is an error if there was a problem.\n // data is the parsed data object\n // raw is the json string\n // res is the response from couch\n})\n```\n\n# Configuration\n\nThis program is designed to work with\n[npmconf](https://npmjs.org/package/npmconf), but you can also pass in\na plain-jane object with the appropriate configs, and it'll shim it\nfor you. Any configuration thingie that has get/set/del methods will\nalso be accepted.\n\n* `registry` **Required** {String} URL to the registry\n* `cache` **Required** {String} Path to the cache folder\n* `always-auth` {Boolean} Auth even for GET requests.\n* `auth` {String} A base64-encoded `username:password`\n* `email` {String} User's email address\n* `tag` {String} The default tag to use when publishing new packages.\n Default = `\"latest\"`\n* `ca` {String} Cerficate signing authority certificates to trust.\n* `strict-ssl` {Boolean} Whether or not to be strict with SSL\n certificates. Default = `true`\n* `user-agent` {String} User agent header to send. Default =\n `\"node/{process.version} {process.platform} {process.arch}\"`\n* `log` {Object} The logger to use. Defaults to `require(\"npmlog\")` if\n that works, otherwise logs are disabled.\n* `fetch-retries` {Number} Number of times to retry on GET failures.\n Default=2\n* `fetch-retry-factor` {Number} `factor` setting for `node-retry`. Default=10\n* `fetch-retry-mintimeout` {Number} `minTimeout` setting for `node-retry`.\n Default=10000 (10 seconds)\n* `fetch-retry-maxtimeout` {Number} `maxTimeout` setting for `node-retry`.\n Default=60000 (60 seconds)\n* `proxy` {URL} The url to proxy requests through.\n* `https-proxy` {URL} The url to proxy https requests through.\n Defaults to be the same as `proxy` if unset.\n* `_auth` {String} The base64-encoded authorization header.\n* `username` `_password` {String} Username/password to use to generate\n `_auth` if not supplied.\n* `_token` {Object} A token for use with\n [couch-login](https://npmjs.org/package/couch-login)\n\n# client.request(method, where, [what], [etag], [nofollow], cb)\n\n* `method` {String} HTTP method\n* `where` {String} Path to request on the server\n* `what` {Stream | Buffer | String | Object} The request body. Objects\n that are not Buffers or Streams are encoded as JSON.\n* `etag` {String} The cached ETag\n* `nofollow` {Boolean} Prevent following 302/301 responses\n* `cb` {Function}\n * `error` {Error | null}\n * `data` {Object} the parsed data object\n * `raw` {String} the json\n * `res` {Response Object} response from couch\n\nMake a request to the registry. All the other methods are wrappers\naround this. one.\n\n# client.adduser(username, password, email, cb)\n\n* `username` {String}\n* `password` {String}\n* `email` {String}\n* `cb` {Function}\n\nAdd a user account to the registry, or verify the credentials.\n\n# client.get(url, [timeout], [nofollow], [staleOk], cb)\n\n* `url` {String} The url path to fetch\n* `timeout` {Number} Number of seconds old that a cached copy must be\n before a new request will be made.\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `staleOk` {Boolean} If there's cached data available, then return that\n to the callback quickly, and update the cache the background.\n\nFetches data from the registry via a GET request, saving it in\nthe cache folder with the ETag.\n\n# client.publish(data, tarball, [readme], cb)\n\n* `data` {Object} Package data\n* `tarball` {String | Stream} Filename or stream of the package tarball\n* `readme` {String} Contents of the README markdown file\n* `cb` {Function}\n\nPublish a package to the registry.\n\nNote that this does not create the tarball from a folder. However, it\ncan accept a gzipped tar stream or a filename to a tarball.\n\n# client.star(package, starred, cb)\n\n* `package` {String} Name of the package to star\n* `starred` {Boolean} True to star the package, false to unstar it.\n* `cb` {Function}\n\nStar or unstar a package.\n\nNote that the user does not have to be the package owner to star or\nunstar a package, though other writes do require that the user be the\npackage owner.\n\n# client.tag(project, version, tag, cb)\n\n* `project` {String} Project name\n* `version` {String} Version to tag\n* `tag` {String} Tag name to apply\n* `cb` {Function}\n\nMark a version in the `dist-tags` hash, so that `pkg@tag`\nwill fetch the specified version.\n\n# client.unpublish(name, [ver], cb)\n\n* `name` {String} package name\n* `ver` {String} version to unpublish. Leave blank to unpublish all\n versions.\n* `cb` {Function}\n\nRemove a version of a package (or all versions) from the registry. When\nthe last version us unpublished, the entire document is removed from the\ndatabase.\n\n# client.upload(where, file, [etag], [nofollow], cb)\n\n* `where` {String} URL path to upload to\n* `file` {String | Stream} Either the filename or a readable stream\n* `etag` {String} Cache ETag\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `cb` {Function}\n\nUpload an attachment. Mostly used by `client.publish()`.\n",
"readmeFilename": "README.md",
- "_id": "npm-registry-client@0.2.11",
- "_from": "npm-registry-client@0.2.11"
+ "_id": "npm-registry-client@0.2.13",
+ "_from": "npm-registry-client@latest"
}
var temp = osenv.tmpdir()
var home = osenv.home()
+var uidOrPid = process.getuid ? process.getuid() : process.pid
+
if (home) process.env.HOME = home
-else home = temp
+else home = path.resolve(temp, "npm-" + uidOrPid)
+
+var cacheExtra = process.platform === "win32" ? "npm-cache" : ".npm"
+var cacheRoot = process.platform === "win32" && process.env.APPDATA || home
+var cache = path.resolve(cacheRoot, cacheExtra)
+
var globalPrefix
Object.defineProperty(exports, "defaults", {get: function () {
return defaults =
{ "always-auth" : false
-
+ , "bin-links" : true
, browser : null
, ca : // the npm CA certificate.
"-----END CERTIFICATE-----\n" ]
- , cache : process.platform === "win32"
- ? path.resolve(process.env.APPDATA || home || temp, "npm-cache")
- : path.resolve( home || temp, ".npm")
+ , cache : cache
, "cache-lock-stale": 60000
, "cache-lock-retries": 10
, "cache-lock-wait": 10000
, "cache-max": Infinity
- , "cache-min": 0
+ , "cache-min": 10
, color : true
, coverage: false
, "https-proxy" : process.env.HTTPS_PROXY || process.env.https_proxy ||
process.env.HTTP_PROXY || process.env.http_proxy || null
, "user-agent" : "node/" + process.version
+ + ' ' + process.platform
+ + ' ' + process.arch
, "rebuild-bundle" : true
, registry : "https://registry.npmjs.org/"
, rollback : true
exports.types =
{ "always-auth" : Boolean
+ , "bin-links": Boolean
, browser : [null, String]
, ca: [null, String, Array]
, cache : path
if (!type) {
try { return JSON.parse(content) }
catch (er) { return ini.parse(content) }
- } if (type === 'json') {
+ } else if (type === 'json') {
if (this.emit) {
try { return JSON.parse(content) }
catch (er) { this.emit('error', er) }
{
"name": "config-chain",
- "version": "1.1.3",
+ "version": "1.1.5",
"description": "HANDLE CONFIGURATION ONCE AND FOR ALL",
"homepage": "http://github.com/dominictarr/config-chain",
"repository": {
},
"dependencies": {
"proto-list": "~1.2.1",
- "ini": "~1.0.2"
+ "ini": "1"
},
"devDependencies": {
"tap": "0.3.0"
},
"readme": "#config-chain\n\nUSE THIS MODULE TO LOAD ALL YOUR CONFIGURATIONS\n\n``` js\n\n //npm install config-chain\n\n var cc = require('config-chain')\n , opts = require('optimist').argv //ALWAYS USE OPTIMIST FOR COMMAND LINE OPTIONS.\n , env = opts.env || process.env.YOUR_APP_ENV || 'dev' //SET YOUR ENV LIKE THIS.\n\n // EACH ARG TO CONFIGURATOR IS LOADED INTO CONFIGURATION CHAIN\n // EARLIER ITEMS OVERIDE LATER ITEMS\n // PUTS COMMAND LINE OPTS FIRST, AND DEFAULTS LAST!\n\n //strings are interpereted as filenames.\n //will be loaded synchronously\n\n var conf =\n cc(\n //OVERRIDE SETTINGS WITH COMMAND LINE OPTS\n opts,\n\n //ENV VARS IF PREFIXED WITH 'myApp_'\n\n cc.env('myApp_'), //myApp_foo = 'like this'\n\n //FILE NAMED BY ENV\n path.join(__dirname, 'config.' + env + '.json'),\n\n //IF `env` is PRODUCTION\n env === 'prod'\n ? path.join(__dirname, 'special.json') //load a special file\n : null //NULL IS IGNORED!\n\n //SUBDIR FOR ENV CONFIG\n path.join(__dirname, 'config', env, 'config.json'),\n\n //SEARCH PARENT DIRECTORIES FROM CURRENT DIR FOR FILE\n cc.find('config.json'),\n\n //PUT DEFAULTS LAST\n {\n host: 'localhost'\n port: 8000\n })\n\n var host = conf.get('host')\n\n // or\n\n var host = conf.store.host\n\n```\n\nFINALLY, EASY FLEXIBLE CONFIGURATIONS!\n\n##see also: [proto-list](https://github.com/isaacs/proto-list/)\n\nWHATS THAT YOU SAY?\n\nYOU WANT A \"CLASS\" SO THAT YOU CAN DO CRAYCRAY JQUERY CRAPS?\n\nEXTEND WITH YOUR OWN FUNCTIONALTY!?\n\n## CONFIGCHAIN LIVES TO SERVE ONLY YOU!\n\n```javascript\nvar cc = require('config-chain')\n\n// all the stuff you did before\nvar config = cc({\n some: 'object'\n },\n cc.find('config.json'),\n cc.env('myApp_')\n )\n // CONFIGS AS A SERVICE, aka \"CaaS\", aka EVERY DEVOPS DREAM OMG!\n .addUrl('http://configurator:1234/my-configs')\n // ASYNC FTW!\n .addFile('/path/to/file.json')\n\n // OBJECTS ARE OK TOO, they're SYNC but they still ORDER RIGHT\n // BECAUSE PROMISES ARE USED BUT NO, NOT *THOSE* PROMISES, JUST\n // ACTUAL PROMISES LIKE YOU MAKE TO YOUR MOM, KEPT OUT OF LOVE\n .add({ another: 'object' })\n\n // DIE A THOUSAND DEATHS IF THIS EVER HAPPENS!!\n .on('error', function (er) {\n // IF ONLY THERE WAS SOMETHIGN HARDER THAN THROW\n // MY SORROW COULD BE ADEQUATELY EXPRESSED. /o\\\n throw er\n })\n\n // THROW A PARTY IN YOUR FACE WHEN ITS ALL LOADED!!\n .on('load', function (config) {\n console.awesome('HOLY SHIT!')\n })\n```\n\n# BORING API DOCS\n\n## cc(...args)\n\nMAKE A CHAIN AND ADD ALL THE ARGS.\n\nIf the arg is a STRING, then it shall be a JSON FILENAME.\n\nSYNC I/O!\n\nRETURN THE CHAIN!\n\n## cc.json(...args)\n\nJoin the args INTO A JSON FILENAME!\n\nSYNC I/O!\n\n## cc.find(relativePath)\n\nSEEK the RELATIVE PATH by climbing the TREE OF DIRECTORIES.\n\nRETURN THE FOUND PATH!\n\nSYNC I/O!\n\n## cc.parse(content, file, type)\n\nParse the content string, and guess the type from either the\nspecified type or the filename.\n\nRETURN THE RESULTING OBJECT!\n\nNO I/O!\n\n## cc.env(prefix, env=process.env)\n\nGet all the keys on the provided env object (or process.env) which are\nprefixed by the specified prefix, and put the values on a new object.\n\nRETURN THE RESULTING OBJECT!\n\nNO I/O!\n\n## cc.ConfigChain()\n\nThe ConfigChain class for CRAY CRAY JQUERY STYLE METHOD CHAINING!\n\nOne of these is returned by the main exported function, as well.\n\nIt inherits (prototypically) from\n[ProtoList](https://github.com/isaacs/proto-list/), and also inherits\n(parasitically) from\n[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)\n\nIt has all the methods from both, and except where noted, they are\nunchanged.\n\n### LET IT BE KNOWN THAT chain IS AN INSTANCE OF ConfigChain.\n\n## chain.sources\n\nA list of all the places where it got stuff. The keys are the names\npassed to addFile or addUrl etc, and the value is an object with some\ninfo about the data source.\n\n## chain.addFile(filename, type, [name=filename])\n\nFilename is the name of the file. Name is an arbitrary string to be\nused later if you desire. Type is either 'ini' or 'json', and will\ntry to guess intelligently if omitted.\n\nLoaded files can be saved later.\n\n## chain.addUrl(url, type, [name=url])\n\nSame as the filename thing, but with a url.\n\nCan't be saved later.\n\n## chain.addEnv(prefix, env, [name='env'])\n\nAdd all the keys from the env object that start with the prefix.\n\n## chain.addString(data, file, type, [name])\n\nParse the string and add it to the set. (Mainly used internally.)\n\n## chain.add(object, [name])\n\nAdd the object to the set.\n\n## chain.root {Object}\n\nThe root from which all the other config objects in the set descend\nprototypically.\n\nPut your defaults here.\n\n## chain.set(key, value, name)\n\nSet the key to the value on the named config object. If name is\nunset, then set it on the first config object in the set. (That is,\nthe one with the highest priority, which was added first.)\n\n## chain.get(key, [name])\n\nGet the key from the named config object explicitly, or from the\nresolved configs if not specified.\n\n## chain.save(name, type)\n\nWrite the named config object back to its origin.\n\nCurrently only supported for env and file config types.\n\nFor files, encode the data according to the type.\n\n## chain.on('save', function () {})\n\nWhen one or more files are saved, emits `save` event when they're all\nsaved.\n\n## chain.on('load', function (chain) {})\n\nWhen the config chain has loaded all the specified files and urls and\nsuch, the 'load' event fires.\n",
"readmeFilename": "readme.markdown",
- "_id": "config-chain@1.1.3",
+ "_id": "config-chain@1.1.5",
"_from": "config-chain@~1.1.1"
}
{
"name": "npmconf",
- "version": "0.0.17",
+ "version": "0.0.23",
"description": "The config thing npm uses",
"main": "npmconf.js",
"directories": {
"once": "~1.1.1",
"mkdirp": "~0.3.3",
"osenv": "0.0.3",
- "nopt": "2"
+ "nopt": "2",
+ "semver": "~1.1.0",
+ "ini": "~1.1.0"
},
"devDependencies": {},
"scripts": {
"license": "BSD",
"readme": "# npmconf\n\nThe config thing npm uses\n\nIf you are interested in interacting with the config settings that npm\nuses, then use this module.\n\nHowever, if you are writing a new Node.js program, and want\nconfiguration functionality similar to what npm has, but for your\nown thing, then I'd recommend using [rc](https://github.com/dominictarr/rc),\nwhich is probably what you want.\n\nIf I were to do it all over again, that's what I'd do for npm. But,\nalas, there are many systems depending on many of the particulars of\nnpm's configuration setup, so it's not worth the cost of changing.\n\n## USAGE\n\n```javascript\nvar npmconf = require('npmconf')\n\n// pass in the cli options that you read from the cli\n// or whatever top-level configs you want npm to use for now.\nnpmconf.load({some:'configs'}, function (er, conf) {\n // do stuff with conf\n conf.get('some', 'cli') // 'configs'\n conf.get('username') // 'joebobwhatevers'\n conf.set('foo', 'bar', 'user')\n conf.save('user', function (er) {\n // foo = bar is now saved to ~/.npmrc or wherever\n })\n})\n```\n",
"readmeFilename": "README.md",
- "_id": "npmconf@0.0.17",
- "_from": "npmconf@latest"
+ "_id": "npmconf@0.0.23",
+ "_from": "npmconf@0"
}
{
"name": "read-installed",
"description": "Read all the installed packages in a folder, and return a tree structure with all the data.",
- "version": "0.0.4",
+ "version": "0.1.1",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/read-installed"
"semver": "1.x",
"slide": "~1.1.3",
"read-package-json": "0",
- "graceful-fs": "~1.1.8",
+ "graceful-fs": "~1.2.0",
"npmlog": "0"
},
"optionalDependencies": {
- "graceful-fs": "~1.1.8",
+ "graceful-fs": "~1.2.0",
"npmlog": "0"
},
"author": {
},
"readme": "# read-installed\n\nRead all the installed packages in a folder, and return a tree\nstructure with all the data.\n\nnpm uses this.\n\n## Usage\n\n```javascript\nvar readInstalled = require(\"read-installed\")\n// depth is optional, defaults to Infinity\nreadInstalled(folder, depth, function (er, data) {\n ...\n})\n```\n",
"readmeFilename": "README.md",
- "_id": "read-installed@0.0.4",
- "_from": "read-installed@latest"
+ "_id": "read-installed@0.1.1",
+ "_from": "read-installed@0"
}
var rpSeen = {}
function readInstalled_ (folder, parent, name, reqver, depth, maxDepth, cb) {
- //console.error(folder, name)
-
var installed
, obj
, real
Object.keys(obj.dependencies).forEach(function (dep) {
resolveInheritance(obj.dependencies[dep])
})
+ findUnmet(obj)
}
// find unmet deps by walking up the tree object.
fuSeen.push(obj)
//console.error("find unmet", obj.name, obj.parent && obj.parent.name)
var deps = obj.dependencies = obj.dependencies || {}
+
//console.error(deps)
Object.keys(deps)
.filter(function (d) { return typeof deps[d] === "string" })
var peerDeps = obj.peerDependencies = obj.peerDependencies || {}
Object.keys(peerDeps).forEach(function (d) {
- var dependency = obj.parent && obj.parent.dependencies &&
- obj.parent.dependencies[d]
+ var dependency
+
+ if (!obj.parent) {
+ dependency = obj.dependencies[d]
+
+ // read it as a missing dep
+ if (!dependency) {
+ obj.dependencies[d] = peerDeps[d]
+ }
+ } else {
+ dependency = obj.parent.dependencies && obj.parent.dependencies[d]
+ }
+
+ if (!dependency) return
+
dependency.extraneous = false
if (!semver.satisfies(dependency.version, peerDeps[d])) {
{
"name": "read-package-json",
- "version": "0.1.12",
+ "version": "0.1.13",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"semver": "1.x",
"slide": "~1.1.3",
"npmlog": "0",
- "graceful-fs": "~1.1.8"
+ "graceful-fs": "~1.2"
},
"devDependencies": {
"tap": "~0.2.5"
},
"optionalDependencies": {
"npmlog": "0",
- "graceful-fs": "~1.1.8"
+ "graceful-fs": "~1.2"
},
"readme": "# read-package-json\n\nThis is the thing that npm uses to read package.json files. It\nvalidates some stuff, and loads some default things.\n\nIt keeps a cache of the files you've read, so that you don't end\nup reading the same package.json file multiple times.\n\nNote that if you just want to see what's literally in the package.json\nfile, you can usually do `var data = require('some-module/package.json')`.\n\nThis module is basically only needed by npm, but it's handy to see what\nnpm will see when it looks at your package.\n\n## Usage\n\n```javascript\nvar readJson = require('read-package-json')\n\nreadJson('/path/to/package.json', function (er, data) {\n if (er) {\n console.error(\"There was an error reading the file\")\n return\n }\n\n console.error('the package data is', data)\n}\n```\n\n## readJson(file, cb)\n\n* `file` {String} The path to the package.json file\n* `cb` {Function}\n\nReads the JSON file and does the things.\n\n## `package.json` Fields\n\nSee `man 5 package.json` or `npm help json`.\n\n## readJson.log\n\nBy default this is a reference to the `npmlog` module. But if that\nmodule can't be found, then it'll be set to just a dummy thing that does\nnothing.\n\nReplace with your own `{log,warn,error}` object for fun loggy time.\n\n## readJson.extras(file, data, cb)\n\nRun all the extra stuff relative to the file, with the parsed data.\n\nModifies the data as it does stuff. Calls the cb when it's done.\n\n## readJson.extraSet = [fn, fn, ...]\n\nArray of functions that are called by `extras`. Each one receives the\narguments `fn(file, data, cb)` and is expected to call `cb(er, data)`\nwhen done or when an error occurs.\n\nOrder is indeterminate, so each function should be completely\nindependent.\n\nMix and match!\n\n## readJson.cache\n\nThe `lru-cache` object that readJson uses to not read the same file over\nand over again. See\n[lru-cache](https://github.com/isaacs/node-lru-cache) for details.\n\n## Other Relevant Files Besides `package.json`\n\nSome other files have an effect on the resulting data object, in the\nfollowing ways:\n\n### `README?(.*)`\n\nIf there is a `README` or `README.*` file present, then npm will attach\na `readme` field to the data with the contents of this file.\n\nOwing to the fact that roughly 100% of existing node modules have\nMarkdown README files, it will generally be assumed to be Markdown,\nregardless of the extension. Please plan accordingly.\n\n### `server.js`\n\nIf there is a `server.js` file, and there is not already a\n`scripts.start` field, then `scripts.start` will be set to `node\nserver.js`.\n\n### `AUTHORS`\n\nIf there is not already a `contributors` field, then the `contributors`\nfield will be set to the contents of the `AUTHORS` file, split by lines,\nand parsed.\n\n### `bindings.gyp`\n\nIf a bindings.gyp file exists, and there is not already a\n`scripts.install` field, then the `scripts.install` field will be set to\n`node-gyp rebuild`.\n\n### `wscript`\n\nIf a wscript file exists, and there is not already a `scripts.install`\nfield, then the `scripts.install` field will be set to `node-waf clean ;\nnode-waf configure build`.\n\nNote that the `bindings.gyp` file supercedes this, since node-waf has\nbeen deprecated in favor of node-gyp.\n\n### `index.js`\n\nIf the json file does not exist, but there is a `index.js` file\npresent instead, and that file has a package comment, then it will try\nto parse the package comment, and use that as the data instead.\n\nA package comment looks like this:\n\n```javascript\n/**package\n * { \"name\": \"my-bare-module\"\n * , \"version\": \"1.2.3\"\n * , \"description\": \"etc....\" }\n **/\n\n// or...\n\n/**package\n{ \"name\": \"my-bare-module\"\n, \"version\": \"1.2.3\"\n, \"description\": \"etc....\" }\n**/\n```\n\nThe important thing is that it starts with `/**package`, and ends with\n`**/`. If the package.json file exists, then the index.js is not\nparsed.\n\n### `{directories.man}/*.[0-9]`\n\nIf there is not already a `man` field defined as an array of files or a\nsingle file, and\nthere is a `directories.man` field defined, then that directory will\nbe searched for manpages.\n\nAny valid manpages found in that directory will be assigned to the `man`\narray, and installed in the appropriate man directory at package install\ntime, when installed globally on a Unix system.\n\n### `{directories.bin}/*`\n\nIf there is not already a `bin` field defined as a string filename or a\nhash of `<name> : <filename>` pairs, then the `directories.bin`\ndirectory will be searched and all the files within it will be linked as\nexecutables at install time.\n\nWhen installing locally, npm links bins into `node_modules/.bin`, which\nis in the `PATH` environ when npm runs scripts. When\ninstalling globally, they are linked into `{prefix}/bin`, which is\npresumably in the `PATH` environment variable.\n",
"readmeFilename": "README.md",
- "_id": "read-package-json@0.1.12",
+ "_id": "read-package-json@0.1.13",
"_from": "read-package-json@latest"
}
{
"name": "rimraf",
- "version": "2.1.1",
+ "version": "2.1.4",
"main": "rimraf.js",
"description": "A deep deletion module for node (like `rm -rf`)",
"author": {
"url": "https://github.com/isaacs/rimraf/raw/master/LICENSE"
},
"optionalDependencies": {
- "graceful-fs": "~1.1"
+ "graceful-fs": "~1"
},
"repository": {
"type": "git",
],
"readme": "A `rm -rf` for node.\n\nInstall with `npm install rimraf`, or just drop rimraf.js somewhere.\n\n## API\n\n`rimraf(f, callback)`\n\nThe callback will be called with an error if there is one. Certain\nerrors are handled for you:\n\n* `EBUSY` - rimraf will back off a maximum of opts.maxBusyTries times\n before giving up.\n* `EMFILE` - If too many file descriptors get opened, rimraf will\n patiently wait until more become available.\n\n\n## rimraf.sync\n\nIt can remove stuff synchronously, too. But that's not so good. Use\nthe async API. It's better.\n",
"readmeFilename": "README.md",
- "_id": "rimraf@2.1.1",
+ "_id": "rimraf@2.1.4",
"dependencies": {
- "graceful-fs": "~1.1"
+ "graceful-fs": "~1"
},
- "dist": {
- "shasum": "ee9cec7e2d796ef59ceaa5f3a3024c225e630c61"
- },
- "_from": "rimraf@2.1.1"
+ "_from": "rimraf@2"
}
if (er && er.code === "ENOENT")
return cb()
if (er && (er.code === "EPERM" || er.code === "EISDIR"))
- return rmdir(p, cb)
+ return rmdir(p, er, cb)
return cb(er)
})
}
-function rmdir (p, cb) {
+function rmdir (p, originalEr, cb) {
+ // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
+ // if we guessed wrong, and it's not a directory, then
+ // raise the original error.
+ fs.rmdir(p, function (er) {
+ if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST"))
+ rmkids(p, cb)
+ else if (er && er.code === "ENOTDIR")
+ cb(originalEr)
+ else
+ cb(er)
+ })
+}
+
+function rmkids(p, cb) {
fs.readdir(p, function (er, files) {
if (er)
return cb(er)
return
if (er.code !== "EPERM" && er.code !== "EISDIR")
throw er
- fs.readdirSync(p).forEach(function (f) {
- rimrafSync(path.join(p, f))
- })
- fs.rmdirSync(p)
+ try {
+ fs.rmdirSync(p)
+ } catch (er2) {
+ if (er2.code === "ENOENT")
+ return
+ if (er2.code === "ENOTDIR")
+ throw er
+ if (er2.code === "ENOTEMPTY") {
+ fs.readdirSync(p).forEach(function (f) {
+ rimrafSync(path.join(p, f))
+ })
+ fs.rmdirSync(p)
+ }
+ }
}
}
{
"name": "semver",
- "version": "1.1.2",
+ "version": "1.1.3",
"description": "The semantic version parser used by npm.",
"main": "semver.js",
"scripts": {
},
"readme": "semver(1) -- The semantic versioner for npm\n===========================================\n\n## Usage\n\n $ npm install semver\n\n semver.valid('1.2.3') // '1.2.3'\n semver.valid('a.b.c') // null\n semver.clean(' =v1.2.3 ') // '1.2.3'\n semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true\n semver.gt('1.2.3', '9.8.7') // false\n semver.lt('1.2.3', '9.8.7') // true\n\nAs a command-line utility:\n\n $ semver -h\n\n Usage: semver -v <version> [-r <range>]\n Test if version(s) satisfy the supplied range(s),\n and sort them.\n\n Multiple versions or ranges may be supplied.\n\n Program exits successfully if any valid version satisfies\n all supplied ranges, and prints all satisfying versions.\n\n If no versions are valid, or ranges are not satisfied,\n then exits failure.\n\n Versions are printed in ascending order, so supplying\n multiple versions to the utility will just sort them.\n\n## Versions\n\nA version is the following things, in this order:\n\n* a number (Major)\n* a period\n* a number (minor)\n* a period\n* a number (patch)\n* OPTIONAL: a hyphen, followed by a number (build)\n* OPTIONAL: a collection of pretty much any non-whitespace characters\n (tag)\n\nA leading `\"=\"` or `\"v\"` character is stripped off and ignored.\n\n## Comparisons\n\nThe ordering of versions is done using the following algorithm, given\ntwo versions and asked to find the greater of the two:\n\n* If the majors are numerically different, then take the one\n with a bigger major number. `2.3.4 > 1.3.4`\n* If the minors are numerically different, then take the one\n with the bigger minor number. `2.3.4 > 2.2.4`\n* If the patches are numerically different, then take the one with the\n bigger patch number. `2.3.4 > 2.3.3`\n* If only one of them has a build number, then take the one with the\n build number. `2.3.4-0 > 2.3.4`\n* If they both have build numbers, and the build numbers are numerically\n different, then take the one with the bigger build number.\n `2.3.4-10 > 2.3.4-9`\n* If only one of them has a tag, then take the one without the tag.\n `2.3.4 > 2.3.4-beta`\n* If they both have tags, then take the one with the lexicographically\n larger tag. `2.3.4-beta > 2.3.4-alpha`\n* At this point, they're equal.\n\n## Ranges\n\nThe following range styles are supported:\n\n* `>1.2.3` Greater than a specific version.\n* `<1.2.3` Less than\n* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`\n* `~1.2.3` := `>=1.2.3 <1.3.0`\n* `~1.2` := `>=1.2.0 <1.3.0`\n* `~1` := `>=1.0.0 <2.0.0`\n* `1.2.x` := `>=1.2.0 <1.3.0`\n* `1.x` := `>=1.0.0 <2.0.0`\n\nRanges can be joined with either a space (which implies \"and\") or a\n`||` (which implies \"or\").\n\n## Functions\n\n* valid(v): Return the parsed version, or null if it's not valid.\n* inc(v, release): Return the version incremented by the release type\n (major, minor, patch, or build), or null if it's not valid.\n\n### Comparison\n\n* gt(v1, v2): `v1 > v2`\n* gte(v1, v2): `v1 >= v2`\n* lt(v1, v2): `v1 < v2`\n* lte(v1, v2): `v1 <= v2`\n* eq(v1, v2): `v1 == v2` This is true if they're logically equivalent,\n even if they're not the exact same string. You already know how to\n compare strings.\n* neq(v1, v2): `v1 != v2` The opposite of eq.\n* cmp(v1, comparator, v2): Pass in a comparison string, and it'll call\n the corresponding function above. `\"===\"` and `\"!==\"` do simple\n string comparison, but are included for completeness. Throws if an\n invalid comparison string is provided.\n* compare(v1, v2): Return 0 if v1 == v2, or 1 if v1 is greater, or -1 if\n v2 is greater. Sorts in ascending order if passed to Array.sort().\n* rcompare(v1, v2): The reverse of compare. Sorts an array of versions\n in descending order when passed to Array.sort().\n\n\n### Ranges\n\n* validRange(range): Return the valid range or null if it's not valid\n* satisfies(version, range): Return true if the version satisfies the\n range.\n* maxSatisfying(versions, range): Return the highest version in the list\n that satisfies the range, or null if none of them do.\n",
"readmeFilename": "README.md",
- "_id": "semver@1.1.2",
- "_from": "semver@latest"
+ "_id": "semver@1.1.3",
+ "_from": "semver@~1.1.2"
}
// ">1.0.2 <2.0.0" like 1.0.3 - 1.9999.9999
var starExpression = /(<|>)?=?\s*\*/g
, starReplace = ""
- , compTrimExpression = new RegExp("((<|>)?=?)\\s*("
+ , compTrimExpression = new RegExp("((<|>)?=|<|>)\\s*("
+semver+"|"+xRangePlain+")", "g")
, compTrimReplace = "$1$3"
} else if (!p || p === "*" || p.toLowerCase() === "x") {
ret = ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-"
}
- //console.error("parseXRange", [].slice.call(arguments), ret)
return ret
})
}
tap.plan(8)
test("\ncomparison tests", function (t) {
+// [version1, version2]
+// version1 should be greater than version2
; [ ["0.0.0", "0.0.0foo"]
, ["0.0.1", "0.0.0"]
, ["1.0.0", "0.9.9"]
})
test("\nequality tests", function (t) {
+// [version1, version2]
+// version1 should be equivalent to version2
; [ ["1.2.3", "v1.2.3"]
, ["1.2.3", "=1.2.3"]
, ["1.2.3", "v 1.2.3"]
test("\nrange tests", function (t) {
+// [range, version]
+// version should be included by range
; [ ["1.0.0 - 2.0.0", "1.2.3"]
, ["1.0.0", "1.0.0"]
, [">=*", "0.2.4"]
, ["=0.7.x", "0.7.0-asdf"]
, [">=0.7.x", "0.7.0-asdf"]
, ["<=0.7.x", "0.6.2"]
+ , ["~1.2.1 >=1.2.3", "1.2.3"]
+ , ["~1.2.1 =1.2.3", "1.2.3"]
+ , ["~1.2.1 1.2.3", "1.2.3"]
+ , ['~1.2.1 >=1.2.3 1.2.3', '1.2.3']
+ , ['~1.2.1 1.2.3 >=1.2.3', '1.2.3']
+ , ['~1.2.1 1.2.3', '1.2.3']
+ , ['>=1.2.1 1.2.3', '1.2.3']
+ , ['1.2.3 >=1.2.1', '1.2.3']
+ , ['>=1.2.3 >=1.2.1', '1.2.3']
+ , ['>=1.2.1 >=1.2.3', '1.2.3']
].forEach(function (v) {
t.ok(satisfies(v[1], v[0]), v[0]+" satisfied by "+v[1])
})
})
test("\nnegative range tests", function (t) {
+// [range, version]
+// version should not be included by range
; [ ["1.0.0 - 2.0.0", "2.2.3"]
, ["1.0.0", "1.0.1"]
, [">=1.0.0", "0.0.0"]
})
test("\nincrement versions test", function (t) {
+// [version, inc, result]
+// inc(version, inc) -> result
; [ [ "1.2.3", "major", "2.0.0" ]
, [ "1.2.3", "minor", "1.3.0" ]
, [ "1.2.3", "patch", "1.2.4" ]
})
test("\nreplace stars test", function (t) {
+// replace stars with ""
; [ [ "", "" ]
, [ "*", "" ]
, [ "> *", "" ]
})
test("\nvalid range test", function (t) {
+// [range, result]
+// validRange(range) -> result
+// translate ranges into their canonical form
; [ ["1.0.0 - 2.0.0", ">=1.0.0 <=2.0.0"]
, ["1.0.0", "1.0.0"]
, [">=*", ""]
})
test("\ncomparators test", function (t) {
+// [range, comparators]
+// turn range into a set of individual comparators
; [ ["1.0.0 - 2.0.0", [[">=1.0.0", "<=2.0.0"]] ]
, ["1.0.0", [["1.0.0"]] ]
, [">=*", [[">=0.0.0-"]] ]
, ["<1.2", [["<1.2.0-"]] ]
, ["< 1.2", [["<1.2.0-"]] ]
, ["1", [[">=1.0.0-", "<2.0.0-"]] ]
+ , ["1 2", [[">=1.0.0-", "<2.0.0-", ">=2.0.0-", "<3.0.0-"]] ]
].forEach(function (v) {
t.equivalent(toComparators(v[0]), v[1], "toComparators("+v[0]+") === "+JSON.stringify(v[1]))
})
node_modules
examples/extract/
test/tmp/
-test/fixtures/symlink
+test/fixtures/
},
"name": "tar",
"description": "tar for node",
- "version": "0.1.14",
+ "version": "0.1.16",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-tar.git"
"license": "BSD",
"readme": "# node-tar\n\nTar for Node.js.\n\n## Goals of this project\n\n1. Be able to parse and reasonably extract the contents of any tar file\n created by any program that creates tar files, period.\n\n At least, this includes every version of:\n\n * bsdtar\n * gnutar\n * solaris posix tar\n * Joerg Schilling's star (\"Schilly tar\")\n\n2. Create tar files that can be extracted by any of the following tar\n programs:\n\n * bsdtar/libarchive version 2.6.2\n * gnutar 1.15 and above\n * SunOS Posix tar\n * Joerg Schilling's star (\"Schilly tar\")\n\n3. 100% test coverage. Speed is important. Correctness is slightly\n more important.\n\n4. Create the kind of tar interface that Node users would want to use.\n\n5. Satisfy npm's needs for a portable tar implementation with a\n JavaScript interface.\n\n6. No excuses. No complaining. No tolerance for failure.\n\n## But isn't there already a tar.js?\n\nYes, there are a few. This one is going to be better, and it will be\nfanatically maintained, because npm will depend on it.\n\nThat's why I need to write it from scratch. Creating and extracting\ntarballs is such a large part of what npm does, I simply can't have it\nbe a black box any longer.\n\n## Didn't you have something already? Where'd it go?\n\nIt's in the \"old\" folder. It's not functional. Don't use it.\n\nIt was a useful exploration to learn the issues involved, but like most\nsoftware of any reasonable complexity, node-tar won't be useful until\nit's been written at least 3 times.\n",
"readmeFilename": "README.md",
- "_id": "tar@0.1.14",
+ "_id": "tar@0.1.16",
"_from": "tar@~0.1.12"
}
var types =
{ 0: "File"
, "\0": "OldFile" // like 0
+ , "": "OldFile"
, 1: "Link"
, 2: "SymbolicLink"
, 3: "CharacterDevice"
{
- "version": "1.2.2",
+ "version": "1.2.10",
"name": "npm",
"publishConfig": {
"proprietary-attribs": false
"bin": "./bin/npm-cli.js",
"dependencies": {
"semver": "~1.1.2",
- "ini": "~1.0.5",
+ "ini": "~1.1.0",
"slide": "1",
"abbrev": "~1.0.4",
- "graceful-fs": "~1.1.1",
+ "graceful-fs": "~1.2.0",
"minimatch": "~0.2.8",
"nopt": "~2.1.1",
"rimraf": "2",
"request": "~2.9",
"which": "1",
"tar": "~0.1.12",
- "fstream": "~0.1.17",
+ "fstream": "~0.1.22",
"block-stream": "*",
"inherits": "1",
"mkdirp": "~0.3.3",
"chownr": "0",
"npmlog": "0",
"ansi": "~0.1.2",
- "npm-registry-client": "~0.2.10",
+ "npm-registry-client": "~0.2.13",
"read-package-json": "~0.1.8",
"read-installed": "0",
- "glob": "~3.1.14",
+ "glob": "~3.1.18",
"init-package-json": "0.0.6",
"osenv": "0",
- "lockfile": ">=0.2",
+ "lockfile": "~0.3.0",
"retry": "~0.6.0",
"once": "~1.1.1",
"npmconf": "0",
],
"devDependencies": {
"ronn": "~0.3.6",
- "tap": "~0.2.5"
+ "tap": "~0.4.0"
},
"engines": {
"node": ">=0.6",
},
"scripts": {
"test": "node ./test/run.js && tap test/tap/*.js",
+ "tap": "tap test/tap/*.js",
"prepublish": "node bin/npm-cli.js prune ; rm -rf test/*/*/node_modules ; make -j4 doc",
"dumpconf": "env | grep npm | sort | uniq",
"echo": "node bin/npm-cli.js"
+++ /dev/null
-just an npm test
+++ /dev/null
-{
- "npm-test-peer-deps-file": {
- "version": "1.2.3",
- "from": "https://raw.github.com/gist/3971128/3f6aa37b4fa1186c2f47da9b77dcc4ec496e3483/index.js",
- "resolved": "https://raw.github.com/gist/3971128/3f6aa37b4fa1186c2f47da9b77dcc4ec496e3483/index.js",
- "dependencies": {
- "opener": {
- "version": "1.3.0",
- "from": "opener@1.3.0"
- }
- }
- },
- "npm-test-peer-deps-file-invalid": {
- "version": "1.2.3",
- "from": "https://gist.github.com/raw/4303335/861f8d3213061826ab31591840c3cb0ac737f4fc/index.js",
- "resolved": "https://gist.github.com/raw/4303335/861f8d3213061826ab31591840c3cb0ac737f4fc/index.js"
- },
- "dict": {
- "peerInvalid": true
- }
-}
+++ /dev/null
-var path = require("path")
-var assert = require("assert")
-
-process.env.npm_config_prefix = process.cwd()
-delete process.env.npm_config_global
-delete process.env.npm_config_depth
-
-var npm = process.env.npm_execpath
-
-require("child_process").exec(npm + " ls --json", {
- env: process.env, cwd: process.cwd() },
- function (err, stdout, stderr) {
-
- var actual = JSON.parse(stdout).dependencies
- var expected = require("./npm-ls.json")
-
- // Delete the "problems" entry because it contains system-specific path info,
- // so we can't compare it accurately and thus have deleted it from
- // ./npm-ls.json.
- delete actual.dict.problems
-
- // It's undefined which peerDependency will get installed first, so
- // this will be either version 1.1.0 or version 1.0.0
- var dictVer = actual.dict.version
- delete actual.dict.version
- delete actual.dict.from
- delete actual.dict.resolved
- assert(dictVer === "1.1.0" || dictVer === "1.0.0")
- console.error(JSON.stringify(actual, null, 2))
- assert.deepEqual(actual, expected)
-
- assert.ok(err)
- assert(/peer invalid/.test(err.message))
-})
var npm = process.env.npm_execpath
-require("child_process").exec(npm + " ls --json", {
+require("child_process").execFile(process.execPath, [npm, "ls", "--json"], {
env: process.env, cwd: process.cwd() },
function (err, stdout, stderr) {
var actual = JSON.parse(stdout).dependencies
var expected = require("./npm-ls.json")
+
+ // resolved url doesn't matter
+ delete actual.dict.resolved
+ delete expected.dict.resolved
+
console.error(JSON.stringify(actual, null, 2))
console.error(JSON.stringify(expected, null, 2))
var npm = process.env.npm_execpath
-require("child_process").exec(npm + " ls --json", {
+require("child_process").execFile(process.execPath, [npm, "ls", "--json"], {
stdio: "pipe", env: process.env, cwd: process.cwd() },
function (err, stdout, stderr) {
if (err) throw err
, existsSync = fs.existsSync || path.existsSync
, spawn = require("child_process").spawn
, npm = require("../../")
+ , rimraf = require("rimraf")
test("not every pkg.name can be required", function (t) {
t.plan(1)
function setup (cb) {
process.chdir(__dirname + "/false_name")
npm.load(function () {
- spawn("rm", [ "-rf", __dirname + "/false_name/node_modules" ])
- .on("exit", function () {
- fs.mkdirSync(__dirname + "/false_name/node_modules")
- cb()
- })
+ rimraf.sync(__dirname + "/false_name/node_modules")
+ fs.mkdirSync(__dirname + "/false_name/node_modules")
+ cb()
})
}
--- /dev/null
+{
+ "name": "package-with-peer-dep",
+ "version": "0.0.0",
+ "peerDependencies": {
+ "opener": "*"
+ }
+}
--- /dev/null
+var fs = require("fs")
+var test = require("tap").test
+var rimraf = require("rimraf")
+var npm = require("../../")
+
+test("installing dependencies that having conflicting peerDependencies", function (t) {
+ t.plan(1)
+
+ rimraf.sync(__dirname + "/peer-deps-invalid/node_modules")
+ process.chdir(__dirname + "/peer-deps-invalid")
+
+ npm.load(function () {
+ npm.commands.install([], function (err) {
+ if (!err) {
+ t.fail("No error!")
+ process.exit(1)
+ return
+ }
+
+ t.equal(err.code, "EPEERINVALID")
+ process.exit(0)
+ })
+ })
+})
{
"author": "Domenic Denicola <domenic@domenicdenicola.com> (http://domenicdenicola.com/)",
- "name": "npm-test-peer-deps-invalid",
+ "name": "peer-deps-invalid",
"version": "0.0.0",
"dependencies": {
"npm-test-peer-deps-file": "https://raw.github.com/gist/3971128/3f6aa37b4fa1186c2f47da9b77dcc4ec496e3483/index.js",
"npm-test-peer-deps-file-invalid": "https://gist.github.com/raw/4303335/861f8d3213061826ab31591840c3cb0ac737f4fc/index.js"
- },
- "scripts": {
- "test": "node test.js"
}
}
--- /dev/null
+var fs = require("fs")
+var test = require("tap").test
+var rimraf = require("rimraf")
+var npm = require("../../")
+
+var peerDepsTestUrl = "https://gist.github.com/raw/3971128/3f6aa37b4fa1186c2f47da9b77dcc4ec496e3483/index.js"
+
+test("installing a peerDependencies-using package without a package.json present (GH-3049)", function (t) {
+
+ rimraf.sync(__dirname + "/peer-deps-without-package-json/node_modules")
+ fs.mkdirSync(__dirname + "/peer-deps-without-package-json/node_modules")
+ process.chdir(__dirname + "/peer-deps-without-package-json")
+
+ npm.load(function () {
+ npm.install(peerDepsTestUrl, function (err) {
+ if (err) {
+ t.fail(err)
+ t.end()
+ process.exit(1)
+ return
+ }
+
+ t.ok(fs.existsSync(__dirname + "/peer-deps-without-package-json/node_modules/npm-test-peer-deps-file"))
+ t.ok(fs.existsSync(__dirname + "/peer-deps-without-package-json/node_modules/dict"))
+ t.end()
+ process.exit(0)
+ })
+ })
+})