npm: Upgrade to v1.2.10
authorisaacs <i@izs.me>
Wed, 6 Feb 2013 16:39:27 +0000 (08:39 -0800)
committerisaacs <i@izs.me>
Wed, 6 Feb 2013 16:39:31 +0000 (08:39 -0800)
270 files changed:
deps/npm/AUTHORS
deps/npm/doc/api/npm.md
deps/npm/doc/cli/config.md
deps/npm/doc/cli/global.md [new file with mode: 0644]
deps/npm/doc/cli/index.md
deps/npm/doc/cli/install.md
deps/npm/doc/cli/rm.md [new file with mode: 0644]
deps/npm/html/api/bin.html
deps/npm/html/api/bugs.html
deps/npm/html/api/commands.html
deps/npm/html/api/config.html
deps/npm/html/api/deprecate.html
deps/npm/html/api/docs.html
deps/npm/html/api/edit.html
deps/npm/html/api/explore.html
deps/npm/html/api/help-search.html
deps/npm/html/api/init.html
deps/npm/html/api/install.html
deps/npm/html/api/link.html
deps/npm/html/api/load.html
deps/npm/html/api/ls.html
deps/npm/html/api/npm.html
deps/npm/html/api/outdated.html
deps/npm/html/api/owner.html
deps/npm/html/api/pack.html
deps/npm/html/api/prefix.html
deps/npm/html/api/prune.html
deps/npm/html/api/publish.html
deps/npm/html/api/rebuild.html
deps/npm/html/api/restart.html
deps/npm/html/api/root.html
deps/npm/html/api/run-script.html
deps/npm/html/api/search.html
deps/npm/html/api/shrinkwrap.html
deps/npm/html/api/start.html
deps/npm/html/api/stop.html
deps/npm/html/api/submodule.html
deps/npm/html/api/tag.html
deps/npm/html/api/test.html
deps/npm/html/api/uninstall.html
deps/npm/html/api/unpublish.html
deps/npm/html/api/update.html
deps/npm/html/api/version.html
deps/npm/html/api/view.html
deps/npm/html/api/whoami.html
deps/npm/html/doc/README.html
deps/npm/html/doc/adduser.html
deps/npm/html/doc/bin.html
deps/npm/html/doc/bugs.html
deps/npm/html/doc/build.html
deps/npm/html/doc/bundle.html
deps/npm/html/doc/cache.html
deps/npm/html/doc/changelog.html
deps/npm/html/doc/coding-style.html
deps/npm/html/doc/completion.html
deps/npm/html/doc/config.html
deps/npm/html/doc/dedupe.html
deps/npm/html/doc/deprecate.html
deps/npm/html/doc/developers.html
deps/npm/html/doc/disputes.html
deps/npm/html/doc/docs.html
deps/npm/html/doc/edit.html
deps/npm/html/doc/explore.html
deps/npm/html/doc/faq.html
deps/npm/html/doc/folders.html
deps/npm/html/doc/global.html [new file with mode: 0644]
deps/npm/html/doc/help-search.html
deps/npm/html/doc/help.html
deps/npm/html/doc/index.html
deps/npm/html/doc/init.html
deps/npm/html/doc/install.html
deps/npm/html/doc/json.html
deps/npm/html/doc/link.html
deps/npm/html/doc/ls.html
deps/npm/html/doc/npm.html
deps/npm/html/doc/outdated.html
deps/npm/html/doc/owner.html
deps/npm/html/doc/pack.html
deps/npm/html/doc/prefix.html
deps/npm/html/doc/prune.html
deps/npm/html/doc/publish.html
deps/npm/html/doc/rebuild.html
deps/npm/html/doc/registry.html
deps/npm/html/doc/removing-npm.html
deps/npm/html/doc/restart.html
deps/npm/html/doc/rm.html [new file with mode: 0644]
deps/npm/html/doc/root.html
deps/npm/html/doc/run-script.html
deps/npm/html/doc/scripts.html
deps/npm/html/doc/search.html
deps/npm/html/doc/semver.html
deps/npm/html/doc/shrinkwrap.html
deps/npm/html/doc/star.html
deps/npm/html/doc/start.html
deps/npm/html/doc/stop.html
deps/npm/html/doc/submodule.html
deps/npm/html/doc/tag.html
deps/npm/html/doc/test.html
deps/npm/html/doc/uninstall.html
deps/npm/html/doc/unpublish.html
deps/npm/html/doc/update.html
deps/npm/html/doc/version.html
deps/npm/html/doc/view.html
deps/npm/html/doc/whoami.html
deps/npm/lib/build.js
deps/npm/lib/cache.js
deps/npm/lib/dedupe.js
deps/npm/lib/install.js
deps/npm/lib/link.js
deps/npm/lib/outdated.js
deps/npm/lib/publish.js
deps/npm/lib/run-script.js
deps/npm/lib/uninstall.js
deps/npm/lib/unpublish.js
deps/npm/lib/utils/error-handler.js
deps/npm/lib/utils/lifecycle.js
deps/npm/lib/utils/tar.js
deps/npm/man/man1/README.1
deps/npm/man/man1/adduser.1
deps/npm/man/man1/bin.1
deps/npm/man/man1/bugs.1
deps/npm/man/man1/build.1
deps/npm/man/man1/bundle.1
deps/npm/man/man1/cache.1
deps/npm/man/man1/changelog.1
deps/npm/man/man1/coding-style.1
deps/npm/man/man1/completion.1
deps/npm/man/man1/config.1
deps/npm/man/man1/dedupe.1
deps/npm/man/man1/deprecate.1
deps/npm/man/man1/developers.1
deps/npm/man/man1/disputes.1
deps/npm/man/man1/docs.1
deps/npm/man/man1/edit.1
deps/npm/man/man1/explore.1
deps/npm/man/man1/faq.1
deps/npm/man/man1/folders.1
deps/npm/man/man1/global.1
deps/npm/man/man1/help-search.1
deps/npm/man/man1/help.1
deps/npm/man/man1/index.1
deps/npm/man/man1/init.1
deps/npm/man/man1/install.1
deps/npm/man/man1/json.1
deps/npm/man/man1/link.1
deps/npm/man/man1/ls.1
deps/npm/man/man1/npm.1
deps/npm/man/man1/outdated.1
deps/npm/man/man1/owner.1
deps/npm/man/man1/pack.1
deps/npm/man/man1/prefix.1
deps/npm/man/man1/prune.1
deps/npm/man/man1/publish.1
deps/npm/man/man1/rebuild.1
deps/npm/man/man1/registry.1
deps/npm/man/man1/removing-npm.1
deps/npm/man/man1/restart.1
deps/npm/man/man1/rm.1
deps/npm/man/man1/root.1
deps/npm/man/man1/run-script.1
deps/npm/man/man1/scripts.1
deps/npm/man/man1/search.1
deps/npm/man/man1/semver.1
deps/npm/man/man1/shrinkwrap.1
deps/npm/man/man1/star.1
deps/npm/man/man1/start.1
deps/npm/man/man1/stop.1
deps/npm/man/man1/submodule.1
deps/npm/man/man1/tag.1
deps/npm/man/man1/test.1
deps/npm/man/man1/uninstall.1
deps/npm/man/man1/unpublish.1
deps/npm/man/man1/update.1
deps/npm/man/man1/version.1
deps/npm/man/man1/view.1
deps/npm/man/man1/whoami.1
deps/npm/man/man3/bin.3
deps/npm/man/man3/bugs.3
deps/npm/man/man3/commands.3
deps/npm/man/man3/config.3
deps/npm/man/man3/deprecate.3
deps/npm/man/man3/docs.3
deps/npm/man/man3/edit.3
deps/npm/man/man3/explore.3
deps/npm/man/man3/help-search.3
deps/npm/man/man3/init.3
deps/npm/man/man3/install.3
deps/npm/man/man3/link.3
deps/npm/man/man3/load.3
deps/npm/man/man3/ls.3
deps/npm/man/man3/npm.3
deps/npm/man/man3/outdated.3
deps/npm/man/man3/owner.3
deps/npm/man/man3/pack.3
deps/npm/man/man3/prefix.3
deps/npm/man/man3/prune.3
deps/npm/man/man3/publish.3
deps/npm/man/man3/rebuild.3
deps/npm/man/man3/restart.3
deps/npm/man/man3/root.3
deps/npm/man/man3/run-script.3
deps/npm/man/man3/search.3
deps/npm/man/man3/shrinkwrap.3
deps/npm/man/man3/start.3
deps/npm/man/man3/stop.3
deps/npm/man/man3/submodule.3
deps/npm/man/man3/tag.3
deps/npm/man/man3/test.3
deps/npm/man/man3/uninstall.3
deps/npm/man/man3/unpublish.3
deps/npm/man/man3/update.3
deps/npm/man/man3/version.3
deps/npm/man/man3/view.3
deps/npm/man/man3/whoami.3
deps/npm/node_modules/fstream/package.json
deps/npm/node_modules/glob/glob.js
deps/npm/node_modules/glob/package.json
deps/npm/node_modules/glob/test/00-setup.js
deps/npm/node_modules/glob/test/bash-comparison.js
deps/npm/node_modules/glob/test/bash-results.json [new file with mode: 0644]
deps/npm/node_modules/glob/test/mark.js
deps/npm/node_modules/glob/test/pause-resume.js
deps/npm/node_modules/glob/test/root.js
deps/npm/node_modules/graceful-fs/graceful-fs.js
deps/npm/node_modules/graceful-fs/package.json
deps/npm/node_modules/graceful-fs/test/open.js
deps/npm/node_modules/ini/README.md
deps/npm/node_modules/ini/ini.js
deps/npm/node_modules/ini/package.json
deps/npm/node_modules/ini/test/fixtures/foo.ini
deps/npm/node_modules/ini/test/foo.js
deps/npm/node_modules/lockfile/LICENSE
deps/npm/node_modules/lockfile/lockfile.js
deps/npm/node_modules/lockfile/package.json
deps/npm/node_modules/lockfile/test/basic.js
deps/npm/node_modules/node-gyp/README.md
deps/npm/node_modules/node-gyp/addon.gypi
deps/npm/node_modules/node-gyp/lib/build.js
deps/npm/node_modules/node-gyp/lib/configure.js
deps/npm/node_modules/node-gyp/package.json
deps/npm/node_modules/npm-registry-client/README.md
deps/npm/node_modules/npm-registry-client/node_modules/couch-login/package.json
deps/npm/node_modules/npm-registry-client/package.json
deps/npm/node_modules/npmconf/config-defs.js
deps/npm/node_modules/npmconf/node_modules/config-chain/index.js
deps/npm/node_modules/npmconf/node_modules/config-chain/package.json
deps/npm/node_modules/npmconf/package.json
deps/npm/node_modules/read-installed/package.json
deps/npm/node_modules/read-installed/read-installed.js
deps/npm/node_modules/read-package-json/package.json
deps/npm/node_modules/rimraf/package.json
deps/npm/node_modules/rimraf/rimraf.js
deps/npm/node_modules/semver/package.json
deps/npm/node_modules/semver/semver.js
deps/npm/node_modules/semver/test.js
deps/npm/node_modules/tar/.npmignore
deps/npm/node_modules/tar/package.json
deps/npm/node_modules/tar/tar.js
deps/npm/package.json
deps/npm/test/packages/npm-test-peer-deps-invalid/README [deleted file]
deps/npm/test/packages/npm-test-peer-deps-invalid/npm-ls.json [deleted file]
deps/npm/test/packages/npm-test-peer-deps-invalid/test.js [deleted file]
deps/npm/test/packages/npm-test-peer-deps/test.js
deps/npm/test/packages/npm-test-shrinkwrap/test.js
deps/npm/test/tap/false_name.js
deps/npm/test/tap/package-with-peer-dep/package.json [new file with mode: 0644]
deps/npm/test/tap/peer-deps-invalid.js [new file with mode: 0644]
deps/npm/test/tap/peer-deps-invalid/package.json [moved from deps/npm/test/packages/npm-test-peer-deps-invalid/package.json with 81% similarity]
deps/npm/test/tap/peer-deps-without-package-json.js [new file with mode: 0644]
deps/npm/test/tap/peer-deps-without-package-json/.gitkeep [moved from deps/npm/node_modules/rimraf/test/test-fiber.js with 100% similarity]

index 4a5f1ef..4d964f4 100644 (file)
@@ -88,3 +88,5 @@ Ian Livingstone <ianl@cs.dal.ca>
 Patrick Pfeiffer <patrick@buzzle.at>
 Paul Miller <paul@paulmillr.com>
 seebees <seebees@gmail.com>
+Carl Lange <carl@flax.ie>
+Jan Lehnardt <jan@apache.org>
index a2f034c..8c7a816 100644 (file)
@@ -4,7 +4,7 @@ npm(3) -- node package manager
 ## 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)
@@ -25,12 +25,13 @@ This is the API documentation for npm.
 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
index 9f051a0..3deafce 100644 (file)
@@ -167,6 +167,18 @@ then the user could change the behavior by doing:
 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"`
@@ -228,7 +240,7 @@ explicitly used, and that only GET requests use the cache.
 
 ### cache-min
 
-* Default: 0
+* Default: 10
 * Type: Number
 
 The minimum time (in seconds) to keep items in the registry cache before
@@ -357,10 +369,10 @@ Operates in "global" mode, so that packages are installed into the
 `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
 
@@ -398,7 +410,7 @@ A proxy to use for outgoing https requests.
 
 ### 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
@@ -568,7 +580,7 @@ standard output.
 
 ### 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
diff --git a/deps/npm/doc/cli/global.md b/deps/npm/doc/cli/global.md
new file mode 100644 (file)
index 0000000..2035861
--- /dev/null
@@ -0,0 +1,209 @@
+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)
index f8fde25..04852ce 100644 (file)
@@ -82,6 +82,10 @@ npm-index(1) -- Index of all npm documentation
 
  Folder Structures Used by npm
 
+## npm-global(1)
+
+ Folder Structures Used by npm
+
 ## npm-help-search(1)
 
  Search npm help documentation
@@ -154,6 +158,10 @@ npm-index(1) -- Index of all npm documentation
 
  Start a package
 
+## npm-rm(1)
+
+ Remove a package
+
 ## npm-root(1)
 
  Display npm root
index 1d2f6ec..2f32551 100644 (file)
@@ -165,6 +165,9 @@ rather than locally.  See `npm-folders(1)`.
 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.
 
diff --git a/deps/npm/doc/cli/rm.md b/deps/npm/doc/cli/rm.md
new file mode 100644 (file)
index 0000000..f7f743f
--- /dev/null
@@ -0,0 +1,19 @@
+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)
index 15168f2..53761a1 100644 (file)
@@ -19,7 +19,7 @@
 <p>This function should not be used programmatically.  Instead, just refer
 to the <code>npm.bin</code> member.</p>
 </div>
-<p id="footer">bin &mdash; npm@1.2.2</p>
+<p id="footer">bin &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 3ed4011..7831e95 100644 (file)
@@ -25,7 +25,7 @@ optional version number.</p>
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">bugs &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 789ea04..8948891 100644 (file)
@@ -28,7 +28,7 @@ usage, or <code>man 3 npm-&lt;command&gt;</code> for programmatic usage.</p>
 
 <ul><li><a href="../doc/index.html">index(1)</a></li></ul>
 </div>
-<p id="footer">commands &mdash; npm@1.2.2</p>
+<p id="footer">commands &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 62f256f..db52614 100644 (file)
@@ -33,7 +33,7 @@ functions instead.</p>
 
 <ul><li><a href="../api/npm.html">npm(3)</a></li></ul>
 </div>
-<p id="footer">config &mdash; npm@1.2.2</p>
+<p id="footer">config &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c3b0244..fc46f80 100644 (file)
@@ -32,7 +32,7 @@ install the package.</p></li></ul>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">deprecate &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 1a13aaf..5cf46ec 100644 (file)
@@ -25,7 +25,7 @@ optional version number.</p>
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">docs &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 1f1d178..6d179bd 100644 (file)
@@ -30,7 +30,7 @@ to open. The package can optionally have a version number attached.</p>
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">edit &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 77e5b8e..5945efe 100644 (file)
@@ -24,7 +24,7 @@ sure to use <code>npm rebuild &lt;pkg&gt;</code> if you make any changes.</p>
 
 <p>The first element in the &#39;args&#39; 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 &mdash; npm@1.2.2</p>
+<p id="footer">explore &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a2f3c70..79837a8 100644 (file)
@@ -32,7 +32,7 @@ Name of the file that matched</li></ul>
 
 <p>The silent parameter is not neccessary not used, but it may in the future.</p>
 </div>
-<p id="footer">help-search &mdash; npm@1.2.2</p>
+<p id="footer">help-search &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 39dc68d..409018e 100644 (file)
@@ -35,7 +35,7 @@ then go ahead and use this programmatically.</p>
 
 <p><a href="../doc/json.html">json(1)</a></p>
 </div>
-<p id="footer">init &mdash; npm@1.2.2</p>
+<p id="footer">init &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 3ad0f7a..2f7d67d 100644 (file)
@@ -25,7 +25,7 @@ the name of a package to be installed.</p>
 <p>Finally, &#39;callback&#39; 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 &mdash; npm@1.2.2</p>
+<p id="footer">install &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 4209687..451b0c0 100644 (file)
@@ -39,7 +39,7 @@ npm.commands.link(&#39;redis&#39;, cb)  # link-install the package</code></pre>
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">link &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 02d20ad..3da18c6 100644 (file)
@@ -32,7 +32,7 @@ config object.</p>
 
 <p>For a list of all the available command-line configs, see <code>npm help config</code></p>
 </div>
-<p id="footer">load &mdash; npm@1.2.2</p>
+<p id="footer">load &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 3029db2..3a8753d 100644 (file)
@@ -59,7 +59,7 @@ project.</p>
 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 &mdash; npm@1.2.2</p>
+<p id="footer">ls &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b761b6f..c5eb011 100644 (file)
@@ -11,7 +11,7 @@
 <h2 id="SYNOPSIS">SYNOPSIS</h2>
 
 <pre><code>var npm = require(&quot;npm&quot;)
-npm.load(configObject, function (er, npm) {
+npm.load([configObject,] function (er, npm) {
   // use the npm object, now that it&#39;s loaded.
 
   npm.config.set(key, val)
@@ -24,7 +24,7 @@ npm.load(configObject, function (er, npm) {
 
 <h2 id="VERSION">VERSION</h2>
 
-<p>1.2.2</p>
+<p>1.2.10</p>
 
 <h2 id="DESCRIPTION">DESCRIPTION</h2>
 
@@ -32,12 +32,13 @@ npm.load(configObject, function (er, npm) {
 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&#39;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&#39;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.&lt;cmd&gt;</code>.  See <code><a href="../doc/index.html">index(1)</a></code> for a list of
@@ -91,7 +92,7 @@ method names.  Use the <code>npm.deref</code> method to find the real name.</p>
 
 <pre><code>var cmd = npm.deref(&quot;unp&quot;) // cmd === &quot;unpublish&quot;</code></pre>
 </div>
-<p id="footer">npm &mdash; npm@1.2.2</p>
+<p id="footer">npm &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b27dd86..3d27712 100644 (file)
@@ -19,7 +19,7 @@ currently outdated.</p>
 
 <p>If the &#39;packages&#39; parameter is left out, npm will check all packages.</p>
 </div>
-<p id="footer">outdated &mdash; npm@1.2.2</p>
+<p id="footer">outdated &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index eedbed3..049f74c 100644 (file)
@@ -34,7 +34,7 @@ that is not implemented at this time.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">owner &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 6f60696..81a6d6e 100644 (file)
@@ -25,7 +25,7 @@ overwritten the second time.</p>
 
 <p>If no arguments are supplied, then npm packs the current package folder.</p>
 </div>
-<p id="footer">pack &mdash; npm@1.2.2</p>
+<p id="footer">pack &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 9bfb96e..a1b4e98 100644 (file)
@@ -21,7 +21,7 @@
 
 <p>This function is not useful programmatically</p>
 </div>
-<p id="footer">prefix &mdash; npm@1.2.2</p>
+<p id="footer">prefix &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index cf0f067..5268d31 100644 (file)
@@ -23,7 +23,7 @@
 <p>Extraneous packages are packages that are not listed on the parent
 package&#39;s dependencies list.</p>
 </div>
-<p id="footer">prune &mdash; npm@1.2.2</p>
+<p id="footer">prune &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 71e9060..c7602ab 100644 (file)
@@ -32,7 +32,7 @@ the registry.  Overwrites when the &quot;force&quot; environment variable is set
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">publish &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e9b6e61..d97fdae 100644 (file)
@@ -22,7 +22,7 @@ the new binary. If no &#39;packages&#39; parameter is specify, every package wil
 
 <p>See <code>npm help build</code></p>
 </div>
-<p id="footer">rebuild &mdash; npm@1.2.2</p>
+<p id="footer">rebuild &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 54801f1..19023e2 100644 (file)
@@ -27,7 +27,7 @@ in the <code>packages</code> parameter.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">restart &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c88eac9..4191995 100644 (file)
@@ -21,7 +21,7 @@
 
 <p>This function is not useful programmatically.</p>
 </div>
-<p id="footer">root &mdash; npm@1.2.2</p>
+<p id="footer">root &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 6551e50..f8dfd4a 100644 (file)
@@ -29,7 +29,7 @@ assumed to be the command to run. All other elements are ignored.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">run-script &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 811b2f8..37bad3f 100644 (file)
@@ -32,7 +32,7 @@ excluded term (the &quot;searchexclude&quot; config). The search is case insensi
 and doesn&#39;t try to read your mind (it doesn&#39;t do any verb tense matching or the
 like).</p>
 </div>
-<p id="footer">search &mdash; npm@1.2.2</p>
+<p id="footer">search &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 7267240..d83a8ad 100644 (file)
@@ -26,7 +26,7 @@ but the shrinkwrap file will still be written.</p>
 <p>Finally, &#39;callback&#39; is a function that will be called when the shrinkwrap has
 been saved.</p>
 </div>
-<p id="footer">shrinkwrap &mdash; npm@1.2.2</p>
+<p id="footer">shrinkwrap &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5b3aafe..675f3f3 100644 (file)
@@ -19,7 +19,7 @@
 <p>npm can run tests on multiple packages. Just specify multiple packages
 in the <code>packages</code> parameter.</p>
 </div>
-<p id="footer">start &mdash; npm@1.2.2</p>
+<p id="footer">start &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b95ef54..9e36cf9 100644 (file)
@@ -19,7 +19,7 @@
 <p>npm can run stop on multiple packages. Just specify multiple packages
 in the <code>packages</code> parameter.</p>
 </div>
-<p id="footer">stop &mdash; npm@1.2.2</p>
+<p id="footer">stop &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index cf2fda8..e156748 100644 (file)
@@ -33,7 +33,7 @@ dependencies into the submodule folder.</p>
 
 <ul><li>npm help json</li><li>git help submodule</li></ul>
 </div>
-<p id="footer">submodule &mdash; npm@1.2.2</p>
+<p id="footer">submodule &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 3ce716e..2803372 100644 (file)
@@ -29,7 +29,7 @@ parameter is missing or falsey (empty), the default froom the config will be
 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 &mdash; npm@1.2.2</p>
+<p id="footer">tag &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b4c41ca..00ba0ea 100644 (file)
@@ -22,7 +22,7 @@ true.</p>
 <p>npm can run tests on multiple packages. Just specify multiple packages
 in the <code>packages</code> parameter.</p>
 </div>
-<p id="footer">test &mdash; npm@1.2.2</p>
+<p id="footer">test &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 7c86d6b..90a6b32 100644 (file)
@@ -22,7 +22,7 @@ the name of a package to be uninstalled.</p>
 <p>Finally, &#39;callback&#39; 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 &mdash; npm@1.2.2</p>
+<p id="footer">uninstall &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 7a9a507..349d3dd 100644 (file)
@@ -26,7 +26,7 @@ is what is meant.</p>
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">unpublish &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 52894e6..740deee 100644 (file)
@@ -18,7 +18,7 @@
 
 <p>The &#39;packages&#39; argument is an array of packages to update. The &#39;callback&#39; parameter will be called when done or when an error occurs.</p>
 </div>
-<p id="footer">update &mdash; npm@1.2.2</p>
+<p id="footer">update &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 717950b..3b7b03c 100644 (file)
@@ -24,7 +24,7 @@ fail if the repo is not clean.</p>
 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 &mdash; npm@1.2.2</p>
+<p id="footer">version &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c8547f2..3617f76 100644 (file)
@@ -99,7 +99,7 @@ the field name.</p>
 
 <p>corresponding to the list of fields selected.</p>
 </div>
-<p id="footer">view &mdash; npm@1.2.2</p>
+<p id="footer">view &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5110105..522b746 100644 (file)
@@ -21,7 +21,7 @@
 
 <p>This function is not useful programmatically</p>
 </div>
-<p id="footer">whoami &mdash; npm@1.2.2</p>
+<p id="footer">whoami &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 87960d4..d53f740 100644 (file)
@@ -240,7 +240,7 @@ will no doubt tell you to put the output in a gist or email.</p>
 
 <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> &mdash; npm@1.2.2</p>
+<p id="footer"><a href="../doc/README.html">README</a> &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 701242c..f965cde 100644 (file)
@@ -39,7 +39,7 @@ authorize on a new machine.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">adduser &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 247a8f2..bf863db 100644 (file)
@@ -20,7 +20,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">bin &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index ee0c256..c648c5f 100644 (file)
@@ -36,7 +36,7 @@ config param.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">bugs &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 46ae979..5dbb9e3 100644 (file)
@@ -25,7 +25,7 @@ A folder containing a <code>package.json</code> file in its root.</li></ul>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">build &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index fa6a05d..c1425bb 100644 (file)
@@ -20,7 +20,7 @@ install packages into the local space.</p>
 
 <ul><li><a href="../doc/install.html">install(1)</a></li></ul>
 </div>
-<p id="footer">bundle &mdash; npm@1.2.2</p>
+<p id="footer">bundle &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5e2cf71..efa25c5 100644 (file)
@@ -66,7 +66,7 @@ they do not make an HTTP request to the registry.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">cache &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 0b0c1ae..06e6b71 100644 (file)
@@ -65,7 +65,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">changelog &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index dc1e30b..120c2e0 100644 (file)
@@ -182,7 +182,7 @@ set to anything.&quot;</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">coding-style &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 23b5318..cc0128b 100644 (file)
@@ -33,7 +33,7 @@ completions based on the arguments.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">completion &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 43604e1..fbab250 100644 (file)
@@ -152,6 +152,17 @@ the package.json has this:</p>
 <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&#39;t support symlinks, even on
+ostensibly Unix systems.</p>
+
 <h3 id="browser">browser</h3>
 
 <ul><li>Default: OS X: <code>&quot;open&quot;</code>, others: <code>&quot;google-chrome&quot;</code></li><li>Type: String</li></ul>
@@ -206,7 +217,7 @@ explicitly used, and that only GET requests use the cache.</p>
 
 <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>
@@ -317,8 +328,8 @@ the git binary.</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>
 
@@ -352,7 +363,7 @@ user.</p>
 
 <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>
 
@@ -501,7 +512,7 @@ standard output.</p>
 
 <h3 id="prefix">prefix</h3>
 
-<ul><li>Default: node&#39;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>
@@ -756,7 +767,7 @@ then answer &quot;no&quot; to any prompt.</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 &mdash; npm@1.2.2</p>
+<p id="footer">config &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a921cd6..c871d3d 100644 (file)
@@ -57,7 +57,7 @@ registry.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">dedupe &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c461327..dd98b4c 100644 (file)
@@ -31,7 +31,7 @@ something like this:</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">deprecate &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 450ddca..425826e 100644 (file)
@@ -160,7 +160,7 @@ from a fresh checkout.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">developers &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 43a9da1..62aac9a 100644 (file)
@@ -86,7 +86,7 @@ an empty tarball, you&#39;re going to be evicted.</li></ol>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">disputes &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 02663c0..7843a49 100644 (file)
@@ -37,7 +37,7 @@ config param.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">docs &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 9a89749..74fd445 100644 (file)
@@ -37,7 +37,7 @@ or <code>&quot;notepad&quot;</code> on Windows.</li><li>Type: path</li></ul>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">edit &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 0b7f3ef..47ef0a8 100644 (file)
@@ -40,7 +40,7 @@ Windows</li><li>Type: path</li></ul>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">explore &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 4cc7000..9fe947e 100644 (file)
@@ -250,7 +250,7 @@ There is not sufficient need to impose namespace rules on everyone.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">faq &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 7868c2f..c966c34 100644 (file)
@@ -205,7 +205,7 @@ cannot be found elsewhere.  See <code><a href="../doc/json.html">json(1)</a></co
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">folders &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
diff --git a/deps/npm/html/doc/global.html b/deps/npm/html/doc/global.html
new file mode 100644 (file)
index 0000000..b26baa4
--- /dev/null
@@ -0,0 +1,240 @@
+<!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&#39;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&#39;re going to <code>require()</code> it.</li><li>Install it <strong>globally</strong> if you&#39;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&#39;s <code>process.installPrefix</code>.</p>
+
+<p>On windows, this is the exact location of the node.exe binary.  On Unix
+systems, it&#39;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(&quot;packagename&quot;)</code> to load its main module, or
+<code>require(&quot;packagename/lib/path/to/sub/module&quot;)</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
+&quot;current directory&quot; for the purpose of running npm commands.  (This
+behavior is inspired by and similar to git&#39;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&#39;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 &quot;globally&quot;.</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&#39;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 -&gt; bar -&gt; baz</code>.  Imagine if, in
+addition to that, baz depended on bar, so you&#39;d have:
+<code>foo -&gt; bar -&gt; baz -&gt; bar -&gt; baz ...</code>.  However, since the folder
+structure is: <code>foo/node_modules/bar/node_modules/baz</code>, there&#39;s no need to
+put another copy of bar into <code>.../baz/node_modules</code>, since when it calls
+require(&quot;bar&quot;), 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
+&quot;a&quot; 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 &quot;target&quot; 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) &lt;---[A]
+    +-- bar (1.2.3) &lt;---[B]
+    |   +-- node_modules
+    |   |   `-- baz (2.0.2) &lt;---[C]
+    |   |       `-- node_modules
+    |   |           `-- quux (3.2.0)
+    |   `-- asdf (2.3.4)
+    `-- baz (1.2.3) &lt;---[D]
+        `-- node_modules
+            `-- quux (3.2.0) &lt;---[E]</code></pre>
+
+<p>Since foo depends directly on bar@1.2.3 and baz@1.2.3, those are
+installed in foo&#39;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&#39;s bar&#39;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&#39;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-&gt;quux-&gt;bar</code> dependency creates a cycle.
+However, because <code>bar</code> is already in <code>quux</code>&#39;s ancestry [B], it does not
+unpack another copy of bar into that folder.</p>
+
+<p>Underneath <code>foo-&gt;baz</code> [D], quux&#39;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 &mdash; 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>
index 2866c45..9e17cf8 100644 (file)
@@ -38,7 +38,7 @@ where the terms were found in the documentation.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">help-search &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e07da58..ffc2ac5 100644 (file)
@@ -36,7 +36,7 @@ matches are equivalent to specifying a topic name.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">help &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a9edf49..049bf6f 100644 (file)
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">index &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 37664a6..39519e3 100644 (file)
@@ -29,7 +29,7 @@ without a really good reason to do so.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">init &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 534ba26..f68eab5 100644 (file)
@@ -77,6 +77,9 @@ rather than locally.  See <code><a href="../doc/folders.html">folders(1)</a></co
 <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&#39;s most of what npm does.</p>
 
@@ -133,7 +136,7 @@ affects a real use-case, it will be investigated.</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 &mdash; npm@1.2.2</p>
+<p id="footer">install &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 1ea27fc..22e5a37 100644 (file)
@@ -525,7 +525,7 @@ overridden.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">json &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 1107004..6d078e9 100644 (file)
@@ -58,7 +58,7 @@ installation target into your project&#39;s <code>node_modules</code> folder.</p
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">link &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 2930a94..c522d88 100644 (file)
@@ -25,7 +25,7 @@ limit the results to only the paths to the packages named.  Note that
 nested packages will <em>also</em> show the paths to the specified packages.
 For example, running <code>npm ls promzard</code> in npm&#39;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>
 
@@ -64,7 +64,7 @@ project.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">ls &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 9eb30a9..501a4c7 100644 (file)
@@ -14,7 +14,7 @@
 
 <h2 id="VERSION">VERSION</h2>
 
-<p>1.2.2</p>
+<p>1.2.10</p>
 
 <h2 id="DESCRIPTION">DESCRIPTION</h2>
 
@@ -135,7 +135,7 @@ will no doubt tell you to put the output in a gist or email.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">npm &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b3c1606..fbf9820 100644 (file)
@@ -21,7 +21,7 @@ packages are currently outdated.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">outdated &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 8228fb0..f359fee 100644 (file)
@@ -34,7 +34,7 @@ that is not implemented at this time.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">owner &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 3dc318d..bb2ae8f 100644 (file)
@@ -29,7 +29,7 @@ overwritten the second time.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">pack &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index bdde2a5..3c1f9f5 100644 (file)
@@ -20,7 +20,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">prefix &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index bc97027..8045149 100644 (file)
@@ -25,7 +25,7 @@ package&#39;s dependencies list.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">prune &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a24ca2d..2cec4ba 100644 (file)
@@ -29,7 +29,7 @@ the registry.  Overwrites when the &quot;--force&quot; flag is set.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">publish &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 2c6a4e1..f3780da 100644 (file)
@@ -25,7 +25,7 @@ the new binary.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">rebuild &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 7e618b7..0ce8ce6 100644 (file)
@@ -95,7 +95,7 @@ ask for help on the <a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">registry &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 36f1c62..858e162 100644 (file)
@@ -58,7 +58,7 @@ modules.  To track those down, you can do the following:</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">removing-npm &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index fd21f56..27da194 100644 (file)
@@ -24,7 +24,7 @@ the &quot;start&quot; script.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">restart &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
diff --git a/deps/npm/html/doc/rm.html b/deps/npm/html/doc/rm.html
new file mode 100644 (file)
index 0000000..24c398c
--- /dev/null
@@ -0,0 +1,57 @@
+<!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 &lt;name&gt;
+npm uninstall &lt;name&gt;</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 &mdash; 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>
index 0973dd8..8a48ad7 100644 (file)
@@ -20,7 +20,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">root &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b353786..bcbbcac 100644 (file)
@@ -23,7 +23,7 @@ called directly, as well.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">run-script &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index d6beacf..9aa1f5b 100644 (file)
@@ -218,7 +218,7 @@ will sudo the npm command in question.</li></ul>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">scripts &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 0554e40..39885c5 100644 (file)
@@ -24,7 +24,7 @@ expression characters must be escaped or quoted in most shells.)</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">search &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c0206e1..0c462e6 100644 (file)
@@ -104,7 +104,7 @@ that satisfies the range, or null if none of them do.</li></ul>
 
 <ul><li><a href="../doc/json.html">json(1)</a></li></ul>
 </div>
-<p id="footer">semver &mdash; npm@1.2.2</p>
+<p id="footer">semver &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 7389ebf..6d6760b 100644 (file)
@@ -169,7 +169,7 @@ versions.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">shrinkwrap &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b896fae..007f8bf 100644 (file)
@@ -26,7 +26,7 @@ a vaguely positive way to show that you care.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">star &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index bcc3dbb..3e6aa1c 100644 (file)
@@ -20,7 +20,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">start &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 59a3a3f..115a980 100644 (file)
@@ -20,7 +20,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">stop &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 9eadc8b..a70b4d0 100644 (file)
@@ -33,7 +33,7 @@ dependencies into the submodule folder.</p>
 
 <ul><li><a href="../doc/json.html">json(1)</a></li><li>git help submodule</li></ul>
 </div>
-<p id="footer">submodule &mdash; npm@1.2.2</p>
+<p id="footer">submodule &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 8ff5d51..28a38fa 100644 (file)
@@ -21,7 +21,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">tag &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index ee09bfe..9428eb2 100644 (file)
@@ -23,7 +23,7 @@ true.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">test &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index de8dc5f..c81e946 100644 (file)
@@ -22,7 +22,7 @@ on its behalf.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">uninstall &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 8766a0a..e9a8ec0 100644 (file)
@@ -34,7 +34,7 @@ the root package entry is removed from the registry entirely.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">unpublish &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index bec6bcb..1f134e3 100644 (file)
@@ -23,7 +23,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">update &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c1d13a2..d7fbfaa 100644 (file)
@@ -40,7 +40,7 @@ in your git config for this to work properly.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">version &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 0fcc49c..f09cd1b 100644 (file)
@@ -90,7 +90,7 @@ the field name.</p>
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">view &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a0ee7b9..505bc33 100644 (file)
@@ -20,7 +20,7 @@
 
 <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 &mdash; npm@1.2.2</p>
+<p id="footer">whoami &mdash; npm@1.2.10</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 815739c..d9deb32 100644 (file)
@@ -69,6 +69,9 @@ function writeBuiltinConf (folder, cb) {
 }
 
 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
@@ -109,7 +112,7 @@ function rebuildBundles (pkg, folder, parent, gtop, cb) {
     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
index 7b83350..5e92ef5 100644 (file)
@@ -139,7 +139,7 @@ function read (name, ver, forceBypass, 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 addNamed(name, ver, c)
     deprCheck(data)
     c(er, data)
@@ -389,6 +389,7 @@ function addRemoteGit (u, parsed, name, cb_) {
     // 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(/#.*$/, "")
 
@@ -404,16 +405,16 @@ function addRemoteGit (u, parsed, name, cb_) {
 
     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")
@@ -427,16 +428,16 @@ function checkGitDir (p, u, co, cb) {
                 + "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
@@ -447,12 +448,12 @@ function cloneGitRemote (p, u, co, cb) {
         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]
@@ -481,9 +482,10 @@ function archiveGitRemote (p, u, co, cb) {
       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()
   })
 
@@ -712,7 +714,7 @@ function addNameVersion (name, ver, data, cb) {
       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)
         })
@@ -1071,6 +1073,7 @@ function lockFileName (u) {
 }
 
 var madeCache = false
+var myLocks = {}
 function lock (u, cb) {
   // the cache dir needs to exist already for this.
   if (madeCache) then()
@@ -1085,10 +1088,16 @@ function lock (u, cb) {
                , 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)
 }
index 51c6fca..bd0056e 100644 (file)
@@ -35,8 +35,16 @@ function dedupe (args, silent, 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) {
@@ -265,7 +273,7 @@ function readInstalled (dir, counter, parent, cb) {
   })
 
   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]++
@@ -294,6 +302,9 @@ function readInstalled (dir, counter, parent, cb) {
 
   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()
   })
 
index ef5ef14..5f97dc4 100644 (file)
@@ -61,6 +61,7 @@ install.completion = function (opts, cb) {
 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")
@@ -77,12 +78,24 @@ function install (args, cb_) {
   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/..
@@ -148,7 +161,7 @@ function install (args, cb_) {
     // 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: {}
@@ -164,6 +177,45 @@ function install (args, cb_) {
   })
 }
 
+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:
 //
@@ -186,7 +238,7 @@ function readDependencies (context, where, opts, cb) {
     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]
       })
@@ -456,7 +508,7 @@ function installManyTop_ (what, where, context, cb) {
       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]])
       })
@@ -536,9 +588,15 @@ function targetResolver (where, context, deps) {
 
   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, [])
 
@@ -657,7 +715,7 @@ function localLink (target, where, context, cb) {
     , 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, "..")
@@ -705,14 +763,36 @@ function resultList (target, where, parentId) {
          , 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]
@@ -720,7 +800,10 @@ function installOne_ (target, where, context, cb) {
       , [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)
       }
@@ -786,14 +869,14 @@ function checkList (value, list) {
     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 {
@@ -933,7 +1016,7 @@ function write (target, targetFolder, context, cb_) {
 
         if (peerDeps.length > 0) {
           actions.push(
-            [ installManyAndBuild, peerDeps, pdTargetFolder, pdContext ]
+            [ installMany, peerDeps, pdTargetFolder, pdContext ]
           )
         }
 
index e912796..4ecd64a 100644 (file)
@@ -20,7 +20,7 @@ link.completion = function (opts, cb) {
   var dir = npm.globalDir
   fs.readdir(dir, function (er, files) {
     cb(er, files.filter(function (f) {
-      return f.charAt(0) !== "."
+      return !f.match(/^[\._-]/)
     }))
   })
 }
index bb9f93e..e3ef5b1 100644 (file)
@@ -76,7 +76,7 @@ function outdated_ (args, dir, parentHas, cb) {
 
   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()
   })
@@ -87,10 +87,13 @@ function outdated_ (args, dir, parentHas, cb) {
       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) {
index e22719f..8de09e5 100644 (file)
@@ -32,7 +32,7 @@ function publish (args, isRetry, cb) {
   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
index d509cc8..0808f2e 100644 (file)
@@ -25,7 +25,7 @@ runScript.completion = function (opts, cb) {
     // 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)
@@ -36,7 +36,7 @@ runScript.completion = function (opts, cb) {
       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)
@@ -57,7 +57,7 @@ runScript.completion = function (opts, cb) {
 
   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()
index 275088e..bebc230 100644 (file)
@@ -30,7 +30,7 @@ function uninstall (args, cb) {
   // 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
index c0056e7..0e48ab7 100644 (file)
@@ -56,7 +56,7 @@ function unpublish (args, cb) {
     // 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)
     })
index 7fabd69..51394f1 100644 (file)
@@ -203,6 +203,14 @@ function errorHandler (er) {
               ].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
index ba5cee5..3f0042f 100644 (file)
@@ -221,6 +221,9 @@ function makeEnv (data, prefix, env) {
 
   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
index 3a84bbd..c96c4c4 100644 (file)
@@ -27,32 +27,57 @@ if (process.env.SUDO_UID && myUid === 0) {
 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) {
@@ -67,21 +92,21 @@ function pack_ (targetTarball, folder, pkg, cb_) {
       // 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)
-  })
+  }
 }
 
 
@@ -101,18 +126,41 @@ function unpack (tarball, unpackTarget, dMode, fMode, uid, gid, 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)
index bb9254d..49724d6 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 63a2d32..d6cbd3b 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 9495dfa..b979cb6 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 8156f39..498afd4 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 67ccb0b..6d134ef 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 976fcd4..dc37939 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 43234d5..d671d88 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 3584b87..97ecbb6 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index add053c..9bf22ea 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index ff8af5f..edc41c9 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 8041285..0269570 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
@@ -277,6 +277,25 @@ Type: Boolean
 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
@@ -384,7 +403,7 @@ explicitly used, and that only GET requests use the cache\.
 .SS "cache\-min"
 .
 .IP "\(bu" 4
-Default: 0
+Default: 10
 .
 .IP "\(bu" 4
 Type: Number
@@ -611,14 +630,14 @@ Type: Boolean
 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
 .
@@ -683,7 +702,7 @@ A proxy to use for outgoing https requests\.
 .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
@@ -976,7 +995,7 @@ standard output\.
 .SS "prefix"
 .
 .IP "\(bu" 4
-Default: node\'s process\.installPrefix
+Default: see npm help folders
 .
 .IP "\(bu" 4
 Type: path
index 1a3a541..d9efaed 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 0b4868b..64d290d 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index a7e9e7c..c3dcb24 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index d8b110f..a94f9a6 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 96d85c9..b84a569 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 35db1fb..cd5c7af 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index f5fa96d..df6e249 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index b85b3cf..256e0ba 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index abef276..0780dfd 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 070d40c..0780dfd 100644 (file)
@@ -1,7 +1,7 @@
-.\" 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
@@ -148,9 +148,8 @@ prevented\.
 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
 .
index 926e340..2cd9869 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 0de2638..81bd96a 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 0065d78..2a6bcfe 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
@@ -66,6 +66,9 @@
 .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
 .
index 41bf011..2019f80 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index dfb2c29..248f301 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
@@ -288,6 +288,10 @@ The \fB\-\-link\fR argument will cause npm to link global installs into the
 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\.
 .
index 6d3d384..4e0a24a 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 505fcf3..597611b 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 272e451..1e224cd 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
@@ -29,7 +29,7 @@ For example, running \fBnpm ls promzard\fR in npm\'s source tree will show:
 .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
 .
index 93fc999..dd7de70 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
@@ -14,7 +14,7 @@ npm <command> [args]
 .fi
 .
 .SH "VERSION"
-1.2.2
+1.2.10
 .
 .SH "DESCRIPTION"
 npm is the package manager for the Node JavaScript platform\.  It puts
index 2b8a569..e39d5fb 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 7418f0a..8e7ec69 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index afe332d..548a91f 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 7b4bbfc..1f7504a 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 0aecb54..0af35f9 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index f915e30..e34b091 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 8559907..0c62ec4 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 003e89c..678f06d 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 2c2118c..ed06f6a 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index a5969b8..8676312 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 5df9588..14006f6 100644 (file)
@@ -1,7 +1,7 @@
-.\" 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
index 04ec036..68fe89f 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 479a3ff..84a23f1 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 11f6b8a..60b36ca 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 17de3fd..9817c84 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 8ecdd02..ab65fa0 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index a2b354d..d767100 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index b9dc3f3..f8b1404 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 29347d3..d86236c 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 240e3b0..642f0df 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index c06af34..64e17d8 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 74c65a3..7c397d3 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 51c8ad7..c32a714 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 7c188fc..14006f6 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 8188852..3420d5e 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 214ab23..58a073b 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index d2d5219..227aade 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index afe2b77..2da98f4 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 4222bfe..d68996a 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 1047557..62ea4f7 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 7997c17..7cd6ecd 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 5aafad6..58fd72e 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 5a43889..71ab767 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index c9a7ecb..fa9bc86 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 6e9913c..7192761 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 938e3cc..e5d416b 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index c0cc6c0..fb9a3ec 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 802e912..fcee327 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 53db516..577a8c4 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 67e871f..3e064e5 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 1fbf67e..77a1950 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 94cf49d..0df78c7 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 163e58b..58f6ee8 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index a02644c..e836d7f 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
@@ -10,7 +10,7 @@
 .
 .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)
@@ -21,7 +21,7 @@ npm\.load(configObject, function (er, npm) {
 .fi
 .
 .SH "VERSION"
-1.2.2
+1.2.10
 .
 .SH "DESCRIPTION"
 This is the API documentation for npm\.
@@ -29,10 +29,13 @@ To find documentation of the command line
 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
index 1247068..47dc1a4 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 2e706ed..4b93094 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 4a7596a..775fcfc 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 67b9a84..2d25b5e 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 1302dd7..72f335c 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index cbc618f..4bf2fd0 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index ff3804c..97b5d97 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 20c73f6..f11867d 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index b863e85..741484a 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 237f11b..3a9fb15 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 79218c5..07dd8d6 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 8e2ea94..ea70223 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 172f928..63504a5 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 943f439..11bdc11 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 22d95ff..ef4afc4 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 5b5a13b..7425ffe 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 590de2a..79e0ae8 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index cb51cc1..119d61c 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index c2a868b..a6ba030 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 96885b7..063c634 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 06d46cb..c7b80ae 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index dc70c52..384c524 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 07c89b6..4bb5b33 100644 (file)
@@ -1,7 +1,7 @@
 .\" 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
index 1d3faaf..ba8e622 100644 (file)
@@ -6,7 +6,7 @@
   },
   "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"
@@ -18,7 +18,7 @@
   "dependencies": {
     "rimraf": "2",
     "mkdirp": "0.3",
-    "graceful-fs": "~1.1.2",
+    "graceful-fs": "~1.2.0",
     "inherits": "~1.0.0"
   },
   "devDependencies": {
@@ -30,6 +30,6 @@
   "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"
 }
index 10c87bc..d241e7c 100644 (file)
@@ -22,7 +22,7 @@
 //
 //   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 .. $])
 //
@@ -87,7 +87,6 @@ function Glob (pattern, options, cb) {
   if (typeof cb === "function") {
     this.on("error", cb)
     this.on("end", function (matches) {
-      // console.error("cb with matches", matches)
       cb(null, matches)
     })
   }
@@ -111,6 +110,8 @@ function Glob (pattern, options, cb) {
 
   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
 
@@ -126,6 +127,7 @@ function Glob (pattern, options, cb) {
     pattern = "**/" + pattern
   }
 
+  this.strict = options.strict !== false
   this.dot = !!options.dot
   this.mark = !!options.mark
   this.sync = !!options.sync
@@ -134,7 +136,11 @@ function Glob (pattern, options, cb) {
   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)
@@ -164,6 +170,8 @@ function Glob (pattern, options, cb) {
   }
 }
 
+Glob.prototype.log = function () {}
+
 Glob.prototype._finish = function () {
   assert(this instanceof Glob)
 
@@ -172,7 +180,7 @@ Glob.prototype._finish = function () {
 
   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) {
@@ -213,7 +221,7 @@ Glob.prototype._finish = function () {
     }, this)
   }
 
-  if (this.debug) console.error("emitting end", all)
+  this.log("emitting end", all)
 
   this.EOF = this.found = all
   this.emitMatch(this.EOF)
@@ -266,9 +274,9 @@ Glob.prototype._processEmitQueue = function (m) {
       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
   }
@@ -315,9 +323,19 @@ Glob.prototype._process = function (pattern, depth, index, cb_) {
         // 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)
@@ -344,12 +362,24 @@ Glob.prototype._process = function (pattern, depth, index, cb_) {
   // 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!
@@ -414,9 +444,14 @@ Glob.prototype._process = function (pattern, depth, index, cb_) {
           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)
@@ -446,11 +481,13 @@ Glob.prototype._stat = function (f, cb) {
   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"
@@ -481,6 +518,16 @@ Glob.prototype._stat = function (f, cb) {
 Glob.prototype._afterStat = function (f, abs, cb, er, stat) {
   var exists
   assert(this instanceof Glob)
+
+  if (abs.slice(-1) === "/" && stat && !stat.isDirectory()) {
+    this.log("should be ENOTDIR, fake it")
+
+    er = new Error("ENOTDIR, not a directory '" + abs + "'")
+    er.path = abs
+    er.code = "ENOTDIR"
+    stat = null
+  }
+
   if (er || !stat) {
     exists = false
   } else {
@@ -494,14 +541,16 @@ Glob.prototype._readdir = function (f, cb) {
   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"
@@ -522,7 +571,7 @@ Glob.prototype._readdir = function (f, cb) {
       , 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))
     }
@@ -590,7 +639,7 @@ function absWin (p) {
   // 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) !== ':'
index c684b80..c1fe087 100644 (file)
@@ -6,7 +6,7 @@
   },
   "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"
   },
@@ -31,9 +31,6 @@
   "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"
 }
index 2b60643..245afaf 100644 (file)
@@ -48,14 +48,129 @@ files.forEach(function (f) {
   })
 })
 
-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
+}
index a052ae8..239ed1a 100644 (file)
@@ -2,25 +2,8 @@
 // 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")
 
@@ -35,84 +18,46 @@ function alphasort (a, b) {
 }
 
 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()
 }
diff --git a/deps/npm/node_modules/glob/test/bash-results.json b/deps/npm/node_modules/glob/test/bash-results.json
new file mode 100644 (file)
index 0000000..8c341db
--- /dev/null
@@ -0,0 +1,347 @@
+{
+  "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"
+  ]
+}
index fda66f8..ed68a33 100644 (file)
@@ -6,13 +6,17 @@ test("mark, no / on pattern", function (t) {
   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()
   })
 })
@@ -21,13 +25,16 @@ test("mark=false, no / on pattern", function (t) {
   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()
   })
 })
@@ -36,13 +43,15 @@ test("mark=true, / on pattern", function (t) {
   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()
   })
 })
@@ -51,13 +60,15 @@ test("mark=false, / on pattern", function (t) {
   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()
   })
 })
index c848ed2..e1ffbab 100644 (file)
@@ -3,6 +3,8 @@ var tap = require("tap")
 , child_process = require("child_process")
 // just some gnarly pattern with lots of matches
 , pattern = "test/a/!(symlink)/**"
+, bashResults = require("./bash-results.json")
+, patterns = Object.keys(bashResults)
 , glob = require("../")
 , Glob = glob.Glob
 , path = require("path")
@@ -25,54 +27,19 @@ function cleanResults (m) {
   }).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")
@@ -97,7 +64,7 @@ tap.test("use a Glob object, and pause/resume it", function (t) {
     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()
index 5ccdd0e..95c23f9 100644 (file)
@@ -1,43 +1,46 @@
-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()
 })
index be9951e..fe9c3f4 100644 (file)
@@ -1,10 +1,14 @@
 // 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")
index 30f4c40..1748b98 100644 (file)
@@ -6,7 +6,7 @@
   },
   "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"
@@ -30,6 +30,7 @@
   ],
   "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"
 }
index d05f880..930d532 100644 (file)
@@ -1,6 +1,11 @@
 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')
index 9f82a76..acbe8ec 100644 (file)
@@ -17,6 +17,9 @@ Consider an ini-file `config.ini` that looks like this:
 
     [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:
 
@@ -29,6 +32,7 @@ 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'))
 
@@ -42,6 +46,11 @@ This will result in a file called `config_modified.ini` being written to the fil
     database = use_another_database
     [section.paths.default]
     tmpdir = /tmp
+    array[] = first value
+    array[] = second value
+    array[] = third value
+    array[] = fourth value
+
 
 ## API
 
@@ -68,4 +77,3 @@ would result in
 
 ### unsafe(val)
 Unescapes the string `val`
-
index 45651c0..eaf3209 100644 (file)
@@ -13,7 +13,12 @@ function encode (obj, section) {
 
   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
@@ -71,13 +76,32 @@ function decode (str) {
       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)
index 3f45c18..41c6360 100644 (file)
@@ -6,7 +6,7 @@
   },
   "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"
@@ -22,7 +22,8 @@
   "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"
 }
index 6f11f36..1d81378 100644 (file)
@@ -8,6 +8,17 @@ o = p
 ; 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
@@ -15,6 +26,10 @@ 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?
 
+; Nested array
+cr[] = four
+cr[] = eight
+
 ; nested child without middle parent
 ; should create otherwise-empty a.b
 [a.b.c]
index 64bd223..3a05eaf 100644 (file)
@@ -10,6 +10,11 @@ var i = require("../")
             + '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'
@@ -17,21 +22,26 @@ var i = require("../")
             + '{ 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',
index 74489e2..0c44ae7 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (c) Isaac Z. Schlueter
+Copyright (c) Isaac Z. Schlueter ("Author")
 All rights reserved.
 
 The BSD License
@@ -6,20 +6,22 @@ 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.
index 0bc5416..c5e62f4 100644 (file)
@@ -8,6 +8,10 @@ if (process.version.match(/^v0.[456]/)) {
 
 var locks = {}
 
+function hasOwnProperty (obj, prop) {
+  return Object.prototype.hasOwnProperty.call(obj, prop)
+}
+
 process.on('exit', function () {
   // cleanup
   Object.keys(locks).forEach(exports.unlockSync)
@@ -21,7 +25,7 @@ process.on('uncaughtException', function H (er) {
   })
   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
   }
@@ -29,20 +33,21 @@ process.on('uncaughtException', function H (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]
 }
 
@@ -161,46 +166,23 @@ exports.lock = function (path, opts, cb) {
 }
 
 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) {
index b93404b..6846b94 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "lockfile",
-  "version": "0.2.1",
+  "version": "0.3.0",
   "main": "lockfile.js",
   "directories": {
     "test": "test"
@@ -31,6 +31,7 @@
   "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"
 }
index 77308cd..c4d5eba 100644 (file)
@@ -10,9 +10,51 @@ test('setup', function (t) {
   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
@@ -221,6 +263,7 @@ test('cleanup', function (t) {
   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()
 })
 
index 722bd6e..f05f820 100644 (file)
@@ -40,10 +40,15 @@ You will also need to install:
     * 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
 ----------
 
index 5e02e66..5f74155 100644 (file)
@@ -17,6 +17,7 @@
 
     'conditions': [
       [ 'OS=="mac"', {
+        'defines': [ '_DARWIN_USE_64_BIT_INODE=1' ],
         'libraries': [ '-undefined dynamic_lookup' ],
         'xcode_settings': {
           'DYLIB_INSTALL_NAME_BASE': '@rpath'
@@ -27,6 +28,9 @@
         # 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' ],
index 8f049b4..450f313 100644 (file)
@@ -117,9 +117,9 @@ function build (gyp, argv, callback) {
    */
 
   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
index 82de1e6..e320099 100644 (file)
@@ -250,24 +250,20 @@ function configure (gyp, argv, callback) {
       , 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) {
index 811a533..8ddfe91 100644 (file)
@@ -10,7 +10,7 @@
     "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 &lt;nathan@tootallnate.net&gt;\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 &lt;nathan@tootallnate.net&gt;\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"
 }
index 4b180a0..22751c4 100644 (file)
@@ -37,7 +37,7 @@ also be accepted.
 * `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.
index 3b7ab38..65ffd0c 100644 (file)
@@ -24,5 +24,9 @@
   "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"
 }
index 6e74fee..7af896e 100644 (file)
@@ -6,7 +6,7 @@
   },
   "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"
   },
@@ -16,7 +16,7 @@
   },
   "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",
@@ -33,8 +33,8 @@
     "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"
 }
index 7a6f56b..5acfd51 100644 (file)
@@ -82,8 +82,15 @@ var defaults
 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 () {
@@ -106,7 +113,7 @@ Object.defineProperty(exports, "defaults", {get: function () {
 
   return defaults =
     { "always-auth" : false
-
+    , "bin-links" : true
     , browser : null
 
     , ca : // the npm CA certificate.
@@ -169,16 +176,14 @@ Object.defineProperty(exports, "defaults", {get: function () {
         "-----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
@@ -227,6 +232,8 @@ Object.defineProperty(exports, "defaults", {get: function () {
     , "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
@@ -265,6 +272,7 @@ Object.defineProperty(exports, "defaults", {get: function () {
 
 exports.types =
   { "always-auth" : Boolean
+  , "bin-links": Boolean
   , browser : [null, String]
   , ca: [null, String, Array]
   , cache : path
index 84815ca..ab41961 100755 (executable)
@@ -47,7 +47,7 @@ var parse = exports.parse = function (content, file, type) {
   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) }
index 10e7227..35ff769 100644 (file)
@@ -1,6 +1,6 @@
 {
   "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": {
@@ -9,7 +9,7 @@
   },
   "dependencies": {
     "proto-list": "~1.2.1",
-    "ini": "~1.0.2"
+    "ini": "1"
   },
   "devDependencies": {
     "tap": "0.3.0"
@@ -24,6 +24,6 @@
   },
   "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"
 }
index 65348d5..946db98 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "npmconf",
-  "version": "0.0.17",
+  "version": "0.0.23",
   "description": "The config thing npm uses",
   "main": "npmconf.js",
   "directories": {
@@ -12,7 +12,9 @@
     "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": {
@@ -37,6 +39,6 @@
   "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"
 }
index e05c5a9..c20eada 100644 (file)
@@ -1,7 +1,7 @@
 {
   "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": {
@@ -28,6 +28,6 @@
   },
   "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"
 }
index 192907c..4babfc8 100644 (file)
@@ -121,8 +121,6 @@ function readInstalled (folder, depth, cb) {
 
 var rpSeen = {}
 function readInstalled_ (folder, parent, name, reqver, depth, maxDepth, cb) {
-  //console.error(folder, name)
-
   var installed
     , obj
     , real
@@ -251,6 +249,7 @@ function resolveInheritance (obj) {
   Object.keys(obj.dependencies).forEach(function (dep) {
     resolveInheritance(obj.dependencies[dep])
   })
+  findUnmet(obj)
 }
 
 // find unmet deps by walking up the tree object.
@@ -261,6 +260,7 @@ function findUnmet (obj) {
   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" })
@@ -297,8 +297,21 @@ function findUnmet (obj) {
 
   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])) {
index edf606e..3c1370d 100644 (file)
@@ -1,6 +1,6 @@
 {
   "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"
 }
index ce7e1dd..679ee6b 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "rimraf",
-  "version": "2.1.1",
+  "version": "2.1.4",
   "main": "rimraf.js",
   "description": "A deep deletion module for node (like `rm -rf`)",
   "author": {
@@ -13,7 +13,7 @@
     "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"
 }
index 7fc291c..ed915f9 100644 (file)
@@ -63,12 +63,26 @@ function rimraf_ (p, cb) {
     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)
@@ -100,9 +114,19 @@ function rimrafSync (p) {
       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)
+      }
+    }
   }
 }
index 7056071..1f4ec58 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "semver",
-  "version": "1.1.2",
+  "version": "1.1.3",
   "description": "The semantic version parser used by npm.",
   "main": "semver.js",
   "scripts": {
@@ -22,6 +22,6 @@
   },
   "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"
 }
index 3702a7b..01fb1c1 100644 (file)
@@ -84,7 +84,7 @@ function validPackage (version) {
 // ">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"
 
@@ -149,7 +149,6 @@ function replaceXRange (version) {
     } else if (!p || p === "*" || p.toLowerCase() === "x") {
       ret = ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-"
     }
-    //console.error("parseXRange", [].slice.call(arguments), ret)
     return ret
   })
 }
index 1d81140..bc3952c 100644 (file)
@@ -17,6 +17,8 @@ var tap = require("tap")
 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"]
@@ -61,6 +63,8 @@ test("\ncomparison tests", function (t) {
 })
 
 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"]
@@ -112,6 +116,8 @@ test("\nequality tests", function (t) {
 
 
 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"]
@@ -177,6 +183,16 @@ test("\nrange tests", function (t) {
   , ["=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])
   })
@@ -184,6 +200,8 @@ test("\nrange tests", function (t) {
 })
 
 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"]
@@ -236,6 +254,8 @@ test("\nnegative range tests", function (t) {
 })
 
 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"   ]
@@ -257,6 +277,7 @@ test("\nincrement versions test", function (t) {
 })
 
 test("\nreplace stars test", function (t) {
+// replace stars with ""
 ; [ [ "", "" ]
   , [ "*", "" ]
   , [ "> *", "" ]
@@ -271,6 +292,9 @@ test("\nreplace stars test", function (t) {
 })
 
 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"]
   , [">=*", ""]
@@ -337,6 +361,8 @@ test("\nvalid range test", function (t) {
 })
 
 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-"]] ]
@@ -398,6 +424,7 @@ test("\ncomparators test", function (t) {
   , ["<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]))
   })
index 856407e..c167ad5 100644 (file)
@@ -2,4 +2,4 @@
 node_modules
 examples/extract/
 test/tmp/
-test/fixtures/symlink
+test/fixtures/
index 702192c..9959135 100644 (file)
@@ -6,7 +6,7 @@
   },
   "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"
@@ -30,6 +30,6 @@
   "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"
 }
index b9dbca4..a81298b 100644 (file)
@@ -75,6 +75,7 @@ Object.keys(fields).forEach(function (f) {
 var types =
   { 0: "File"
   , "\0": "OldFile" // like 0
+  , "": "OldFile"
   , 1: "Link"
   , 2: "SymbolicLink"
   , 3: "CharacterDevice"
index cd6b792..406273a 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "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"
diff --git a/deps/npm/test/packages/npm-test-peer-deps-invalid/README b/deps/npm/test/packages/npm-test-peer-deps-invalid/README
deleted file mode 100644 (file)
index 8848f07..0000000
+++ /dev/null
@@ -1 +0,0 @@
-just an npm test
diff --git a/deps/npm/test/packages/npm-test-peer-deps-invalid/npm-ls.json b/deps/npm/test/packages/npm-test-peer-deps-invalid/npm-ls.json
deleted file mode 100644 (file)
index 285bce7..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "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
-  }
-}
diff --git a/deps/npm/test/packages/npm-test-peer-deps-invalid/test.js b/deps/npm/test/packages/npm-test-peer-deps-invalid/test.js
deleted file mode 100644 (file)
index 7046264..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-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))
-})
index 98dbf5f..519528a 100644 (file)
@@ -7,7 +7,7 @@ delete process.env.npm_config_depth
 
 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) {
 
@@ -15,6 +15,11 @@ require("child_process").exec(npm + " ls --json", {
 
   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))
 
index f3fe8a4..fba90ec 100644 (file)
@@ -7,7 +7,7 @@ delete process.env.npm_config_depth
 
 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
index 0ccf8fc..968b6e7 100644 (file)
@@ -4,6 +4,7 @@ var test = require("tap").test
   , 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)
@@ -20,10 +21,8 @@ test("not every pkg.name can be required", function (t) {
 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()
   })
 }
diff --git a/deps/npm/test/tap/package-with-peer-dep/package.json b/deps/npm/test/tap/package-with-peer-dep/package.json
new file mode 100644 (file)
index 0000000..99cc75b
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "name": "package-with-peer-dep",
+  "version": "0.0.0",
+  "peerDependencies": {
+    "opener": "*"
+  }
+}
diff --git a/deps/npm/test/tap/peer-deps-invalid.js b/deps/npm/test/tap/peer-deps-invalid.js
new file mode 100644 (file)
index 0000000..44b9367
--- /dev/null
@@ -0,0 +1,24 @@
+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)
+    })
+  })
+})
@@ -1,12 +1,9 @@
 {
   "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"
   }
 }
diff --git a/deps/npm/test/tap/peer-deps-without-package-json.js b/deps/npm/test/tap/peer-deps-without-package-json.js
new file mode 100644 (file)
index 0000000..19b6064
--- /dev/null
@@ -0,0 +1,29 @@
+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)
+    })
+  })
+})