npm: Upgrade to 1.1.55
authorisaacs <i@izs.me>
Tue, 21 Aug 2012 22:29:03 +0000 (15:29 -0700)
committerisaacs <i@izs.me>
Tue, 21 Aug 2012 22:29:37 +0000 (15:29 -0700)
170 files changed:
deps/npm/.travis.yml [deleted file]
deps/npm/AUTHORS
deps/npm/doc/cli/dedupe.md [new file with mode: 0644]
deps/npm/doc/cli/index.md
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 [new file with mode: 0644]
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/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/list.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/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/dedupe.js [new file with mode: 0644]
deps/npm/lib/npm.js
deps/npm/lib/publish.js
deps/npm/lib/utils/error-handler.js
deps/npm/lib/utils/fetch.js
deps/npm/lib/utils/find-prefix.js
deps/npm/lib/view.js
deps/npm/man/man1/dedupe.1 [new file with mode: 0644]
deps/npm/man/man1/index.1
deps/npm/man/man1/list.1
deps/npm/man/man1/npm.1
deps/npm/man/man3/npm.3
deps/npm/node_modules/couch-login/couch-login.js
deps/npm/node_modules/couch-login/package.json
deps/npm/node_modules/mkdirp/.gitignore.orig [deleted file]
deps/npm/node_modules/mkdirp/.gitignore.rej [deleted file]
deps/npm/node_modules/mkdirp/examples/pow.js.orig [deleted file]
deps/npm/node_modules/mkdirp/examples/pow.js.rej [deleted file]
deps/npm/node_modules/mkdirp/index.js
deps/npm/node_modules/mkdirp/package.json
deps/npm/node_modules/node-gyp/addon.gypi
deps/npm/node_modules/node-gyp/lib/build.js
deps/npm/node_modules/node-gyp/lib/node-gyp.js
deps/npm/node_modules/node-gyp/package.json
deps/npm/node_modules/node-uuid/.npmignore [deleted file]
deps/npm/node_modules/node-uuid/LICENSE.md [deleted file]
deps/npm/node_modules/node-uuid/README.md [deleted file]
deps/npm/node_modules/node-uuid/package.json [deleted file]
deps/npm/node_modules/node-uuid/uuid.js [deleted file]
deps/npm/node_modules/npm-registry-client/README.md
deps/npm/node_modules/npm-registry-client/index.js
deps/npm/node_modules/npm-registry-client/lib/adduser.js
deps/npm/node_modules/npm-registry-client/lib/get.js
deps/npm/node_modules/npm-registry-client/lib/publish.js
deps/npm/node_modules/npm-registry-client/lib/request.js
deps/npm/node_modules/npm-registry-client/lib/star.js
deps/npm/node_modules/npm-registry-client/package.json
deps/npm/node_modules/npm-registry-client/test/retries.js
deps/npm/node_modules/npmconf/npmconf.js
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/read-package-json/read-json.js
deps/npm/node_modules/read/README.md
deps/npm/node_modules/read/lib/read.js
deps/npm/node_modules/read/node_modules/mute-stream/mute.js
deps/npm/node_modules/read/node_modules/mute-stream/package.json
deps/npm/node_modules/read/node_modules/mute-stream/test/basic.js
deps/npm/node_modules/read/package.json
deps/npm/node_modules/read/test/basic.js
deps/npm/node_modules/read/test/defaults.js
deps/npm/node_modules/read/test/many.js
deps/npm/node_modules/request/README.md
deps/npm/node_modules/request/aws2.js [deleted file]
deps/npm/node_modules/request/main.js
deps/npm/node_modules/request/package.json
deps/npm/node_modules/request/tests/server.js
deps/npm/node_modules/request/tests/test-body.js
deps/npm/node_modules/request/tests/test-defaults.js
deps/npm/node_modules/request/tests/test-follow-all-303.js [new file with mode: 0644]
deps/npm/node_modules/request/tests/test-follow-all.js [new file with mode: 0644]
deps/npm/node_modules/request/tests/test-https-strict.js
deps/npm/node_modules/request/tests/test-https.js
deps/npm/node_modules/request/tests/test-params.js
deps/npm/node_modules/request/tests/test-protocol-changing-redirect.js [new file with mode: 0644]
deps/npm/node_modules/request/tests/test-s3.js [deleted file]
deps/npm/node_modules/request/tests/test-tunnel.js
deps/npm/node_modules/request/tunnel.js
deps/npm/package.json
deps/npm/test/tap/publish-config.js [new file with mode: 0644]

diff --git a/deps/npm/.travis.yml b/deps/npm/.travis.yml
deleted file mode 100644 (file)
index a385519..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-language: node_js
-before_install: "make &>out || cat out; rm out"
-node_js:
-  - 0.8
index 57fdf6a..d1306ad 100644 (file)
@@ -75,3 +75,5 @@ Don Park <donpark@docuverse.com>
 Kei Son <heyacct@gmail.com>
 Nicolas Morel <marsup@gmail.com>
 Mark Dube <markisdee@gmail.com>
+Maxim Bogushevich <boga1@mail.ru>
+Justin Beckwith <justbe@microsoft.com>
diff --git a/deps/npm/doc/cli/dedupe.md b/deps/npm/doc/cli/dedupe.md
new file mode 100644 (file)
index 0000000..220329a
--- /dev/null
@@ -0,0 +1,53 @@
+npm-dedupe(1) -- Reduce duplication
+===================================
+
+## SYNOPSIS
+
+    npm dedupe [package names...]
+
+## DESCRIPTION
+
+Searches the local package tree and attempts to simplify the overall
+structure by moving dependencies further up the tree, where they can
+be more effectively shared by multiple dependent packages.
+
+For example, consider this dependency graph:
+
+    a
+    +-- b <-- depends on c@1.0.x
+    |   `-- c@1.0.3
+    `-- d <-- depends on c@~1.0.9
+        `-- c@1.0.10
+
+In this case, `npm-dedupe(1)` will transform the tree to:
+
+    a
+    +-- b
+    +-- d
+    `-- c@1.0.10
+
+Because of the hierarchical nature of node's module lookup, b and d
+will both get their dependency met by the single c package at the root
+level of the tree.
+
+If a suitable version exists at the target location in the tree
+already, then it will be left untouched, but the other duplicates will
+be deleted.
+
+If no suitable version can be found, then a warning is printed, and
+nothing is done.
+
+If any arguments are supplied, then they are filters, and only the
+named packages will be touched.
+
+Note that this operation transforms the dependency tree, and may
+result in packages getting updated versions, perhaps from the npm
+registry.
+
+This feature is experimental, and may change in future versions.
+
+## SEE ALSO
+
+* npm-ls(1)
+* npm-update(1)
+* npm-install(1)
index ee88f3d..b2ffd13 100644 (file)
@@ -46,6 +46,10 @@ npm-index(1) -- Index of all npm documentation
 
  Manage the npm configuration file
 
+## npm-dedupe(1)
+
+ Reduce duplication
+
 ## npm-deprecate(1)
 
  Deprecate a version of a package
index d3650c2..8aa2d95 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.1.49</p>
+<p id="footer">bin &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 41c5d2b..219b803 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.1.49</p>
+<p id="footer">bugs &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 2003aca..43af61f 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.1.49</p>
+<p id="footer">commands &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 01e7203..b7fe10b 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.1.49</p>
+<p id="footer">config &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 2ba085b..7e72b88 100644 (file)
@@ -30,7 +30,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.1.49</p>
+<p id="footer">deprecate &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 79e6b98..f86ed17 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.1.49</p>
+<p id="footer">docs &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 576a866..a3fc44c 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.1.49</p>
+<p id="footer">edit &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 92dcc7d..cdcef38 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.1.49</p>
+<p id="footer">explore &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5ca7c75..1bc95b5 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.1.49</p>
+<p id="footer">help-search &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 720ef2b..eaf4cd3 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.1.49</p>
+<p id="footer">init &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 6faf410..48af7a1 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.1.49</p>
+<p id="footer">install &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 28334bc..440491a 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.1.49</p>
+<p id="footer">link &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 075e1aa..ca63551 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.1.49</p>
+<p id="footer">load &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 8eeb35b..38fc4e1 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.1.49</p>
+<p id="footer">ls &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e761aee..57e29b6 100644 (file)
@@ -24,7 +24,7 @@ npm.load(configObject, function (er, npm) {
 
 <h2 id="VERSION">VERSION</h2>
 
-<p>1.1.49</p>
+<p>1.1.55</p>
 
 <h2 id="DESCRIPTION">DESCRIPTION</h2>
 
@@ -91,7 +91,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.1.49</p>
+<p id="footer">npm &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e867abf..8e17b40 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.1.49</p>
+<p id="footer">outdated &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index df85a9d..1a1b366 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.1.49</p>
+<p id="footer">owner &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 0409c5c..bdc713f 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.1.49</p>
+<p id="footer">pack &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index ecc978e..a9324dc 100644 (file)
@@ -21,7 +21,7 @@
 
 <p>This function is not useful programmatically</p>
 </div>
-<p id="footer">prefix &mdash; npm@1.1.49</p>
+<p id="footer">prefix &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 6b9c3a8..a81dd49 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.1.49</p>
+<p id="footer">prune &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 48dce3f..6df771b 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.1.49</p>
+<p id="footer">publish &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index dcde5ae..664afdc 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.1.49</p>
+<p id="footer">rebuild &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 7edf903..3222a45 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.1.49</p>
+<p id="footer">restart &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 4237ca8..fe58151 100644 (file)
@@ -21,7 +21,7 @@
 
 <p>This function is not useful programmatically.</p>
 </div>
-<p id="footer">root &mdash; npm@1.1.49</p>
+<p id="footer">root &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 3ee6d88..f1026bc 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.1.49</p>
+<p id="footer">run-script &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 4d9ce2b..59c1eba 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.1.49</p>
+<p id="footer">search &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 2667ac6..4a010eb 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.1.49</p>
+<p id="footer">shrinkwrap &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 8f5c26f..d8b3837 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.1.49</p>
+<p id="footer">start &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 8888693..bad5cc7 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.1.49</p>
+<p id="footer">stop &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c9a6fc4..b19872f 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.1.49</p>
+<p id="footer">submodule &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index dc8e9e4..4c7e48b 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.1.49</p>
+<p id="footer">tag &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 9de5959..4725752 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.1.49</p>
+<p id="footer">test &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index dfdf1c6..7ebf4d2 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.1.49</p>
+<p id="footer">uninstall &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index ca4dd63..071d3bd 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.1.49</p>
+<p id="footer">unpublish &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5149b35..34badda 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.1.49</p>
+<p id="footer">update &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a4104a8..ba51d91 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.1.49</p>
+<p id="footer">version &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 056b39b..87249b0 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.1.49</p>
+<p id="footer">view &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 0c694ba..22ba012 100644 (file)
@@ -21,7 +21,7 @@
 
 <p>This function is not useful programmatically</p>
 </div>
-<p id="footer">whoami &mdash; npm@1.1.49</p>
+<p id="footer">whoami &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c97a90d..48744c9 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.1.49</p>
+<p id="footer"><a href="../doc/README.html">README</a> &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 4eddcd1..f75c5f0 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.1.49</p>
+<p id="footer">adduser &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 211c2aa..e913367 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.1.49</p>
+<p id="footer">bin &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e933cac..337913d 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.1.49</p>
+<p id="footer">bugs &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index d15f2ea..79b481d 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.1.49</p>
+<p id="footer">build &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 40f049e..eb0767e 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.1.49</p>
+<p id="footer">bundle &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index f4dfc77..69225b4 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.1.49</p>
+<p id="footer">cache &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 87c98d4..a304351 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.1.49</p>
+<p id="footer">changelog &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b13fee0..00d8485 100644 (file)
@@ -180,7 +180,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.1.49</p>
+<p id="footer">coding-style &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 34084fa..3b06ec7 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.1.49</p>
+<p id="footer">completion &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 86dbd2b..d7410da 100644 (file)
@@ -748,7 +748,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.1.49</p>
+<p id="footer">config &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
diff --git a/deps/npm/html/doc/dedupe.html b/deps/npm/html/doc/dedupe.html
new file mode 100644 (file)
index 0000000..f549081
--- /dev/null
@@ -0,0 +1,92 @@
+<!doctype html>
+<html>
+  <title>dedupe</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/dedupe.html">dedupe</a></h1> <p>Reduce duplication</p>
+
+<h2 id="SYNOPSIS">SYNOPSIS</h2>
+
+<pre><code>npm dedupe [package names...]</code></pre>
+
+<h2 id="DESCRIPTION">DESCRIPTION</h2>
+
+<p>Searches the local package tree and attempts to simplify the overall
+structure by moving dependencies further up the tree, where they can
+be more effectively shared by multiple dependent packages.</p>
+
+<p>For example, consider this dependency graph:</p>
+
+<pre><code>a
++-- b &lt;-- depends on c@1.0.x
+|   `-- c@1.0.3
+`-- d &lt;-- depends on c@~1.0.9
+    `-- c@1.0.10</code></pre>
+
+<p>In this case, <code><a href="../doc/dedupe.html">dedupe(1)</a></code> will transform the tree to:</p>
+
+<pre><code>a
++-- b
++-- d
+`-- c@1.0.10</code></pre>
+
+<p>Because of the hierarchical nature of node&#39;s module lookup, b and d
+will both get their dependency met by the single c package at the root
+level of the tree.</p>
+
+<p>If a suitable version exists at the target location in the tree
+already, then it will be left untouched, but the other duplicates will
+be deleted.</p>
+
+<p>If no suitable version can be found, then a warning is printed, and
+nothing is done.</p>
+
+<p>If any arguments are supplied, then they are filters, and only the
+named packages will be touched.</p>
+
+<p>Note that this operation transforms the dependency tree, and may
+result in packages getting updated versions, perhaps from the npm
+registry.</p>
+
+<p>This feature is experimental, and may change in future versions.</p>
+
+<h2 id="SEE-ALSO">SEE ALSO</h2>
+
+<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.1.55</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 68f7d30..b21e768 100644 (file)
@@ -29,7 +29,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.1.49</p>
+<p id="footer">deprecate &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a6c30b0..dfebc19 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.1.49</p>
+<p id="footer">developers &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5cda8b1..ffd47c6 100644 (file)
@@ -80,7 +80,7 @@ license statement)</li><li>Illegal content.</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.1.49</p>
+<p id="footer">disputes &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 887cfdd..c02c1bd 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.1.49</p>
+<p id="footer">docs &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index ab81081..5f2ec47 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.1.49</p>
+<p id="footer">edit &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 90d8d68..9bac57c 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.1.49</p>
+<p id="footer">explore &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index f9337fc..9a0063e 100644 (file)
@@ -241,7 +241,7 @@ We&#39;ll have someone kick it or something.</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.1.49</p>
+<p id="footer">faq &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c5ab5d4..fd92980 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.1.49</p>
+<p id="footer">folders &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c1780e7..bfd5d3a 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.1.49</p>
+<p id="footer">help-search &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index df582ef..dec4a9f 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.1.49</p>
+<p id="footer">help &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e430b5b..2ceb2b6 100644 (file)
 
 <p> Manage the npm configuration file</p>
 
+<h2 id="npm-dedupe-1"><a href="../doc/dedupe.html">dedupe(1)</a></h2>
+
+<p> Reduce duplication</p>
+
 <h2 id="npm-deprecate-1"><a href="../doc/deprecate.html">deprecate(1)</a></h2>
 
 <p> Deprecate a version of a package</p>
 
 <p> Display npm username</p>
 </div>
-<p id="footer">index &mdash; npm@1.1.49</p>
+<p id="footer">index &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5fed647..322e63c 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.1.49</p>
+<p id="footer">init &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 257a45c..502e2be 100644 (file)
@@ -133,7 +133,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.1.49</p>
+<p id="footer">install &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index cdeeaa1..f26d01e 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.1.49</p>
+<p id="footer">json &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index fc95392..443e928 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.1.49</p>
+<p id="footer">link &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b17f6fc..eeff3ab 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.1.49 /path/to/npm
+<pre><code>npm@1.1.55 /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">list &mdash; npm@1.1.49</p>
+<p id="footer">list &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 83324b9..4ddfb3a 100644 (file)
@@ -14,7 +14,7 @@
 
 <h2 id="VERSION">VERSION</h2>
 
-<p>1.1.49</p>
+<p>1.1.55</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.1.49</p>
+<p id="footer">npm &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 607bdd0..a399607 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.1.49</p>
+<p id="footer">outdated &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index c2991ba..00239e4 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.1.49</p>
+<p id="footer">owner &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index f7223ce..178c7fe 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.1.49</p>
+<p id="footer">pack &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 4c74d1f..8dece47 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.1.49</p>
+<p id="footer">prefix &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 05bd29b..edbcf34 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.1.49</p>
+<p id="footer">prune &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index d028b84..184543d 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.1.49</p>
+<p id="footer">publish &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index ca1ad33..88d1dc3 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.1.49</p>
+<p id="footer">rebuild &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 5ef97da..1ff9fdf 100644 (file)
@@ -97,7 +97,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.1.49</p>
+<p id="footer">registry &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 024122a..c2b2fe1 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.1.49</p>
+<p id="footer">removing-npm &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 251780c..d9c4c15 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.1.49</p>
+<p id="footer">restart &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index fc8ecad..210f22e 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.1.49</p>
+<p id="footer">root &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index d28e1b2..3bcba2d 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.1.49</p>
+<p id="footer">run-script &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e71d621..441418d 100644 (file)
@@ -177,7 +177,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.1.49</p>
+<p id="footer">scripts &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e002a40..ff21fe7 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.1.49</p>
+<p id="footer">search &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 46bce35..ee114b9 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.1.49</p>
+<p id="footer">semver &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index de942cc..884f674 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.1.49</p>
+<p id="footer">shrinkwrap &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b06ce6a..2e0fa1d 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.1.49</p>
+<p id="footer">star &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 792c5ef..b80fd81 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.1.49</p>
+<p id="footer">start &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index a73dc1c..800fa1d 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.1.49</p>
+<p id="footer">stop &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 45660e8..3b58ed9 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.1.49</p>
+<p id="footer">submodule &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b42386d..1cfeeba 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.1.49</p>
+<p id="footer">tag &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 93a49d0..2189043 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.1.49</p>
+<p id="footer">test &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 6b3c715..cbc5835 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.1.49</p>
+<p id="footer">uninstall &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index e1a6560..36442c8 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.1.49</p>
+<p id="footer">unpublish &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 64a0a82..10053a7 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.1.49</p>
+<p id="footer">update &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index b9a0acd..b6269a5 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.1.49</p>
+<p id="footer">version &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 0742a1f..5877aae 100644 (file)
@@ -88,7 +88,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.1.49</p>
+<p id="footer">view &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
index 1d4ee84..342e4d1 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.1.49</p>
+<p id="footer">whoami &mdash; npm@1.1.55</p>
 <script>
 ;(function () {
 var wrapper = document.getElementById("wrapper")
diff --git a/deps/npm/lib/dedupe.js b/deps/npm/lib/dedupe.js
new file mode 100644 (file)
index 0000000..9a35790
--- /dev/null
@@ -0,0 +1,334 @@
+// traverse the node_modules/package.json tree
+// looking for duplicates.  If any duplicates are found,
+// then move them up to the highest level necessary
+// in order to make them no longer duplicated.
+//
+// This is kind of ugly, and really highlights the need for
+// much better "put pkg X at folder Y" abstraction.  Oh well,
+// whatever.  Perfect enemy of the good, and all that.
+
+var fs = require("fs")
+var asyncMap = require("slide").asyncMap
+var path = require("path")
+var readJson = require("read-package-json")
+var archy = require("archy")
+var util = require("util")
+var RegClient = require("npm-registry-client")
+var npmconf = require("npmconf")
+var npm = require("npm")
+var semver = require("semver")
+var npm = require("npm")
+var rimraf = require("rimraf")
+var log = require("npmlog")
+var npm = require("./npm.js")
+
+module.exports = dedupe
+
+dedupe.usage = "npm dedupe [pkg pkg...]"
+
+function dedupe (args, silent, cb) {
+  if (typeof silent === "function") cb = silent, silent = false
+  var dryrun = false
+  if (npm.command.match(/^find/)) dryrun = true
+  return dedupe_(npm.prefix, args, {}, dryrun, silent, cb)
+}
+
+function dedupe_ (dir, filter, unavoidable, dryrun, silent, cb) {
+  readInstalled(path.resolve(dir), {}, null, function (er, data, counter) {
+    // find out which things are dupes
+    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) {
+      s[k] = []
+      return s
+    }, {})
+
+    // any that are unavoidable need to remain as they are.  don't even
+    // try to touch them or figure it out.  Maybe some day, we can do
+    // something a bit more clever here, but for now, just skip over it,
+    // and all its children.
+    ;(function U (obj) {
+      if (unavoidable[obj.name]) {
+        obj.unavoidable = true
+      }
+      if (obj.parent && obj.parent.unavoidable) {
+        obj.unavoidable = true
+      }
+      Object.keys(obj.children).forEach(function (k) {
+        U(obj.children[k])
+      })
+    })
+
+    // then collect them up and figure out who needs them
+    ;(function C (obj) {
+      if (dupes[obj.name] && !obj.unavoidable) {
+        dupes[obj.name].push(obj)
+        obj.duplicate = true
+      }
+      obj.dependents = whoDepends(obj)
+      Object.keys(obj.children).forEach(function (k) {
+        C(obj.children[k])
+      })
+    })(data)
+
+    if (dryrun) {
+      var k = Object.keys(dupes)
+      if (!k.length) return cb()
+      return npm.commands.ls(k, silent, cb)
+    }
+
+    var summary = Object.keys(dupes).map(function (n) {
+      return [n, dupes[n].filter(function (d) {
+        return d && d.parent && !d.parent.duplicate && !d.unavoidable
+      }).map(function M (d) {
+        return [d.path, d.version, d.dependents.map(function (k) {
+          return [k.path, k.version, k.dependencies[d.name] || ""]
+        })]
+      })]
+    }).map(function (item) {
+      var name = item[0]
+      var set = item[1]
+
+      var ranges = set.map(function (i) {
+        return i[2].map(function (d) {
+          return d[2]
+        })
+      }).reduce(function (l, r) {
+        return l.concat(r)
+      }, []).map(function (v, i, set) {
+        if (set.indexOf(v) !== i) return false
+        return v
+      }).filter(function (v) {
+        return v !== false
+      })
+
+      var locs = set.map(function (i) {
+        return i[0]
+      })
+
+      var versions = set.map(function (i) {
+        return i[1]
+      }).filter(function (v, i, set) {
+        return set.indexOf(v) === i
+      })
+
+      var has = set.map(function (i) {
+        return [i[0], i[1]]
+      }).reduce(function (set, kv) {
+        set[kv[0]] = kv[1]
+        return set
+      }, {})
+
+      var loc = locs.length ? locs.reduce(function (a, b) {
+        // a=/path/to/node_modules/foo/node_modules/bar
+        // b=/path/to/node_modules/elk/node_modules/bar
+        // ==/path/to/node_modules/bar
+        a = a.split(/\/node_modules\//)
+        b = b.split(/\/node_modules\//)
+        var name = a.pop()
+        b.pop()
+        // find the longest chain that both A and B share.
+        // then push the name back on it, and join by /node_modules/
+        var res = []
+        for (var i = 0, al = a.length, bl = b.length; i < al && i < bl && a[i] === b[i]; i++);
+        return a.slice(0, i).concat(name).join("/node_modules/")
+      }) : undefined
+
+      return [item[0], { item: item
+                       , ranges: ranges
+                       , locs: locs
+                       , loc: loc
+                       , has: has
+                       , versions: versions
+                       }]
+    }).filter(function (i) {
+      return i[1].loc
+    })
+
+    findVersions(npm, summary, function (er, set) {
+      if (er) return cb(er)
+      if (!set.length) return cb()
+      installAndRetest(set, filter, dir, unavoidable, silent, cb)
+    })
+  })
+}
+
+function installAndRetest (set, filter, dir, unavoidable, silent, cb) {
+  //return cb(null, set)
+  var remove = []
+
+  asyncMap(set, function (item, cb) {
+    // [name, has, loc, locMatch, regMatch, others]
+    var name = item[0]
+    var has = item[1]
+    var where = item[2]
+    var locMatch = item[3]
+    var regMatch = item[4]
+    var others = item[5]
+
+    // nothing to be done here.  oh well.  just a conflict.
+    if (!locMatch && !regMatch) {
+      log.warn("unavoidable conflict", item[0], item[1])
+      log.warn("unavoidable conflict", "Not de-duplicating")
+      unavoidable[item[0]] = true
+      return cb()
+    }
+
+    // nothing to do except to clean up the extraneous deps
+    if (locMatch && has[where] === locMatch) {
+      remove.push.apply(remove, others)
+      return cb()
+    }
+
+    if (regMatch) {
+      var what = name + "@" + regMatch
+      // where is /path/to/node_modules/foo/node_modules/bar
+      // for package "bar", but we need it to be just
+      // /path/to/node_modules/foo
+      where = where.split(/\/node_modules\//)
+      where.pop()
+      where = where.join("/node_modules/")
+      remove.push.apply(remove, others)
+
+      return npm.commands.install(where, what, cb)
+    }
+
+    // hrm?
+    return cb(new Error("danger zone\n" + name + " " +
+                        + regMatch + " " + locMatch))
+
+  }, function (er, installed) {
+    if (er) return cb(er)
+    asyncMap(remove, rimraf, function (er) {
+      if (er) return cb(er)
+      remove.forEach(function (r) {
+        log.info("rm", r)
+      })
+      dedupe_(dir, filter, unavoidable, false, silent, cb)
+    })
+  })
+}
+
+function findVersions (npm, summary, cb) {
+  // now, for each item in the summary, try to find the maximum version
+  // that will satisfy all the ranges.  next step is to install it at
+  // the specified location.
+  asyncMap(summary, function (item, cb) {
+    var name = item[0]
+    var data = item[1]
+    var loc = data.loc
+    var locs = data.locs.filter(function (l) {
+      return l !== loc
+    })
+
+    // not actually a dupe, or perhaps all the other copies were
+    // children of a dupe, so this'll maybe be picked up later.
+    if (locs.length === 0) {
+      return cb()
+    }
+
+    // { <folder>: <version> }
+    var has = data.has
+
+    // the versions that we already have.
+    // if one of these is ok, then prefer to use that.
+    // otherwise, try fetching from the registry.
+    var versions = data.versions
+
+    var ranges = data.ranges
+    npm.registry.get(name, function (er, data) {
+      var regVersions = er ? [] : Object.keys(data.versions)
+      var locMatch = bestMatch(versions, ranges)
+      var regMatch = bestMatch(regVersions, ranges)
+
+      cb(null, [[name, has, loc, locMatch, regMatch, locs]])
+    })
+  }, cb)
+}
+
+function bestMatch (versions, ranges) {
+  return versions.filter(function (v) {
+    return !ranges.some(function (r) {
+      return !semver.satisfies(v, r)
+    })
+  }).sort(semver.compare).pop()
+}
+
+
+function readInstalled (dir, counter, parent, cb) {
+  var pkg, children, realpath
+
+  fs.realpath(dir, function (er, rp) {
+    realpath = rp
+    next()
+  })
+
+  readJson(path.resolve(dir, "package.json"), function (er, data) {
+    if (er) return cb() // not a package, probably.
+    counter[data.name] = counter[data.name] || 0
+    counter[data.name]++
+    pkg =
+      { _id: data._id
+      , name: data.name
+      , version: data.version
+      , dependencies: data.dependencies || {}
+      , optionalDependencies: data.optionalDependencies || {}
+      , devDependencies: data.devDependencies || {}
+      , bundledDependencies: data.bundledDependencies || []
+      , path: dir
+      , realPath: dir
+      , children: {}
+      , parent: parent
+      , family: Object.create(parent ? parent.family : null)
+      , unavoidable: false
+      , duplicate: false
+      }
+    if (parent) {
+      parent.children[data.name] = pkg
+      parent.family[data.name] = pkg
+    }
+    next()
+  })
+
+  fs.readdir(path.resolve(dir, "node_modules"), function (er, c) {
+    children = c || [] // error is ok, just means no children.
+    next()
+  })
+
+  function next () {
+    if (!children || !pkg || !realpath) return
+
+    // ignore devDependencies.  Just leave them where they are.
+    children = children.filter(function (c) {
+      return !pkg.devDependencies.hasOwnProperty(c)
+    })
+
+    pkg.realPath = realpath
+    if (pkg.realPath !== pkg.path) children = []
+    var d = path.resolve(dir, "node_modules")
+    asyncMap(children, function (child, cb) {
+      readInstalled(path.resolve(d, child), counter, pkg, cb)
+    }, function (er) {
+      cb(er, pkg, counter)
+    })
+  }
+}
+
+function whoDepends (pkg) {
+  var start = pkg.parent || pkg
+  return whoDepends_(pkg, [], start)
+}
+
+function whoDepends_ (pkg, who, test) {
+  if (test !== pkg &&
+      test.dependencies[pkg.name] &&
+      test.family[pkg.name] === pkg) {
+    who.push(test)
+  }
+  Object.keys(test.children).forEach(function (n) {
+    whoDepends_(pkg, who, test.children[n])
+  })
+  return who
+}
+
index 0a321b2..5728f73 100644 (file)
@@ -101,6 +101,8 @@ var commandCache = {}
               , "login": "adduser"
               , "add-user": "adduser"
               , "tst": "test"
+              , "find-dupes": "dedupe"
+              , "ddp": "dedupe"
               }
 
   , aliasNames = Object.keys(aliases)
@@ -116,6 +118,7 @@ var commandCache = {}
               , "prune"
               , "submodule"
               , "pack"
+              , "dedupe"
 
               , "rebuild"
               , "link"
@@ -308,28 +311,7 @@ function load (npm, cli, cb) {
         } catch (e) { token = null }
       }
 
-      npm.registry = new RegClient(
-        { registry: npm.config.get("registry")
-        , cache: npm.config.get("cache")
-        , auth: npm.config.get("_auth")
-        , token: token
-        , alwaysAuth: npm.config.get("always-auth")
-        , email: npm.config.get("email")
-        , proxy: npm.config.get("proxy")
-        , tag: npm.config.get("tag")
-        , ca: npm.config.get("ca")
-        , strictSSL: npm.config.get("strict-ssl")
-        , userAgent: npm.config.get("user-agent")
-        , E404: npm.E404
-        , EPUBLISHCONFLICT: npm.EPUBLISHCONFLICT
-        , log: log
-        , retries: npm.config.get("fetch-retries")
-        , retryFactor: npm.config.get("fetch-retry-factor")
-        , retryMinTimeout: npm.config.get("fetch-retry-mintimeout")
-        , retryMaxTimeout: npm.config.get("fetch-retry-maxtimeout")
-        , cacheMin: npm.config.get("cache-min")
-        , cacheMax: npm.config.get("cache-max")
-        })
+      npm.registry = new RegClient(npm.config)
 
       // save the token cookie in the config file
       if (npm.registry.couchLogin) {
@@ -378,15 +360,15 @@ function loadPrefix (npm, conf, cb) {
     }
   })
 
-  findPrefix(gp, function (er, gp) {
-    Object.defineProperty(npm, "globalPrefix",
-      { get : function () { return gp }
-      , set : function (r) { return gp = r }
-      , enumerable : true
-      })
-    // the prefix MUST exist, or else nothing works.
-    mkdir(gp, next)
-  })
+  gp = path.resolve(gp)
+  Object.defineProperty(npm, "globalPrefix",
+    { get : function () { return gp }
+    , set : function (r) { return gp = r }
+    , enumerable : true
+    })
+  // the prefix MUST exist, or else nothing works.
+  mkdir(gp, next)
+
 
   var i = 2
     , errState = null
index 51a9de7..a84b597 100644 (file)
@@ -2,7 +2,6 @@
 module.exports = publish
 
 var npm = require("./npm.js")
-  , registry = npm.registry
   , log = require("npmlog")
   , tar = require("./utils/tar.js")
   , path = require("path")
@@ -10,6 +9,8 @@ var npm = require("./npm.js")
   , fs = require("graceful-fs")
   , lifecycle = require("./utils/lifecycle.js")
   , chain = require("slide").chain
+  , Conf = require("npmconf").Conf
+  , RegClient = require("npm-registry-client")
 
 publish.usage = "npm publish <tarball>"
               + "\nnpm publish <folder>"
@@ -61,11 +62,11 @@ function publish_ (arg, data, isRetry, cachedir, cb) {
   if (!data) return cb(new Error("no package.json file found"))
 
   // check for publishConfig hash
+  var registry = npm.registry
   if (data.publishConfig) {
-    Object.keys(data.publishConfig).forEach(function (k) {
-      log.info("publishConfig", k + "=" + data.publishConfig[k])
-      npm.config.set(k, data.publishConfig[k])
-    })
+    var pubConf = new Conf(npm.config)
+    pubConf.unshift(data.publishConfig)
+    registry = new RegClient(pubConf)
   }
 
   data._npmVersion = npm.version
@@ -77,10 +78,6 @@ function publish_ (arg, data, isRetry, cachedir, cb) {
     ("This package has been marked as private\n"
     +"Remove the 'private' field from the package.json to publish it."))
 
-  regPublish(data, isRetry, arg, cachedir, cb)
-}
-
-function regPublish (data, isRetry, arg, cachedir, cb) {
   var tarball = cachedir + ".tgz"
   registry.publish(data, tarball, function (er) {
     if (er && er.code === "EPUBLISHCONFLICT"
index 68ede5f..7fabd69 100644 (file)
@@ -197,6 +197,12 @@ function errorHandler (er) {
               ,"Move it away, and try again."].join("\n"))
     break
 
+  case "ENEEDAUTH":
+    log.error("need auth", [er.message
+              ,"You need to authorize this machine using `npm adduser`"
+              ].join("\n"))
+    break
+
   case "ENOTSUP":
     if (er.required) {
       log.error("notsup", [er.message
index 6042abc..b988520 100644 (file)
@@ -65,9 +65,10 @@ function makeRequest (remote, fstr, headers) {
       "Auth required and none provided. Please run 'npm adduser'"))
   }
 
-  var proxy = npm.config.get( remote.protocol === "https:"
-                            ? "https-proxy"
-                            : "proxy")
+  var proxy
+  if (remote.protocol !== "https:" || !(proxy = npm.config.get("https-proxy"))) {
+    proxy = npm.config.get("proxy")
+  }
 
   var opts = { url: remote
              , proxy: proxy
index bc2c959..c3ff85f 100644 (file)
@@ -14,7 +14,6 @@ function findPrefix (p, cb_) {
   }
 
   p = path.resolve(p)
-  if (npm.config.get("global")) return cb(null, p)
   // if there's no node_modules folder, then
   // walk up until we hopefully find one.
   // if none anywhere, then use cwd.
index bdfd481..592d83d 100644 (file)
@@ -189,7 +189,7 @@ function printData (data, name, cb) {
     fields.forEach(function (f) {
       var d = cleanup(data[v][f])
       if (showVersions || showFields || typeof d !== "string") {
-        d = util.inspect(cleanup(data[v][f]), false, 5, true)
+        d = util.inspect(cleanup(data[v][f]), false, 5, npm.color)
       }
       if (f && showFields) f += " = "
       if (d.indexOf("\n") !== -1) d = "\n" + d
diff --git a/deps/npm/man/man1/dedupe.1 b/deps/npm/man/man1/dedupe.1
new file mode 100644 (file)
index 0000000..35b0d1d
--- /dev/null
@@ -0,0 +1,90 @@
+.\" Generated with Ronnjs 0.3.8
+.\" http://github.com/kapouer/ronnjs/
+.
+.TH "NPM\-DEDUPE" "1" "August 2012" "" ""
+.
+.SH "NAME"
+\fBnpm-dedupe\fR \-\- Reduce duplication
+.
+.SH "SYNOPSIS"
+.
+.nf
+npm dedupe [package names\.\.\.]
+.
+.fi
+.
+.SH "DESCRIPTION"
+Searches the local package tree and attempts to simplify the overall
+structure by moving dependencies further up the tree, where they can
+be more effectively shared by multiple dependent packages\.
+.
+.P
+For example, consider this dependency graph:
+.
+.IP "" 4
+.
+.nf
+a
++\-\- b <\-\- depends on c@1\.0\.x
+|   `\-\- c@1\.0\.3
+`\-\- d <\-\- depends on c@~1\.0\.9
+    `\-\- c@1\.0\.10
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In this case, \fBnpm help dedupe\fR will transform the tree to:
+.
+.IP "" 4
+.
+.nf
+a
++\-\- b
++\-\- d
+`\-\- c@1\.0\.10
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Because of the hierarchical nature of node\'s module lookup, b and d
+will both get their dependency met by the single c package at the root
+level of the tree\.
+.
+.P
+If a suitable version exists at the target location in the tree
+already, then it will be left untouched, but the other duplicates will
+be deleted\.
+.
+.P
+If no suitable version can be found, then a warning is printed, and
+nothing is done\.
+.
+.P
+If any arguments are supplied, then they are filters, and only the
+named packages will be touched\.
+.
+.P
+Note that this operation transforms the dependency tree, and may
+result in packages getting updated versions, perhaps from the npm
+registry\.
+.
+.P
+This feature is experimental, and may change in future versions\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+npm help ls
+.
+.IP "\(bu" 4
+npm help update
+.
+.IP "\(bu" 4
+npm help install
+.
+.IP "" 0
+
index ec2d9a9..2f72291 100644 (file)
@@ -39,6 +39,9 @@
 .SH "npm help config"
  Manage the npm configuration file
 .
+.SH "npm help dedupe"
+ Reduce duplication
+.
 .SH "npm help deprecate"
  Deprecate a version of a package
 .
index 65db45c..8808310 100644 (file)
@@ -29,7 +29,7 @@ For example, running \fBnpm ls promzard\fR in npm\'s source tree will show:
 .IP "" 4
 .
 .nf
-npm@1.1.49 /path/to/npm
+npm@1.1.55 /path/to/npm
 â””─┬ init\-package\-json@0\.0\.4
   â””── promzard@0\.1\.5
 .
index 522d451..c0253a1 100644 (file)
@@ -14,7 +14,7 @@ npm <command> [args]
 .fi
 .
 .SH "VERSION"
-1.1.49
+1.1.55
 .
 .SH "DESCRIPTION"
 npm is the package manager for the Node JavaScript platform\.  It puts
index cdbccc9..87072e4 100644 (file)
@@ -21,7 +21,7 @@ npm\.load(configObject, function (er, npm) {
 .fi
 .
 .SH "VERSION"
-1.1.49
+1.1.55
 .
 .SH "DESCRIPTION"
 This is the API documentation for npm\.
index cd7b12c..be037f0 100644 (file)
@@ -283,7 +283,7 @@ function logout (cb) {
   , req = { uri: u, headers: h, json: true }
 
   request.del(req, function (er, res, data) {
-    if (er || res.statusCode !== 200) {
+    if (er || (res.statusCode !== 200 && res.statusCode !== 404)) {
       return cb(er, res, data)
     }
 
index a485486..7d62b73 100644 (file)
@@ -6,7 +6,7 @@
   },
   "name": "couch-login",
   "description": "A module for doing logged-in requests to a couchdb server",
-  "version": "0.1.9",
+  "version": "0.1.10",
   "repository": {
     "type": "git",
     "url": "git://github.com/isaacs/couch-login.git"
@@ -22,6 +22,6 @@
     "tap": "~0.2.4"
   },
   "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.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",
-  "_id": "couch-login@0.1.9",
-  "_from": "couch-login@latest"
+  "_id": "couch-login@0.1.10",
+  "_from": "couch-login@~0.1.9"
 }
diff --git a/deps/npm/node_modules/mkdirp/.gitignore.orig b/deps/npm/node_modules/mkdirp/.gitignore.orig
deleted file mode 100644 (file)
index 9303c34..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules/
-npm-debug.log
\ No newline at end of file
diff --git a/deps/npm/node_modules/mkdirp/.gitignore.rej b/deps/npm/node_modules/mkdirp/.gitignore.rej
deleted file mode 100644 (file)
index 69244ff..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
---- /dev/null
-+++ .gitignore
-@@ -0,0 +1,2 @@
-+node_modules/
-+npm-debug.log
\ No newline at end of file
diff --git a/deps/npm/node_modules/mkdirp/examples/pow.js.orig b/deps/npm/node_modules/mkdirp/examples/pow.js.orig
deleted file mode 100644 (file)
index 7741462..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-var mkdirp = require('mkdirp');
-
-mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
-    if (err) console.error(err)
-    else console.log('pow!')
-});
diff --git a/deps/npm/node_modules/mkdirp/examples/pow.js.rej b/deps/npm/node_modules/mkdirp/examples/pow.js.rej
deleted file mode 100644 (file)
index 81e7f43..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
---- examples/pow.js
-+++ examples/pow.js
-@@ -1,6 +1,15 @@
--var mkdirp = require('mkdirp').mkdirp;
-+var mkdirp = require('../').mkdirp,
-+    mkdirpSync = require('../').mkdirpSync;
- mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
-     if (err) console.error(err)
-     else console.log('pow!')
- });
-+
-+try {
-+  mkdirpSync('/tmp/bar/foo/baz', 0755);
-+  console.log('double pow!');
-+}
-+catch (ex) {
-+  console.log(ex);
-+}
\ No newline at end of file
index 874b310..fda6de8 100644 (file)
@@ -27,18 +27,10 @@ function mkdirP (p, mode, f, made) {
                 });
                 break;
 
-            case 'EISDIR':
-            case 'EPERM':
-                // Operation not permitted or already is a dir.
-                // This is the error you get when trying to mkdir('c:/')
-                // on windows, or mkdir('/') on unix.  Make sure it's a
-                // dir by falling through to the EEXIST case.
-            case 'EROFS':
-                // a read-only file system.
-                // However, the dir could already exist, in which case
-                // the EROFS error will be obscuring a EEXIST!
-                // Fallthrough to that case.
-            case 'EEXIST':
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
                 fs.stat(p, function (er2, stat) {
                     // if the stat fails, then that's super weird.
                     // let the original error be the failure reason.
@@ -46,10 +38,6 @@ function mkdirP (p, mode, f, made) {
                     else cb(null, made);
                 });
                 break;
-
-            default:
-                cb(er, made);
-                break;
         }
     });
 }
@@ -74,7 +62,10 @@ mkdirP.sync = function sync (p, mode, made) {
                 sync(p, mode, made);
                 break;
 
-            case 'EEXIST' :
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
                 var stat;
                 try {
                     stat = fs.statSync(p);
@@ -84,9 +75,6 @@ mkdirP.sync = function sync (p, mode, made) {
                 }
                 if (!stat.isDirectory()) throw err0;
                 break;
-            default :
-                throw err0
-                break;
         }
     }
 
index f779658..0d1eb98 100644 (file)
@@ -1,7 +1,7 @@
 {
   "name": "mkdirp",
   "description": "Recursively mkdir, like `mkdir -p`",
-  "version": "0.3.3",
+  "version": "0.3.4",
   "author": {
     "name": "James Halliday",
     "email": "mail@substack.net",
@@ -14,7 +14,7 @@
   ],
   "repository": {
     "type": "git",
-    "url": "git://github.com/substack/node-mkdirp.git"
+    "url": "http://github.com/substack/node-mkdirp.git"
   },
   "scripts": {
     "test": "tap test/*.js"
   "engines": {
     "node": "*"
   },
-  "_npmUser": {
-    "name": "isaacs",
-    "email": "i@izs.me"
-  },
-  "_id": "mkdirp@0.3.3",
-  "dependencies": {},
-  "optionalDependencies": {},
-  "_engineSupported": true,
-  "_npmVersion": "1.1.24",
-  "_nodeVersion": "v0.7.10-pre",
-  "_defaultsLoaded": true,
-  "_from": "mkdirp@0.3"
+  "readme": "mkdirp\n======\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\nexample\n=======\n\npow.js\n------\n    var mkdirp = require('mkdirp');\n    \n    mkdirp('/tmp/foo/bar/baz', function (err) {\n        if (err) console.error(err)\n        else console.log('pow!')\n    });\n\nOutput\n    pow!\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\nmethods\n=======\n\nvar mkdirp = require('mkdirp');\n\nmkdirp(dir, mode, cb)\n---------------------\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\nmkdirp.sync(dir, mode)\n----------------------\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n    npm install mkdirp\n\nlicense\n=======\n\nMIT/X11\n",
+  "_id": "mkdirp@0.3.4",
+  "_from": "mkdirp@~0.3.3"
 }
index 89e71c0..1573fa9 100644 (file)
@@ -15,6 +15,9 @@
       }],
       [ 'OS=="win"', {
         'libraries': [ '-l<(node_root_dir)/$(Configuration)/node.lib' ],
+        # 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=="freebsd" or OS=="openbsd" or OS=="solaris" or (OS=="linux" and target_arch!="ia32")', {
         'cflags': [ '-fPIC' ],
index dc0a120..01abdd5 100644 (file)
@@ -176,9 +176,13 @@ function build (gyp, argv, callback) {
       argv.push('/clp:Verbosity=minimal')
     }
 
-    // Turn off the Microsoft logo on Windows
     if (win) {
+      // Turn off the Microsoft logo on Windows
       argv.push('/nologo')
+
+      // Fix "warning MSB8012: TargetExt(.dll) does not match
+      // the Linker's OutputFile property value (.node)"
+      argv.push('/property:TargetExt=.node')
     }
 
     // Specify the build type, Release by default
index 26c8beb..58275ee 100644 (file)
@@ -83,6 +83,7 @@ proto.configDefs = {
   , proxy: String     // 'install'
   , nodedir: String   // 'configure'
   , loglevel: String  // everywhere
+  , python: String    // 'configure'
 }
 
 /**
index 7fa75a8..ab51941 100644 (file)
@@ -10,7 +10,7 @@
     "bindings",
     "gyp"
   ],
-  "version": "0.6.5",
+  "version": "0.6.7",
   "installVersion": 9,
   "author": {
     "name": "Nathan Rajlich",
@@ -45,6 +45,6 @@
     "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.2`][windows-python-v2.7.2] recommended, `v3.x.x` not yet supported)\n    * Microsoft Visual C++ ([Express][msvc] 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\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.2]: http://www.python.org/download/releases/2.7.2#download\n[msvc]: http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express\n[win7sdk]: http://www.microsoft.com/download/en/details.aspx?displayLang=en&id=8279\n",
-  "_id": "node-gyp@0.6.5",
+  "_id": "node-gyp@0.6.7",
   "_from": "node-gyp@~0.6.4"
 }
diff --git a/deps/npm/node_modules/node-uuid/.npmignore b/deps/npm/node_modules/node-uuid/.npmignore
deleted file mode 100644 (file)
index fd4f2b0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules
-.DS_Store
diff --git a/deps/npm/node_modules/node-uuid/LICENSE.md b/deps/npm/node_modules/node-uuid/LICENSE.md
deleted file mode 100644 (file)
index bcdddf9..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Copyright (c) 2010 Robert Kieffer
-
-Dual licensed under the [MIT](http://en.wikipedia.org/wiki/MIT_License) and [GPL](http://en.wikipedia.org/wiki/GNU_General_Public_License) licenses.
diff --git a/deps/npm/node_modules/node-uuid/README.md b/deps/npm/node_modules/node-uuid/README.md
deleted file mode 100644 (file)
index a44d9a7..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-# node-uuid
-
-Simple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.
-
-Features:
-
-* Generate RFC4122 version 1 or version 4 UUIDs
-* Runs in node.js and all browsers.
-* Cryptographically strong random # generation on supporting platforms
-* 1.1K minified and gzip'ed  (Want something smaller?  Check this [crazy shit](https://gist.github.com/982883) out! )
-* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)
-
-## Getting Started
-
-Install it in your browser:
-
-```html
-<script src="uuid.js"></script>
-```
-
-Or in node.js:
-
-```
-npm install node-uuid
-```
-
-```javascript
-var uuid = require('node-uuid');
-```
-
-Then create some ids ...
-
-```javascript
-// Generate a v1 (time-based) id
-uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
-
-// Generate a v4 (random) id
-uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
-```
-
-## API
-
-### uuid.v1([`options` [, `buffer` [, `offset`]]])
-
-Generate and return a RFC4122 v1 (timestamp-based) UUID.
-
-* `options` - (Object) Optional uuid state to apply. Properties may include:
-
-  * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomnly generated ID.  See note 1.
-  * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence.  Default: An internally maintained clockseq is used.
-  * `msecs` - (Number | Date) Time in milliseconds since unix Epoch.  Default: The current time is used.
-  * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.
-
-* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
-* `offset` - (Number) Starting index in `buffer` at which to begin writing.
-
-Returns `buffer`, if specified, otherwise the string form of the UUID
-
-Notes:
-
-1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)
-
-Example: Generate string UUID with fully-specified options
-
-```javascript
-uuid.v1({
-  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
-  clockseq: 0x1234,
-  msecs: new Date('2011-11-01').getTime(),
-  nsecs: 5678
-});   // -> "710b962e-041c-11e1-9234-0123456789ab"
-```
-
-Example: In-place generation of two binary IDs
-
-```javascript
-// Generate two ids in an array
-var arr = new Array(32); // -> []
-uuid.v1(null, arr, 0);   // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
-uuid.v1(null, arr, 16);  // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
-
-// Optionally use uuid.unparse() to get stringify the ids
-uuid.unparse(buffer);    // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'
-uuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'
-```
-
-### uuid.v4([`options` [, `buffer` [, `offset`]]])
-
-Generate and return a RFC4122 v4 UUID.
-
-* `options` - (Object) Optional uuid state to apply. Properties may include:
-
-  * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values
-  * `rng` - (Function) Random # generator to use.  Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.
-
-* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
-* `offset` - (Number) Starting index in `buffer` at which to begin writing.
-
-Returns `buffer`, if specified, otherwise the string form of the UUID
-
-Example: Generate string UUID with fully-specified options
-
-```javascript
-uuid.v4({
-  random: [
-    0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,
-    0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36
-  ]
-});
-// -> "109156be-c4fb-41ea-b1b4-efe1671c5836"
-```
-
-Example: Generate two IDs in a single buffer
-
-```javascript
-var buffer = new Array(32); // (or 'new Buffer' in node.js)
-uuid.v4(null, buffer, 0);
-uuid.v4(null, buffer, 16);
-```
-
-### uuid.parse(id[, buffer[, offset]])
-### uuid.unparse(buffer[, offset])
-
-Parse and unparse UUIDs
-
-  * `id` - (String) UUID(-like) string
-  * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used
-  * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0
-
-Example parsing and unparsing a UUID string
-
-```javascript
-var bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> <Buffer 79 7f f0 43 11 eb 11 e1 80 d6 51 09 98 75 5d 10>
-var string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'
-```
-
-### uuid.noConflict()
-
-(Browsers only) Set `uuid` property back to it's previous value.
-
-Returns the node-uuid object.
-
-Example:
-
-```javascript
-var myUuid = uuid.noConflict();
-myUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
-```
-
-## Deprecated APIs
-
-Support for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.
-
-### uuid([format [, buffer [, offset]]])
-
-uuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).
-
-### uuid.BufferClass
-
-The class of container created when generating binary uuid data if no buffer argument is specified.  This is expected to go away, with no replacement API.
-
-## Testing
-
-In node.js
-
-```
-> cd test
-> node uuid.js
-```
-
-In Browser
-
-```
-open test/test.html
-```
-
-### Benchmarking
-
-Requires node.js
-
-```
-npm install uuid uuid-js
-node test/benchmark.js
-```
-
-For a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)
-
-For browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).
-
-## Release notes
-
-v1.3.2:
-* Improve tests and handling of v1() options (Issue #24)
-* Expose RNG option to allow for perf testing with different generators
-
-v1.3:
-* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!
-* Support for node.js crypto API
-* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code
diff --git a/deps/npm/node_modules/node-uuid/package.json b/deps/npm/node_modules/node-uuid/package.json
deleted file mode 100644 (file)
index 9df0da9..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "name"          : "node-uuid",
-  "description"   : "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.",
-  "url"           : "http://github.com/broofa/node-uuid",
-  "keywords"      : ["uuid", "guid", "rfc4122"],
-  "author"        : "Robert Kieffer <robert@broofa.com>",
-  "contributors"  : [
-    {"name": "Christoph Tavan <dev@tavan.de>", "github": "https://github.com/ctavan"}
-  ],
-  "dependencies"  : {},
-  "lib"           : ".",
-  "main"          : "./uuid.js",
-  "version"       : "1.3.3"
-}
diff --git a/deps/npm/node_modules/node-uuid/uuid.js b/deps/npm/node_modules/node-uuid/uuid.js
deleted file mode 100644 (file)
index 27f1d12..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-//     node-uuid/uuid.js
-//
-//     Copyright (c) 2010 Robert Kieffer
-//     Dual licensed under the MIT and GPL licenses.
-//     Documentation and details at https://github.com/broofa/node-uuid
-(function() {
-  var _global = this;
-
-  // Unique ID creation requires a high quality random # generator, but
-  // Math.random() does not guarantee "cryptographic quality".  So we feature
-  // detect for more robust APIs, normalizing each method to return 128-bits
-  // (16 bytes) of random data.
-  var mathRNG, nodeRNG, whatwgRNG;
-
-  // Math.random()-based RNG.  All platforms, very fast, unknown quality
-  var _rndBytes = new Array(16);
-  mathRNG = function() {
-    var r, b = _rndBytes, i = 0;
-
-    for (var i = 0, r; i < 16; i++) {
-      if ((i & 0x03) == 0) r = Math.random() * 0x100000000;
-      b[i] = r >>> ((i & 0x03) << 3) & 0xff;
-    }
-
-    return b;
-  }
-
-  // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
-  // WebKit only (currently), moderately fast, high quality
-  if (_global.crypto && crypto.getRandomValues) {
-    var _rnds = new Uint32Array(4);
-    whatwgRNG = function() {
-      crypto.getRandomValues(_rnds);
-
-      for (var c = 0 ; c < 16; c++) {
-        _rndBytes[c] = _rnds[c >> 2] >>> ((c & 0x03) * 8) & 0xff;
-      }
-      return _rndBytes;
-    }
-  }
-
-  // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
-  // Node.js only, moderately fast, high quality
-  try {
-    var _rb = require('crypto').randomBytes;
-    nodeRNG = _rb && function() {
-      return _rb(16);
-    };
-  } catch (e) {}
-
-  // Select RNG with best quality
-  var _rng = nodeRNG || whatwgRNG || mathRNG;
-
-  // Buffer class to use
-  var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
-
-  // Maps for number <-> hex string conversion
-  var _byteToHex = [];
-  var _hexToByte = {};
-  for (var i = 0; i < 256; i++) {
-    _byteToHex[i] = (i + 0x100).toString(16).substr(1);
-    _hexToByte[_byteToHex[i]] = i;
-  }
-
-  // **`parse()` - Parse a UUID into it's component bytes**
-  function parse(s, buf, offset) {
-    var i = (buf && offset) || 0, ii = 0;
-
-    buf = buf || [];
-    s.toLowerCase().replace(/[0-9a-f]{2}/g, function(byte) {
-      if (ii < 16) { // Don't overflow!
-        buf[i + ii++] = _hexToByte[byte];
-      }
-    });
-
-    // Zero out remaining bytes if string was short
-    while (ii < 16) {
-      buf[i + ii++] = 0;
-    }
-
-    return buf;
-  }
-
-  // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
-  function unparse(buf, offset) {
-    var i = offset || 0, bth = _byteToHex;
-    return  bth[buf[i++]] + bth[buf[i++]] +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] +
-            bth[buf[i++]] + bth[buf[i++]] +
-            bth[buf[i++]] + bth[buf[i++]];
-  }
-
-  // **`v1()` - Generate time-based UUID**
-  //
-  // Inspired by https://github.com/LiosK/UUID.js
-  // and http://docs.python.org/library/uuid.html
-
-  // random #'s we need to init node and clockseq
-  var _seedBytes = _rng();
-
-  // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
-  var _nodeId = [
-    _seedBytes[0] | 0x01,
-    _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
-  ];
-
-  // Per 4.2.2, randomize (14 bit) clockseq
-  var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
-
-  // Previous uuid creation time
-  var _lastMSecs = 0, _lastNSecs = 0;
-
-  // See https://github.com/broofa/node-uuid for API details
-  function v1(options, buf, offset) {
-    var i = buf && offset || 0;
-    var b = buf || [];
-
-    options = options || {};
-
-    var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
-
-    // UUID timestamps are 100 nano-second units since the Gregorian epoch,
-    // (1582-10-15 00:00).  JSNumbers aren't precise enough for this, so
-    // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
-    // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
-    var msecs = options.msecs != null ? options.msecs : new Date().getTime();
-
-    // Per 4.2.1.2, use count of uuid's generated during the current clock
-    // cycle to simulate higher resolution clock
-    var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
-
-    // Time since last uuid creation (in msecs)
-    var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
-
-    // Per 4.2.1.2, Bump clockseq on clock regression
-    if (dt < 0 && options.clockseq == null) {
-      clockseq = clockseq + 1 & 0x3fff;
-    }
-
-    // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
-    // time interval
-    if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
-      nsecs = 0;
-    }
-
-    // Per 4.2.1.2 Throw error if too many uuids are requested
-    if (nsecs >= 10000) {
-      throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
-    }
-
-    _lastMSecs = msecs;
-    _lastNSecs = nsecs;
-    _clockseq = clockseq;
-
-    // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
-    msecs += 12219292800000;
-
-    // `time_low`
-    var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
-    b[i++] = tl >>> 24 & 0xff;
-    b[i++] = tl >>> 16 & 0xff;
-    b[i++] = tl >>> 8 & 0xff;
-    b[i++] = tl & 0xff;
-
-    // `time_mid`
-    var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
-    b[i++] = tmh >>> 8 & 0xff;
-    b[i++] = tmh & 0xff;
-
-    // `time_high_and_version`
-    b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
-    b[i++] = tmh >>> 16 & 0xff;
-
-    // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
-    b[i++] = clockseq >>> 8 | 0x80;
-
-    // `clock_seq_low`
-    b[i++] = clockseq & 0xff;
-
-    // `node`
-    var node = options.node || _nodeId;
-    for (var n = 0; n < 6; n++) {
-      b[i + n] = node[n];
-    }
-
-    return buf ? buf : unparse(b);
-  }
-
-  // **`v4()` - Generate random UUID**
-
-  // See https://github.com/broofa/node-uuid for API details
-  function v4(options, buf, offset) {
-    // Deprecated - 'format' argument, as supported in v1.2
-    var i = buf && offset || 0;
-
-    if (typeof(options) == 'string') {
-      buf = options == 'binary' ? new BufferClass(16) : null;
-      options = null;
-    }
-    options = options || {};
-
-    var rnds = options.random || (options.rng || _rng)();
-
-    // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
-    rnds[6] = (rnds[6] & 0x0f) | 0x40;
-    rnds[8] = (rnds[8] & 0x3f) | 0x80;
-
-    // Copy bytes to buffer, if provided
-    if (buf) {
-      for (var ii = 0; ii < 16; ii++) {
-        buf[i + ii] = rnds[ii];
-      }
-    }
-
-    return buf || unparse(rnds);
-  }
-
-  // Export public API
-  var uuid = v4;
-  uuid.v1 = v1;
-  uuid.v4 = v4;
-  uuid.parse = parse;
-  uuid.unparse = unparse;
-  uuid.BufferClass = BufferClass;
-
-  // Export RNG options
-  uuid.mathRNG = mathRNG;
-  uuid.nodeRNG = nodeRNG;
-  uuid.whatwgRNG = whatwgRNG;
-
-  if (typeof(module) != 'undefined') {
-    // Play nice with node.js
-    module.exports = uuid;
-  } else {
-    // Play nice with browsers
-    var _previousRoot = _global.uuid;
-
-    // **`noConflict()` - (browser only) to reset global 'uuid' var**
-    uuid.noConflict = function() {
-      _global.uuid = _previousRoot;
-      return uuid;
-    }
-    _global.uuid = uuid;
-  }
-}());
index dbeb944..4b180a0 100644 (file)
@@ -8,7 +8,7 @@ It handles all the caching and HTTP calls.
 
 ```javascript
 var RegClient = require('npm-registry-client')
-var client = new RegClient(options)
+var client = new RegClient(config)
 
 client.get("npm", "latest", 1000, function (er, data, raw, res) {
   // error is an error if there was a problem.
@@ -18,29 +18,43 @@ client.get("npm", "latest", 1000, function (er, data, raw, res) {
 })
 ```
 
-# Options
+# Configuration
+
+This program is designed to work with
+[npmconf](https://npmjs.org/package/npmconf), but you can also pass in
+a plain-jane object with the appropriate configs, and it'll shim it
+for you.  Any configuration thingie that has get/set/del methods will
+also be accepted.
 
 * `registry` **Required** {String} URL to the registry
 * `cache` **Required** {String} Path to the cache folder
-* `alwaysAuth` {Boolean} Auth even for GET requests.
+* `always-auth` {Boolean} Auth even for GET requests.
 * `auth` {String} A base64-encoded `username:password`
 * `email` {String} User's email address
 * `tag` {String} The default tag to use when publishing new packages.
   Default = `"latest"`
 * `ca` {String} Cerficate signing authority certificates to trust.
-* `strictSSL` {Boolean} Whether or not to be strict with SSL
+* `strict-ssl` {Boolean} Whether or not to be strict with SSL
   certificates.  Default = `true`
-* `userAgent` {String} User agent header to send.  Default =
+* `user-agent` {String} User agent header to send.  Default =
   `"node/{process.version}"`
 * `log` {Object} The logger to use.  Defaults to `require("npmlog")` if
   that works, otherwise logs are disabled.
-* `retries` {Number} Number of times to retry on GET failures.
+* `fetch-retries` {Number} Number of times to retry on GET failures.
   Default=2
-* `retryFactor` {Number} `factor` setting for `node-retry`. Default=10
-* `retryMinTimeout` {Number} `minTimeout` setting for `node-retry`.
+* `fetch-retry-factor` {Number} `factor` setting for `node-retry`. Default=10
+* `fetch-retry-mintimeout` {Number} `minTimeout` setting for `node-retry`.
   Default=10000 (10 seconds)
-* `retryMaxTimeout` {Number} `maxTimeout` setting for `node-retry`.
+* `fetch-retry-maxtimeout` {Number} `maxTimeout` setting for `node-retry`.
   Default=60000 (60 seconds)
+* `proxy` {URL} The url to proxy requests through.
+* `https-proxy` {URL} The url to proxy https requests through.
+  Defaults to be the same as `proxy` if unset.
+* `_auth` {String} The base64-encoded authorization header.
+* `username` `_password` {String} Username/password to use to generate
+  `_auth` if not supplied.
+* `_token` {Object} A token for use with
+  [couch-login](https://npmjs.org/package/couch-login)
 
 # client.request(method, where, [what], [etag], [nofollow], cb)
 
index 377f787..8d321b8 100644 (file)
@@ -19,78 +19,48 @@ try {
 
 function noop () {}
 
-function RegClient (options) {
+function RegClient (conf) {
+  // accept either a plain-jane object, or a npmconf object
+  // with a "get" method.
+  if (typeof conf.get !== 'function') {
+    var data = conf
+    conf = { get: function (k) { return data[k] }
+           , set: function (k, v) { data[k] = v }
+           , del: function (k) { delete data[k] } }
+  }
+
+  this.conf = conf
+
   // if provided, then the registry needs to be a url.
   // if it's not provided, then we're just using the cache only.
-  var registry = options.registry
+  var registry = conf.get('registry')
   if (registry) {
     registry = url.parse(registry)
     if (!registry.protocol) throw new Error(
       'Invalid registry: ' + registry.url)
-    this.registry = registry.href
-    if (this.registry.slice(-1) !== '/') {
-      this.registry += '/'
+    registry = registry.href
+    if (registry.slice(-1) !== '/') {
+      registry += '/'
     }
+    this.conf.set('registry', registry)
   } else {
-    this.registry = null
+    registry = null
   }
 
-  this.retries = options.retries || 2
-  this.retryFactor = options.retryFactor || 10
-  this.retryMinTimeout = options.retryMinTimeout || 10000
-  this.retryMaxTimeout = options.retryMaxTimeout || 60000
-
-  this.cache = options.cache
-  if (!this.cache) throw new Error("Cache dir is required")
-
-  this.alwaysAuth = options.alwaysAuth || false
+  if (!conf.get('cache')) throw new Error("Cache dir is required")
 
-  this.auth = options.auth || null
-  if (this.auth) {
-    var a = new Buffer(this.auth, "base64").toString()
-    a = a.split(":")
-    this.username = a.shift()
-    this.password = a.join(":")
-  } else {
-    this.username = options.username
-    this.password = options.password
-
-    // if username and password are set, but auth isn't, use them.
-    if (this.username && this.password) {
-      var a = this.username + ":" + this.password
-      this.auth = new Buffer(a, "utf8").toString("base64")
-    }
-  }
-
-  if (this.auth && !this.alwaysAuth && this.registry) {
+  var auth = this.conf.get('_auth')
+  var alwaysAuth = this.conf.get('always-auth')
+  if (auth && !alwaysAuth && registry) {
     // if we're always authing, then we just send the
     // user/pass on every thing.  otherwise, create a
     // session, and use that.
-    this.token = options.token
-    this.couchLogin = new CouchLogin(this.registry, this.token)
-    this.couchLogin.proxy = this.proxy
-  }
-
-  this.email = options.email || null
-  this.defaultTag = options.tag || "latest"
-
-  this.ca = options.ca || null
-
-  this.strictSSL = options.strictSSL
-  if (this.strictSSL === undefined) this.strictSSL = true
-
-  this.userAgent = options.userAgent
-  if (this.userAgent === undefined) {
-    this.userAgent = 'node/' + process.version
+    var token = this.conf.get('_token')
+    this.couchLogin = new CouchLogin(registry, token)
+    this.couchLogin.proxy = this.conf.get('proxy')
   }
 
-  this.cacheMin = options.cacheMin || 0
-  this.cacheMax = options.cacheMax || Infinity
-
-  this.proxy = options.proxy
-  this.httpsProxy = options.httpsProxy || options.proxy
-
-  this.log = options.log || npmlog
+  this.log = conf.log || conf.get('log') || npmlog
 }
 
 require('fs').readdirSync(__dirname + "/lib").forEach(function (f) {
index f940ca1..7106e44 100644 (file)
@@ -1,18 +1,12 @@
-
 module.exports = adduser
 
-var uuid = require("node-uuid")
-  , crypto
-
-try {
-} catch (ex) {}
+var crypto = require('crypto')
 
 function sha (s) {
   return crypto.createHash("sha1").update(s).digest("hex")
 }
 
 function adduser (username, password, email, cb) {
-  if (!crypto) crypto = require("crypto")
 
   password = ("" + (password || "")).trim()
   if (!password) return cb(new Error("No password supplied."))
@@ -27,7 +21,7 @@ function adduser (username, password, email, cb) {
     "Sorry, ':' chars are not allowed in passwords.\n"+
     "See <https://issues.apache.org/jira/browse/COUCHDB-969> for why."))
 
-  var salt = uuid()
+  var salt = crypto.randomBytes(30).toString('hex')
     , userobj =
       { name : username
       , salt : salt
@@ -41,18 +35,18 @@ function adduser (username, password, email, cb) {
 
   // pluck off any other username/password/token.  it needs to be the
   // same as the user we're becoming now.  replace them on error.
-  var pre = { username: this.username
-            , password: this.password
-            , auth: this.auth
-            , token: this.token }
-
-  this.token = null
+  var pre = { username: this.conf.get('username')
+            , password: this.conf.get('_password')
+            , auth: this.conf.get('_auth')
+            , token: this.conf.get('_token') }
+
+  this.conf.del('_token')
+  this.conf.del('username')
+  this.conf.del('_auth')
+  this.conf.del('_password')
   if (this.couchLogin) {
     this.couchLogin.token = null
   }
-  this.username = null
-  this.password = null
-  this.auth = null
 
   cb = done.call(this, cb, pre)
 
@@ -72,13 +66,13 @@ function adduser (username, password, email, cb) {
     , function (error, data, json, response) {
         // if it worked, then we just created a new user, and all is well.
         // but if we're updating a current record, then it'll 409 first
-        if (error && !this.auth) {
+        if (error && !this.conf.get('_auth')) {
           // must be trying to re-auth on a new machine.
           // use this info as auth
           var b = new Buffer(username + ":" + password)
-          this.auth = b.toString("base64")
-          this.username = username
-          this.password = password
+          this.conf.set('_auth', b.toString("base64"))
+          this.conf.set('username', username)
+          this.conf.set('_password', password)
         }
 
         if (!error || !response || response.statusCode !== 409) {
@@ -114,16 +108,16 @@ function done (cb, pre) {
     }
 
     // there was some kind of error, re-instate previous auth/token/etc.
-    this.token = pre.token
+    this.conf.set('_token', pre.token)
     if (this.couchLogin) {
-      this.couchLogin.token = this.token
+      this.couchLogin.token = pre.token
       if (this.couchLogin.tokenSet) {
         this.couchLogin.tokenSet(pre.token)
       }
     }
-    this.username = pre.username
-    this.password = pre.password
-    this.auth = pre.auth
+    this.conf.set('username', pre.username)
+    this.conf.set('_password', pre.password)
+    this.conf.set('_auth', pre.auth)
 
     this.log.verbose("adduser", "back", [error, data, json])
     if (!error) {
index 835eb4c..584a986 100644 (file)
@@ -12,10 +12,10 @@ function get (uri, timeout, nofollow, staleOk, cb) {
   if (typeof cb !== "function") cb = timeout, timeout = -1
   if (typeof cb !== "function") cb = version, version = null
 
-  timeout = Math.min(timeout, this.cacheMax)
-  timeout = Math.max(timeout, this.cacheMin)
+  timeout = Math.min(timeout, this.conf.get('cache-max') || 0)
+  timeout = Math.max(timeout, this.conf.get('cache-min') || Infinity)
 
-  if (!this.registry) timeout = Infinity
+  if (!this.conf.get('registry')) timeout = Infinity
 
   if ( process.env.COMP_CWORD !== undefined
     && process.env.COMP_LINE !== undefined
@@ -29,7 +29,7 @@ function get (uri, timeout, nofollow, staleOk, cb) {
     return requestAll.call(this, cb)
   }
 
-  var cache = path.join(this.cache, uri, ".cache.json")
+  var cache = path.join(this.conf.get('cache'), uri, ".cache.json")
   fs.stat(cache, function (er, stat) {
     if (!er) fs.readFile(cache, function (er, data) {
       try { data = JSON.parse(data) }
@@ -41,9 +41,9 @@ function get (uri, timeout, nofollow, staleOk, cb) {
 }
 
 function requestAll (cb) {
-  var cache = path.join(this.cache, "/-/all", ".cache.json")
+  var cache = path.join(this.conf.get('cache'), "/-/all", ".cache.json")
 
-  mkdir(path.join(this.cache, "-", "all"), function (er) {
+  mkdir(path.join(this.conf.get('cache'), "-", "all"), function (er) {
     fs.readFile(cache, function (er, data) {
       if (er) return requestAll_.call(this, 0, {}, cb)
       try {
@@ -74,7 +74,7 @@ function requestAll_ (c, data, cb) {
     uri = "/-/all"
   }
 
-  var cache = path.join(this.cache, "-/all", ".cache.json")
+  var cache = path.join(this.conf.get('cache'), "-/all", ".cache.json")
   this.request('GET', uri, function (er, updates, _, res) {
     if (er) return cb(er, data)
     var headers = res.headers
@@ -143,20 +143,20 @@ function get_ (uri, timeout, cache, stat, data, nofollow, staleOk, cb) {
 }
 
 function saveToCache (cache, data, saved) {
-  if (this.cacheStat) {
-    var cs = this.cacheStat
+  if (this._cacheStat) {
+    var cs = this._cacheStat
     return saveToCache_.call(this, cache, data, cs.uid, cs.gid, saved)
   }
-  fs.stat(this.cache, function (er, st) {
+  fs.stat(this.conf.get('cache'), function (er, st) {
     if (er) {
       return fs.stat(process.env.HOME || "", function (er, st) {
         // if this fails, oh well.
         if (er) return saved()
-        this.cacheStat = st
+        this._cacheStat = st
         return saveToCache.call(this, cache, data, saved)
       }.bind(this))
     }
-    this.cacheStat = st || { uid: null, gid: null }
+    this._cacheStat = st || { uid: null, gid: null }
     return saveToCache.call(this, cache, data, saved)
   }.bind(this))
 }
index 11aa599..b44b801 100644 (file)
@@ -6,8 +6,14 @@ var path = require("path")
 
 function publish (data, tarball, cb) {
 
-  if (!this.email || !this.auth || !this.username) {
-    return cb(new Error("auth and email required for publishing"))
+  var email = this.conf.get('email')
+  var auth = this.conf.get('_auth')
+  var username = this.conf.get('username')
+
+  if (!email || !auth || !username) {
+    var er = new Error("auth and email required for publishing")
+    er.code = 'ENEEDAUTH'
+    return cb(er)
   }
 
   // add the dist-url to the data, pointing at the tarball.
@@ -15,7 +21,7 @@ function publish (data, tarball, cb) {
   // if the {version} is already there, then fail.
   // then:
   // PUT the data to {config.registry}/{data.name}/{data.version}
-  var registry = this.registry
+  var registry = this.conf.get('registry')
 
   var fullData =
     { _id : data.name
@@ -25,8 +31,8 @@ function publish (data, tarball, cb) {
     , versions : {}
     , readme: data.readme || ""
     , maintainers :
-      [ { name : this.username
-        , email : this.email
+      [ { name : username
+        , email : email
         }
       ]
     }
@@ -58,7 +64,7 @@ function publish (data, tarball, cb) {
     var dataURI = encodeURIComponent(data.name)
                 + "/" + encodeURIComponent(data.version)
 
-    var tag = data.tag || this.defaultTag || "latest"
+    var tag = data.tag || this.conf.get('tag') || "latest"
     dataURI += "/-tag/" + tag
 
     // let's see what versions are already published.
index 486226a..8d90572 100644 (file)
@@ -13,7 +13,8 @@ function regRequest (method, where, what, etag, nofollow, cb_) {
   if (typeof cb_ !== "function") cb_ = etag, etag = null
   if (typeof cb_ !== "function") cb_ = what, what = null
 
-  if (!this.registry) return cb(new Error(
+  var registry = this.conf.get('registry')
+  if (!registry) return cb(new Error(
     "No registry url provided: " + method + " " + where))
 
   // Since there are multiple places where an error could occur,
@@ -29,13 +30,11 @@ function regRequest (method, where, what, etag, nofollow, cb_) {
     return cb(new Error("favicon.ico isn't a package, it's a picture."))
   }
 
-  var registry = this.registry
-
   var adduserChange = /^\/?-\/user\/org\.couchdb\.user:([^\/]+)\/-rev/
   , adduserNew = /^\/?-\/user\/org\.couchdb\.user:([^\/]+)/
   , nu = where.match(adduserNew)
   , uc = where.match(adduserChange)
-  , isUpload = what || this.alwaysAuth
+  , isUpload = what || this.conf.get('always-auth')
   , isDel = method === "DELETE"
   , authRequired = isUpload && !nu || uc || isDel
 
@@ -62,27 +61,30 @@ function regRequest (method, where, what, etag, nofollow, cb_) {
   }
 
   var remote = url.parse(where)
-  , auth = this.auth
+  , auth = this.conf.get('_auth')
 
-  if (authRequired && !this.alwaysAuth) {
+  if (authRequired && !this.conf.get('always-auth')) {
     var couch = this.couchLogin
-    , token = couch && (this.token || couch.token)
+    , token = couch && (this.conf.get('_token') || couch.token)
     , validToken = token && couch.valid(token)
 
     if (!validToken) token = null
-    else this.token = token
+    else this.conf.set('_token', token)
 
     if (couch && !token) {
       // login to get a valid token
-      var a = { name: this.username, password: this.password }
+      var a = { name: this.conf.get('username'),
+                password: this.conf.get('_password') }
       var args = arguments
       return this.couchLogin.login(a, function (er, cr, data) {
         if (er || !couch.valid(couch.token)) {
           er = er || new Error('login error')
           return cb(er, cr, data)
         }
-        this.token = this.couchLogin.token
-        return regRequest.call(this, method, where, what, etag, nofollow, cb_)
+        this.conf.set('_token', this.couchLogin.token)
+        return regRequest.call(this,
+                               method, where, what,
+                               etag, nofollow, cb_)
       }.bind(this))
     }
   }
@@ -101,11 +103,12 @@ function regRequest (method, where, what, etag, nofollow, cb_) {
   // Tuned to spread 3 attempts over about a minute.
   // See formula at <https://github.com/tim-kos/node-retry>.
   var operation = retry.operation({
-    retries: this.retries,
-    factor: this.retryFactor,
-    minTimeout: this.retryMinTimeout,
-    maxTimeout: this.retryMaxTimeout
+    retries: this.conf.get('fetch-retries') || 2,
+    factor: this.conf.get('fetch-retry-factor'),
+    minTimeout: this.conf.get('fetch-retry-mintimeout') || 10000,
+    maxTimeout: this.conf.get('fetch-retry-maxtimeout') || 60000
   })
+
   var self = this
   operation.attempt(function (currentAttempt) {
     self.log.info("retry", "registry request attempt " + currentAttempt
@@ -118,8 +121,8 @@ function regRequest (method, where, what, etag, nofollow, cb_) {
       var timeout = statusCode === 408
       var serverError = statusCode >= 500
       var statusRetry = !statusCode || timeout || serverError
-      if (reauth && this.auth && this.token) {
-        this.token = null
+      if (reauth && this.conf.get('_auth') && this.conf.get('_token')) {
+        this.conf.del('_token')
         this.couchLogin.token = null
         return regRequest.call(this, method, where, what, etag, nofollow, cb_)
       }
@@ -140,10 +143,12 @@ function makeRequest (method, remote, where, what, etag, nofollow, tok, cb_) {
     cb_.apply(null, arguments)
   }
 
+  var strict = this.conf.get('strict-ssl')
+  if (strict === undefined) strict = true
   var opts = { url: remote
              , method: method
-             , ca: this.ca
-             , strictSSL: this.strictSSL }
+             , ca: this.conf.get('ca')
+             , strictSSL: strict }
     , headers = opts.headers = {}
   if (etag) {
     this.log.verbose("etag", etag)
@@ -156,10 +161,12 @@ function makeRequest (method, remote, where, what, etag, nofollow, tok, cb_) {
 
   headers.accept = "application/json"
 
-  headers["user-agent"] = this.userAgent
+  headers["user-agent"] = this.conf.get('user-agent') ||
+                          'node/' + process.version
 
-  opts.proxy = remote.protocol === "https:"
-             ? this.httpsProxy : this.proxy
+  var p = this.conf.get('proxy')
+  var sp = this.conf.get('https-proxy') || p
+  opts.proxy = remote.protocol === "https:" ? sp : p
 
   // figure out wth 'what' is
   if (what) {
@@ -259,7 +266,7 @@ function requestDone (method, where, cb) {
         , caches = p.map(function (part) {
             return _ = path.join(_, part)
           }).map(function (cache) {
-            return path.join(this.cache, cache, ".cache.json")
+            return path.join(this.conf.get('cache'), cache, ".cache.json")
           }, this)
 
       // if the method is DELETE, then also remove the thing itself.
@@ -267,7 +274,7 @@ function requestDone (method, where, cb) {
       // That's what you get for deleting stuff.  Don't do that.
       if (method === "DELETE") {
         p = p.slice(0, p.indexOf("-rev"))
-        caches.push(path.join(this.cache, p.join("/")))
+        caches.push(path.join(this.conf.get('cache'), p.join("/")))
       }
 
       asyncMap(caches, rm, function () {})
index 36a6612..5b7ab4a 100644 (file)
@@ -2,7 +2,7 @@
 module.exports = star
 
 function star (package, starred, cb) {
-  if (!this.username) return cb(new Error(
+  if (!this.conf.get('username')) return cb(new Error(
     "Must be logged in to star/unstar packages"))
 
   var users = {}
@@ -16,10 +16,10 @@ function star (package, starred, cb) {
 
     if (starred) {
       this.log.info("starring", fullData._id)
-      fullData.users[this.username] = true
+      fullData.users[this.conf.get('username')] = true
       this.log.verbose("starring", fullData)
     } else {
-      delete fullData.users[this.username]
+      delete fullData.users[this.conf.get('username')]
       this.log.info("unstarring", fullData._id)
       this.log.verbose("unstarring", fullData)
     }
index 709027a..7ee3487 100644 (file)
@@ -6,7 +6,7 @@
   },
   "name": "npm-registry-client",
   "description": "Client for the npm registry",
-  "version": "0.1.4",
+  "version": "0.2.5",
   "repository": {
     "url": "git://github.com/isaacs/npm-registry-client"
   },
@@ -15,7 +15,6 @@
     "test": "tap test/*.js"
   },
   "dependencies": {
-    "node-uuid": "~1.3.3",
     "request": "~2.9.202",
     "graceful-fs": "~1.1.8",
     "semver": "~1.0.14",
@@ -34,7 +33,7 @@
     "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(options)\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# Options\n\n* `registry` **Required** {String} URL to the registry\n* `cache` **Required** {String} Path to the cache folder\n* `alwaysAuth` {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* `strictSSL` {Boolean} Whether or not to be strict with SSL\n  certificates.  Default = `true`\n* `userAgent` {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* `retries` {Number} Number of times to retry on GET failures.\n  Default=2\n* `retryFactor` {Number} `factor` setting for `node-retry`. Default=10\n* `retryMinTimeout` {Number} `minTimeout` setting for `node-retry`.\n  Default=10000 (10 seconds)\n* `retryMaxTimeout` {Number} `maxTimeout` setting for `node-retry`.\n  Default=60000 (60 seconds)\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",
-  "_id": "npm-registry-client@0.1.4",
-  "_from": "npm-registry-client@latest"
+  "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",
+  "_id": "npm-registry-client@0.2.5",
+  "_from": "npm-registry-client@~0.2.4"
 }
index 500abf2..8f0e63f 100644 (file)
@@ -5,9 +5,9 @@ var pkg = { _id: 'some-package@1.2.3',
             name: 'some-package',
             version: '1.2.3' }
 var client = new RC({
-    retries: 6
-  , retryMinTimeout: 10
-  , retryMaxTimeout: 100
+    'fetch-retries': 6
+  , 'fetch-retry-mintimeout': 10
+  , 'fetch-retry-maxtimeout': 100
   , cache: __dirname + '/fixtures/cache'
   , registry: 'http://localhost:' + server.port })
 
index da4b422..41ba251 100644 (file)
@@ -9,6 +9,7 @@ var path = require('path')
 var nopt = require('nopt')
 var ini = require('ini')
 var Octal = configDefs.Octal
+var mkdirp = require('mkdirp')
 
 exports.load = load
 exports.Conf = Conf
@@ -174,18 +175,23 @@ Conf.prototype.save = function (where, cb) {
   then = then.bind(this)
   done = done.bind(this)
   this._saving ++
+
   var mode = where === 'user' ? 0600 : 0666
   if (!data.trim())
     fs.unlink(target.path, done)
   else {
-    fs.writeFile(target.path, data, 'utf8', function (er) {
+    mkdirp(path.dirname(target.path), function (er) {
       if (er)
         return then(er)
-      if (where === 'user' && myUid && myGid)
-        fs.chown(target.path, +myUid, +myGid, then)
-      else
-        then()
-    }.bind(this))
+      fs.writeFile(target.path, data, 'utf8', function (er) {
+        if (er)
+          return then(er)
+        if (where === 'user' && myUid && myGid)
+          fs.chown(target.path, +myUid, +myGid, then)
+        else
+          then()
+      })
+    })
   }
 
   function then (er) {
index 3a50fe9..8995ddf 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "npmconf",
-  "version": "0.0.6",
+  "version": "0.0.8",
   "description": "The config thing npm uses",
   "main": "npmconf.js",
   "directories": {
@@ -10,6 +10,8 @@
     "config-chain": "~1.1.1",
     "inherits": "~1.0.0",
     "once": "~1.1.1",
+    "mkdirp": "~0.3.3",
+    "osenv": "0.0.3",
     "nopt": "~2.0.0"
   },
   "devDependencies": {},
@@ -37,6 +39,6 @@
     "nopt": "~2.0.0"
   },
   "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",
-  "_id": "npmconf@0.0.6",
-  "_from": "npmconf@latest"
+  "_id": "npmconf@0.0.8",
+  "_from": "npmconf@~0.0.6"
 }
index 3e703bf..b122b54 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.1",
+  "version": "0.0.2",
   "repository": {
     "type": "git",
     "url": "git://github.com/isaacs/read-installed"
@@ -27,6 +27,6 @@
     "url": "http://blog.izs.me/"
   },
   "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",
-  "_id": "read-installed@0.0.1",
-  "_from": "read-installed"
+  "_id": "read-installed@0.0.2",
+  "_from": "read-installed@0"
 }
index be39422..cb77dba 100644 (file)
@@ -286,6 +286,8 @@ function findUnmet (obj) {
                   +found.path+",\nwhich is version "+found.version
                   )
           found.invalid = true
+        } else {
+          found.extraneous = false
         }
         deps[d] = found
       }
index 42d0611..8e56b11 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "read-package-json",
-  "version": "0.1.3",
+  "version": "0.1.4",
   "author": {
     "name": "Isaac Z. Schlueter",
     "email": "i@izs.me",
@@ -31,6 +31,6 @@
     "graceful-fs": "~1.1.8"
   },
   "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",
-  "_id": "read-package-json@0.1.3",
-  "_from": "read-package-json@~0.1.1"
+  "_id": "read-package-json@0.1.4",
+  "_from": "read-package-json@~0.1.3"
 }
index 837c6b7..17e8b43 100644 (file)
@@ -254,7 +254,7 @@ function mans (file, data, cb) {
 function mans_ (file, data, mans, cb) {
                 var m = data.directories && data.directories.man
                 data.man = mans.map(function (mf) {
-                                return path.resolve(m, mf)
+                                return path.resolve(path.dirname(file), m, mf)
                 })
                 return cb(null, data)
 }
index 01aa8e7..2edefdf 100644 (file)
@@ -33,6 +33,21 @@ Every option is optional.
 If silent is true, and the input is a TTY, then read will set raw
 mode, and read character by character.
 
+## COMPATIBILITY
+
+This module works sort of with node 0.6.  It does not work with node
+versions less than 0.6.  It is best on node 0.8.
+
+On node version 0.6, it will remove all listeners on the input
+stream's `data` and `keypress` events, because the readline module did
+not fully clean up after itself in that version of node, and did not
+make it possible to clean up after it in a way that has no potential
+for side effects.
+
+Additionally, some of the readline options (like `terminal`) will not
+function in versions of node before 0.8, because they were not
+implemented in the builtin readline module.
+
 ## CONTRIBUTING
 
 Patches welcome.
index 4b0e303..4b8a422 100644 (file)
@@ -23,7 +23,13 @@ function read (opts, cb) {
   var def = opts.default || ''
   var terminal = !!(opts.terminal || output.isTTY)
   var rlOpts = { input: input, output: output, terminal: terminal }
-  var rl = readline.createInterface(rlOpts)
+
+  if (process.version.match(/^v0\.6/)) {
+    var rl = readline.createInterface(rlOpts.input, rlOpts.output)
+  } else {
+    var rl = readline.createInterface(rlOpts)
+  }
+
   var prompt = (opts.prompt || '').trim() + ' '
   var silent = opts.silent
   var editDef = false
@@ -69,6 +75,13 @@ function read (opts, cb) {
   function done () {
     called = true
     rl.close()
+
+    if (process.version.match(/^v0\.6/)) {
+      rl.input.removeAllListeners('data')
+      rl.input.removeAllListeners('keypress')
+      rl.input.pause()
+    }
+
     clearTimeout(timer)
     output.mute()
     output.end()
index f0c3550..7746618 100644 (file)
@@ -63,6 +63,21 @@ function setIsTTY (isTTY) {
   })
 }
 
+Object.defineProperty(MuteStream.prototype, 'rows', {
+  get: function () {
+    return( this._dest ? this._dest.rows
+          : this._src ? this._src.rows
+          : undefined )
+  }, enumerable: true, configurable: true })
+
+Object.defineProperty(MuteStream.prototype, 'columns', {
+  get: function () {
+    return( this._dest ? this._dest.columns
+          : this._src ? this._src.columns
+          : undefined )
+  }, enumerable: true, configurable: true })
+
+
 MuteStream.prototype.pipe = function (dest) {
   this._dest = dest
   return Stream.prototype.pipe.call(this, dest)
index ff942b8..629b5be 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "mute-stream",
-  "version": "0.0.2",
+  "version": "0.0.3",
   "main": "mute.js",
   "directories": {
     "test": "test"
@@ -28,9 +28,6 @@
   "license": "BSD",
   "description": "Bytes go in, but they don't come out (when muted).",
   "readme": "# mute-stream\n\nBytes go in, but they don't come out (when muted).\n\nThis is a basic pass-through stream, but when muted, the bytes are\nsilently dropped, rather than being passed through.\n\n## Usage\n\n```javascript\nvar MuteStream = require('mute-stream')\n\nvar ms = new MuteStream(options)\n\nms.pipe(process.stdout)\nms.write('foo') // writes 'foo' to stdout\nms.mute()\nms.write('bar') // does not write 'bar'\nms.unmute()\nms.write('baz') // writes 'baz' to stdout\n\n// can also be used to mute incoming data\nvar ms = new MuteStream\ninput.pipe(ms)\n\nms.on('data', function (c) {\n  console.log('data: ' + c)\n})\n\ninput.emit('data', 'foo') // logs 'foo'\nms.mute()\ninput.emit('data', 'bar') // does not log 'bar'\nms.unmute()\ninput.emit('data', 'baz') // logs 'baz'\n```\n\n## Options\n\nAll options are optional.\n\n* `replace` Set to a string to replace each character with the\n  specified string when muted.  (So you can show `****` instead of the\n  password, for example.)\n\n## ms.mute()\n\nSet `muted` to `true`.  Turns `.write()` into a no-op.\n\n## ms.unmute()\n\nSet `muted` to `false`\n\n## ms.isTTY\n\nTrue if the pipe destination is a TTY, or if the incoming pipe source is\na TTY.\n\n## Other stream methods...\n\nThe other standard readable and writable stream methods are all\navailable.  The MuteStream object acts as a facade to its pipe source\nand destination.\n",
-  "_id": "mute-stream@0.0.2",
-  "dist": {
-    "shasum": "75d4466df24a57e80fec806bda88561cd0560d2d"
-  },
+  "_id": "mute-stream@0.0.3",
   "_from": "mute-stream@~0.0.2"
 }
index 473f827..2d1f6ae 100644 (file)
@@ -89,17 +89,29 @@ tap.test('outgoing', function (t) {
 tap.test('isTTY', function (t) {
   var str = new PassThrough
   str.isTTY = true
+  str.columns=80
+  str.rows=24
 
   var ms = new MS
   t.equal(ms.isTTY, false)
+  t.equal(ms.columns, undefined)
+  t.equal(ms.rows, undefined)
   ms.pipe(str)
   t.equal(ms.isTTY, true)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
   str.isTTY = false
   t.equal(ms.isTTY, false)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
   str.isTTY = true
   t.equal(ms.isTTY, true)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
   ms.isTTY = false
   t.equal(ms.isTTY, false)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
 
   ms = new MS
   t.equal(ms.isTTY, false)
index 79e5b7c..f76034e 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "read",
-  "version": "1.0.3",
+  "version": "1.0.4",
   "main": "lib/read.js",
   "dependencies": {
     "mute-stream": "~0.0.2"
@@ -25,7 +25,7 @@
   "scripts": {
     "test": "tap test/*.js"
   },
-  "readme": "## read\n\nFor reading user input from stdin.\n\nSimilar to the `readline` builtin's `question()` method, but with a\nfew more features.\n\n## USAGE\n\n```javascript\nvar read = require(\"read\")\nread(options, callback)\n```\n\nThe callback gets called with either the user input, or the default\nspecified, or an error, as `callback(error, result, isDefault)`\nnode style.\n\n## OPTIONS\n\nEvery option is optional.\n\n* `prompt` What to write to stdout before reading input.\n* `silent` Don't echo the output as the user types it.\n* `replace` Replace silenced characters with the supplied character value.\n* `timeout` Number of ms to wait for user input before giving up.\n* `default` The default value if the user enters nothing.\n* `edit` Allow the user to edit the default value.\n* `terminal` Treat the output as a TTY, whether it is or not.\n* `stdin` Readable stream to get input data from. (default `process.stdin`)\n* `stdout` Writeable stream to write prompts to. (default: `process.stdout`)\n\nIf silent is true, and the input is a TTY, then read will set raw\nmode, and read character by character.\n\n## CONTRIBUTING\n\nPatches welcome.\n",
-  "_id": "read@1.0.3",
-  "_from": "read@~1"
+  "readme": "## read\n\nFor reading user input from stdin.\n\nSimilar to the `readline` builtin's `question()` method, but with a\nfew more features.\n\n## USAGE\n\n```javascript\nvar read = require(\"read\")\nread(options, callback)\n```\n\nThe callback gets called with either the user input, or the default\nspecified, or an error, as `callback(error, result, isDefault)`\nnode style.\n\n## OPTIONS\n\nEvery option is optional.\n\n* `prompt` What to write to stdout before reading input.\n* `silent` Don't echo the output as the user types it.\n* `replace` Replace silenced characters with the supplied character value.\n* `timeout` Number of ms to wait for user input before giving up.\n* `default` The default value if the user enters nothing.\n* `edit` Allow the user to edit the default value.\n* `terminal` Treat the output as a TTY, whether it is or not.\n* `stdin` Readable stream to get input data from. (default `process.stdin`)\n* `stdout` Writeable stream to write prompts to. (default: `process.stdout`)\n\nIf silent is true, and the input is a TTY, then read will set raw\nmode, and read character by character.\n\n## COMPATIBILITY\n\nThis module works sort of with node 0.6.  It does not work with node\nversions less than 0.6.  It is best on node 0.8.\n\nOn node version 0.6, it will remove all listeners on the input\nstream's `data` and `keypress` events, because the readline module did\nnot fully clean up after itself in that version of node, and did not\nmake it possible to clean up after it in a way that has no potential\nfor side effects.\n\nAdditionally, some of the readline options (like `terminal`) will not\nfunction in versions of node before 0.8, because they were not\nimplemented in the builtin readline module.\n\n## CONTRIBUTING\n\nPatches welcome.\n",
+  "_id": "read@1.0.4",
+  "_from": "read@~1.0.3"
 }
index c90c410..f5324b4 100644 (file)
@@ -5,6 +5,11 @@ if (process.argv[2] === 'child') {
   return child()
 }
 
+var CLOSE = 'close'
+if (process.version.match(/^v0\.6/)) {
+  CLOSE = 'exit'
+}
+
 var spawn = require('child_process').spawn
 
 tap.test('basic', function (t) {
@@ -31,7 +36,7 @@ tap.test('basic', function (t) {
     console.error('result %j', c.toString())
   })
 
-  child.on('close', function () {
+  child.on(CLOSE, function () {
     result = JSON.parse(result)
     t.same(result, {"user":"a user","pass":"a password","verify":"a password","passMatch":true})
     t.equal(output, 'Username: (test-user) Password: (<default hidden>) Password again: (<default hidden>) ')
index 6f7644d..f3335ac 100644 (file)
@@ -5,6 +5,11 @@ if (process.argv[2] === 'child') {
   return child()
 }
 
+var CLOSE = 'close'
+if (process.version.match(/^v0\.6/)) {
+  CLOSE = 'exit'
+}
+
 var spawn = require('child_process').spawn
 
 tap.test('defaults', function (t) {
@@ -31,7 +36,7 @@ tap.test('defaults', function (t) {
     console.error('result %j', c.toString())
   })
 
-  child.on('close', function () {
+  child.on(CLOSE, function () {
     result = JSON.parse(result)
     t.same(result, {"user":"test-user","pass":"test-pass","verify":"test-pass","passMatch":true})
     t.equal(output, 'Username: (test-user) Password: (<default hidden>) Password again: (<default hidden>) ')
index 0d32dae..2aaa586 100644 (file)
@@ -1,6 +1,11 @@
 var tap = require('tap')
 var read = require('../lib/read.js')
 
+var CLOSE = 'close'
+if (process.version.match(/^v0\.6/)) {
+  CLOSE = 'exit'
+}
+
 if (process.argv[2] === 'child') {
   return child()
 }
@@ -68,7 +73,7 @@ tap.test('many reads', function (t) {
     output += c
     console.error('' + c)
   })
-  child.on('close', function (c) {
+  child.on(CLOSE, function (c) {
     t.equal(output, expect)
     t.equal(n, 19)
     t.end()
index 8713a80..1a55ac5 100644 (file)
@@ -151,7 +151,7 @@ The first argument can be either a url or an options object. The only required o
 * `headers` - http headers, defaults to {}
 * `body` - entity body for POST and PUT requests. Must be buffer or string.
 * `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header.
-* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.
+* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.  Additionally, parses the response body as json.
 * `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.
 * `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.
 * `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.
diff --git a/deps/npm/node_modules/request/aws2.js b/deps/npm/node_modules/request/aws2.js
deleted file mode 100644 (file)
index eb683f7..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-var crypto = require('crypto')
-
-// The Authentication Header
-// 
-// The Amazon S3 REST API uses the standard HTTPAuthorization header to pass authentication information. (The name of the standard header is unfortunate because it carries authentication information, not authorization).Under the Amazon S3 authentication scheme, the Authorization header has the following form.
-// 
-// Authorization: AWS AWSAccessKeyId:Signature
-// 
-// Developers are issued an AWS Access Key ID and AWS SecretAccess Key when they register. For request authentication, theAWSAccessKeyId element identifies the secret key that was used to compute the signature, and (indirectly) the developer making the request.
-// 
-// The Signature element is the RFC 2104HMAC-SHA1 of selected elements from the request, and so theSignature part of the Authorization header will vary from request to request. If the request signature calculated by the system matches theSignature included with the request, then the requester will have demonstrated possession to the AWSSecret Access Key. The request will then be processed under the identity, and with the authority, of the developer to whom the key was issued.
-// 
-// Following is pseudo-grammar that illustrates the construction of the Authorization request header (\nmeans the Unicode code point U+000A commonly called newline).
-
-function authorizationHeader (accessKey) {
-  // Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature;
-  
-  var authorization = 'AWS' + " " + accessKey + ":" + signature()
-  
-  return authorization
-}
-
-// 
-
-function signature (secret, verb, md5, contenttype, date, amzheaders, bucket, path) {
-  // Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of( YourSecretAccessKeyID, StringToSign ) ) );
-  
-  function encodeSignature (stringToSign) {
-    return crypto.createHash('sha1').update(stringToSign).digest('base64')
-  }
-  
-  // 
-  // StringToSign = HTTP-Verb + "\n" +
-  //  Content-MD5 + "\n" +
-  //  Content-Type + "\n" +
-  //  Date + "\n" +
-  //  CanonicalizedAmzHeaders +
-  //  CanonicalizedResource;
-  
-  function compileStringToSign () {
-    var s = 
-      verb + '\n'
-      (md5 || '') + '\n'
-      (contenttype || '') + '\n'
-      date.toUTCString() + '\n'
-      canonicalizeAmzHeaders(amzheaders) + 
-      canonicalizeResource()
-    return s
-  }
-  
-  // 
-  // CanonicalizedResource = [ "/" + Bucket ] +
-  //  <HTTP-Request-URI, from the protocol name up to the query string> +
-  //  [ sub-resource, if present. For example "?acl", "?location", "?logging", or "?torrent"];
-  
-  function canonicalizeResource () {
-    return '/' + bucket + path
-  }
-  
-  // 
-  // CanonicalizedAmzHeaders = <described below>
-  // 
-  // HMAC-SHA1 is an algorithm defined by RFC 2104 (go to RFC 2104 - Keyed-Hashing for Message Authentication ). The algorithm takes as input two byte-strings: a key and a message. For Amazon S3 Request authentication, use your AWS Secret Access Key (YourSecretAccessKeyID) as the key, and the UTF-8 encoding of the StringToSign as the message. The output of HMAC-SHA1 is also a byte string, called the digest. The Signature request parameter is constructed by Base64 encoding this digest.
-  // Request Canonicalization for Signing
-  // 
-  // Recall that when the system receives an authenticated request, it compares the computed request signature with the signature provided in the request in StringToSign. For that reason, you must compute the signature using the same method used by Amazon S3. We call the process of putting a request in an agreed-upon form for signing "canonicalization".
-  
-}
-
-
-
-// Constructing the CanonicalizedResource Element
-// 
-// CanonicalizedResource represents the Amazon S3 resource targeted by the request. Construct it for a REST request as follows:
-// 
-// Launch Process
-// 
-// 1
-//  
-// 
-// Start with the empty string ("").
-// 
-// 2
-//  
-// 
-// If the request specifies a bucket using the HTTP Host header (virtual hosted-style), append the bucket name preceded by a "/" (e.g., "/bucketname"). For path-style requests and requests that don't address a bucket, do nothing. For more information on virtual hosted-style requests, see Virtual Hosting of Buckets.
-// 
-// 3
-//  
-// 
-// Append the path part of the un-decoded HTTP Request-URI, up-to but not including the query string.
-// 
-// 4
-//  
-// 
-// If the request addresses a sub-resource, like ?versioning, ?location, ?acl, ?torrent, ?lifecycle, or ?versionid append the sub-resource, its value if it has one, and the question mark. Note that in case of multiple sub-resources, sub-resources must be lexicographically sorted by sub-resource name and separated by '&'. e.g. ?acl&versionId=value.
-// 
-// The list of sub-resources that must be included when constructing the CanonicalizedResource Element are: acl, lifecycle, location, logging, notification, partNumber, policy, requestPayment, torrent, uploadId, uploads, versionId, versioning, versions and website.
-// 
-// If the request specifies query string parameters overriding the response header values (see Get Object), append the query string parameters, and its values. When signing you do not encode these values. However, when making the request, you must encode these parameter values. The query string parameters in a GET request include response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, response-content-encoding.
-// 
-// The delete query string parameter must be including when creating the CanonicalizedResource for a Multi-Object Delete request.
-// 
-// Elements of the CanonicalizedResource that come from the HTTP Request-URI should be signed literally as they appear in the HTTP request, including URL-Encoding meta characters.
-// 
-// The CanonicalizedResource might be different than the HTTP Request-URI. In particular, if your request uses the HTTP Host header to specify a bucket, the bucket does appear in the HTTP Request-URI. However, the CanonicalizedResource continues to include the bucket. Query string parameters might also appear in the Request-URI but are not included in CanonicalizedResource. For more information, see Virtual Hosting of Buckets.
-// Constructing the CanonicalizedAmzHeaders Element
-// 
-// To construct the CanonicalizedAmzHeaders part of StringToSign, select all HTTP request headers that start with 'x-amz-' (using a case-insensitive comparison) and use the following process.
-// 
-// CanonicalizedAmzHeaders Process
-// 1  Convert each HTTP header name to lower-case. For example, 'X-Amz-Date' becomes 'x-amz-date'.
-// 2  Sort the collection of headers lexicographically by header name.
-// 3  Combine header fields with the same name into one "header-name:comma-separated-value-list" pair as prescribed by RFC 2616, section 4.2, without any white-space between values. For example, the two metadata headers 'x-amz-meta-username: fred' and 'x-amz-meta-username: barney' would be combined into the single header 'x-amz-meta-username: fred,barney'.
-// 4  "Unfold" long headers that span multiple lines (as allowed by RFC 2616, section 4.2) by replacing the folding white-space (including new-line) by a single space.
-// 5  Trim any white-space around the colon in the header. For example, the header 'x-amz-meta-username: fred,barney' would become 'x-amz-meta-username:fred,barney'
-// 6  Finally, append a new-line (U+000A) to each canonicalized header in the resulting list. Construct the CanonicalizedResource element by concatenating all headers in this list into a single string.
-// 
-// Positional versus Named HTTP Header StringToSign Elements
-// 
-// The first few header elements of StringToSign (Content-Type, Date, and Content-MD5) are positional in nature. StringToSign does not include the names of these headers, only their values from the request. In contrast, the 'x-amz-' elements are named; Both the header names and the header values appear in StringToSign.
-// 
-// If a positional header called for in the definition of StringToSign is not present in your request, (Content-Type or Content-MD5, for example, are optional for PUT requests, and meaningless for GET requests), substitute the empty string ("") in for that position.
-// Time Stamp Requirement
-// 
-// A valid time stamp (using either the HTTP Date header or an x-amz-date alternative) is mandatory for authenticated requests. Furthermore, the client time-stamp included with an authenticated request must be within 15 minutes of the Amazon S3 system time when the request is received. If not, the request will fail with the RequestTimeTooSkewed error status code. The intention of these restrictions is to limit the possibility that intercepted requests could be replayed by an adversary. For stronger protection against eavesdropping, use the HTTPS transport for authenticated requests.
-// 
-// Some HTTP client libraries do not expose the ability to set the Date header for a request. If you have trouble including the value of the 'Date' header in the canonicalized headers, you can set the time-stamp for the request using an 'x-amz-date' header instead. The value of the x-amz-date header must be in one of the RFC 2616 formats (http://www.ietf.org/rfc/rfc2616.txt). When an x-amz-date header is present in a request, the system will ignore any Date header when computing the request signature. Therefore, if you include the x-amz-date header, use the empty string for the Date when constructing the StringToSign. See the next section for an example.
index 2407a93..dcdd5ca 100644 (file)
@@ -107,7 +107,7 @@ Request.prototype.init = function (options) {
   var self = this
   
   if (!options) options = {}
-  
+  if (process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG)) console.error('REQUEST', options)
   if (!self.pool && self.pool !== false) self.pool = globalPool
   self.dests = []
   self.__isRequestRequest = true
@@ -140,12 +140,11 @@ Request.prototype.init = function (options) {
 
     // do the HTTP CONNECT dance using koichik/node-tunnel
     if (http.globalAgent && self.uri.protocol === "https:") {
-      self.tunnel = true
       var tunnelFn = self.proxy.protocol === "http:"
                    ? tunnel.httpsOverHttp : tunnel.httpsOverHttps
 
       var tunnelOptions = { proxy: { host: self.proxy.hostname
-                                   , port: +self.proxy.port 
+                                   , port: +self.proxy.port
                                    , proxyAuth: self.proxy.auth }
                           , ca: this.ca }
 
@@ -223,6 +222,18 @@ Request.prototype.init = function (options) {
     self.emit('error', error)
   }
 
+  self._parserErrorHandler = function (error) {
+    if (this.res) {
+      if (this.res.request) {
+        this.res.request.emit('error', error)
+      } else {
+        this.res.emit('error', error)
+      }
+    } else {
+      this._httpMessage.emit('error', error)
+    }
+  }
+
   if (options.form) {
     self.form(options.form)
   }
@@ -319,7 +330,7 @@ Request.prototype.init = function (options) {
   }
 
   self.once('pipe', function (src) {
-    if (self.ntick) throw new Error("You cannot pipe to this stream after the first nextTick() after creation of the request stream.")
+    if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.")
     self.src = src
     if (isReadStream(src)) {
       if (!self.headers['content-type'] && !self.headers['Content-Type'])
@@ -367,6 +378,70 @@ Request.prototype.init = function (options) {
   })
 }
 
+// Must call this when following a redirect from https to http or vice versa
+// Attempts to keep everything as identical as possible, but update the
+// httpModule, Tunneling agent, and/or Forever Agent in use.
+Request.prototype._updateProtocol = function () {
+  var self = this
+  var protocol = self.uri.protocol
+
+  if (protocol === 'https:') {
+    // previously was doing http, now doing https
+    // if it's https, then we might need to tunnel now.
+    if (self.proxy) {
+      self.tunnel = true
+      var tunnelFn = self.proxy.protocol === 'http:'
+                   ? tunnel.httpsOverHttp : tunnel.httpsOverHttps
+      var tunnelOptions = { proxy: { host: self.proxy.hostname
+                                   , post: +self.proxy.port
+                                   , proxyAuth: self.proxy.auth }
+                          , ca: self.ca }
+      self.agent = tunnelFn(tunnelOptions)
+      return
+    }
+
+    self.httpModule = https
+    switch (self.agentClass) {
+      case ForeverAgent:
+        self.agentClass = ForeverAgent.SSL
+        break
+      case http.Agent:
+        self.agentClass = https.Agent
+        break
+      default:
+        // nothing we can do.  Just hope for the best.
+        return
+    }
+
+    // if there's an agent, we need to get a new one.
+    if (self.agent) self.agent = self.getAgent()
+
+  } else {
+    if (log) log('previously https, now http')
+    // previously was doing https, now doing http
+    // stop any tunneling.
+    if (self.tunnel) self.tunnel = false
+    self.httpModule = http
+    switch (self.agentClass) {
+      case ForeverAgent.SSL:
+        self.agentClass = ForeverAgent
+        break
+      case https.Agent:
+        self.agentClass = http.Agent
+        break
+      default:
+        // nothing we can do.  just hope for the best
+        return
+    }
+
+    // if there's an agent, then get a new one.
+    if (self.agent) {
+      self.agent = null
+      self.agent = self.getAgent()
+    }
+  }
+}
+
 Request.prototype.getAgent = function () {
   var Agent = this.agentClass
   var options = {}
@@ -392,7 +467,11 @@ Request.prototype.getAgent = function () {
     poolKey += this.host + ':' + this.port
   }
 
-  if (options.ca) {
+  // ca option is only relevant if proxy or destination are https
+  var proxy = this.proxy
+  if (typeof proxy === 'string') proxy = url.parse(proxy)
+  var caRelevant = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:'
+  if (options.ca && caRelevant) {
     if (poolKey) poolKey += ':'
     poolKey += options.ca
   }
@@ -402,6 +481,9 @@ Request.prototype.getAgent = function () {
     return this.httpModule.globalAgent
   }
 
+  // we're using a stored agent.  Make sure it's protocol-specific
+  poolKey = this.uri.protocol + poolKey
+
   // already generated an agent for this setting
   if (this.pool[poolKey]) return this.pool[poolKey]
 
@@ -410,25 +492,28 @@ Request.prototype.getAgent = function () {
 
 Request.prototype.start = function () {
   var self = this
-  
+
   if (self._aborted) return
-  
+
   self._started = true
   self.method = self.method || 'GET'
   self.href = self.uri.href
   if (log) log('%method %href', self)
-  
+
   if (self.src && self.src.stat && self.src.stat.size) {
     self.headers['content-length'] = self.src.stat.size
   }
   if (self._aws) {
     self.aws(self._aws, true)
   }
-  
+
   self.req = self.httpModule.request(self, function (response) {
+    if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) {
+      response.connection.once('error', self._parserErrorHandler)
+    }
     if (self._aborted) return
     if (self._paused) response.pause()
-    
+
     self.response = response
     response.request = self
     response.toJSON = toJSON
@@ -446,7 +531,7 @@ Request.prototype.start = function () {
       clearTimeout(self.timeoutTimer)
       self.timeoutTimer = null
     }  
-    
+
     var addCookie = function (cookie) {
       if (self._jar) self._jar.add(new Cookie(cookie))
       else cookieJar.add(new Cookie(cookie))
@@ -470,7 +555,15 @@ Request.prototype.start = function () {
       if (!isUrl.test(response.headers.location)) {
         response.headers.location = url.resolve(self.uri.href, response.headers.location)
       }
-      self.uri = response.headers.location
+
+      var uriPrev = self.uri
+      self.uri = url.parse(response.headers.location)
+
+      // handle the case where we change protocol from https to http or vice versa
+      if (self.uri.protocol !== uriPrev.protocol) {
+        self._updateProtocol()
+      }
+
       self.redirects.push(
         { statusCode : response.statusCode
         , redirectUri: response.headers.location 
@@ -540,7 +633,7 @@ Request.prototype.start = function () {
             if (self.encoding === null) {
               response.body = body
             } else {
-              response.body = body.toString()
+              response.body = body.toString(self.encoding)
             }
           } else if (buffer.length) {
             response.body = buffer.join('')
@@ -584,7 +677,9 @@ Request.prototype.start = function () {
   self.req.on('drain', function() {
     self.emit('drain')
   })
-  
+  self.on('end', function() {
+    self.req.connection.removeListener('error', self._parserErrorHandler)
+  })
   self.emit('request', self.req)
 }
 
@@ -659,10 +754,12 @@ Request.prototype.multipart = function (multipart) {
     self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary;
   }
 
-  console.log('boundary >> ' + self.boundary)
-
   if (!multipart.forEach) throw new Error('Argument error, options.multipart.')
 
+  if (self.preambleCRLF) {
+    self.body.push(new Buffer('\r\n'))
+  }
+  
   multipart.forEach(function (part) {
     var body = part.body
     if(body == null) throw Error('Body attribute missing in multipart.')
@@ -747,6 +844,7 @@ Request.prototype.oauth = function (_oauth) {
       // skip 
     } else {
       delete oa['oauth_'+i]
+      delete oa[i]
     }
   }
   this.headers.Authorization = 
@@ -861,16 +959,25 @@ function request (uri, options, callback) {
 
 module.exports = request
 
-request.defaults = function (options) {
+request.initParams = initParams;
+
+request.defaults = function (options, requester) {
   var def = function (method) {
     var d = function (uri, opts, callback) {
       var params = initParams(uri, opts, callback);
       for (var i in options) {
         if (params.options[i] === undefined) params.options[i] = options[i]
       }
-      return method(params.options, params.callback)
+      if(typeof requester === 'function') {
+        if(method === request) {
+          method = requester;
+        } else {
+          params.options._requester = requester;
+        }
+      }
+      return method(params.options, params.callback);
     }
-    return d
+    return d;
   }
   var de = def(request)
   de.get = def(request.get)
@@ -920,6 +1027,9 @@ request.head = function (uri, options, callback) {
 request.del = function (uri, options, callback) {
   var params = initParams(uri, options, callback);
   params.options.method = 'DELETE'
+  if(typeof params.options._requester === 'function') {
+    request = params.options._requester;
+  }
   return request(params.uri || null, params.options, params.callback)
 }
 request.jar = function () {
index 6796f5d..05d3144 100644 (file)
   "scripts": {
     "test": "node tests/run.js"
   },
-  "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n<pre>\n  npm install request\n</pre>\n\nOr from source:\n\n<pre>\n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n</pre>\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n  if (!error && response.statusCode == 200) {\n    console.log(body) // Print the google web page.\n  }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    if (req.method === 'PUT') {\n      req.pipe(request.put('http://mysite.com/doodle.png'))\n    } else if (req.method === 'GET' || req.method === 'HEAD') {\n      request.get('http://mysite.com/doodle.png').pipe(resp)\n    } \n  }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    var x = request('http://mysite.com/doodle.png')\n    req.pipe(x)\n    x.pipe(resp)\n  }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    r.get('http://google.com/doodle.png').pipe(resp)\n  }\n})\n```\n\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n  , oauth =\n    { callback: 'http://mysite.com/callback/'\n    , consumer_key: CONSUMER_KEY\n    , consumer_secret: CONSUMER_SECRET\n    }\n  , url = 'https://api.twitter.com/oauth/request_token'\n  ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n  // Assume by some stretch of magic you aquired the verifier\n  var access_token = qs.parse(body)\n    , oauth = \n      { consumer_key: CONSUMER_KEY\n      , consumer_secret: CONSUMER_SECRET\n      , token: access_token.oauth_token\n      , verifier: VERIFIER\n      , token_secret: access_token.oauth_token_secret\n      }\n    , url = 'https://api.twitter.com/oauth/access_token'\n    ;\n  request.post({url:url, oauth:oauth}, function (e, r, body) {\n    var perm_token = qs.parse(body)\n      , oauth = \n        { consumer_key: CONSUMER_KEY\n        , consumer_secret: CONSUMER_SECRET\n        , token: perm_token.oauth_token\n        , token_secret: perm_token.oauth_token_secret\n        }\n      , url = 'https://api.twitter.com/1/users/show.json?'\n      , params = \n        { screen_name: perm_token.screen_name\n        , user_id: perm_token.user_id\n        }\n      ;\n    url += qs.stringify(params)\n    request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n      console.log(user)\n    })\n  })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options)  \n  \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n  var request = require('request')\n    , rand = Math.floor(Math.random()*100000000).toString()\n    ;\n  request(\n    { method: 'PUT'\n    , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n    , multipart: \n      [ { 'content-type': 'application/json'\n        ,  body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n        }\n      , { body: 'I am an attachment' }\n      ] \n    }\n  , function (error, response, body) {\n      if(response.statusCode == 201){\n        console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n      } else {\n        console.log('error: '+ response.statusCode)\n        console.log(body)\n      }\n    }\n  )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n  request('http://images.google.com')\n})\n```\n",
+  "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n<pre>\n  npm install request\n</pre>\n\nOr from source:\n\n<pre>\n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n</pre>\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n  if (!error && response.statusCode == 200) {\n    console.log(body) // Print the google web page.\n  }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    if (req.method === 'PUT') {\n      req.pipe(request.put('http://mysite.com/doodle.png'))\n    } else if (req.method === 'GET' || req.method === 'HEAD') {\n      request.get('http://mysite.com/doodle.png').pipe(resp)\n    } \n  }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    var x = request('http://mysite.com/doodle.png')\n    req.pipe(x)\n    x.pipe(resp)\n  }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    r.get('http://google.com/doodle.png').pipe(resp)\n  }\n})\n```\n\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n  , oauth =\n    { callback: 'http://mysite.com/callback/'\n    , consumer_key: CONSUMER_KEY\n    , consumer_secret: CONSUMER_SECRET\n    }\n  , url = 'https://api.twitter.com/oauth/request_token'\n  ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n  // Assume by some stretch of magic you aquired the verifier\n  var access_token = qs.parse(body)\n    , oauth = \n      { consumer_key: CONSUMER_KEY\n      , consumer_secret: CONSUMER_SECRET\n      , token: access_token.oauth_token\n      , verifier: VERIFIER\n      , token_secret: access_token.oauth_token_secret\n      }\n    , url = 'https://api.twitter.com/oauth/access_token'\n    ;\n  request.post({url:url, oauth:oauth}, function (e, r, body) {\n    var perm_token = qs.parse(body)\n      , oauth = \n        { consumer_key: CONSUMER_KEY\n        , consumer_secret: CONSUMER_SECRET\n        , token: perm_token.oauth_token\n        , token_secret: perm_token.oauth_token_secret\n        }\n      , url = 'https://api.twitter.com/1/users/show.json?'\n      , params = \n        { screen_name: perm_token.screen_name\n        , user_id: perm_token.user_id\n        }\n      ;\n    url += qs.stringify(params)\n    request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n      console.log(user)\n    })\n  })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.  Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options)  \n  \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n  var request = require('request')\n    , rand = Math.floor(Math.random()*100000000).toString()\n    ;\n  request(\n    { method: 'PUT'\n    , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n    , multipart: \n      [ { 'content-type': 'application/json'\n        ,  body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n        }\n      , { body: 'I am an attachment' }\n      ] \n    }\n  , function (error, response, body) {\n      if(response.statusCode == 201){\n        console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n      } else {\n        console.log('error: '+ response.statusCode)\n        console.log(body)\n      }\n    }\n  )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n  request('http://images.google.com')\n})\n```\n",
   "_id": "request@2.9.203",
   "dist": {
-    "shasum": "f4c8f35b61b4d6621cb287bb1a1be6002b0bbe4a"
+    "shasum": "baf55a9b2ccfcca405cfcc0b104edf8b2681eeef"
   },
-  "_from": "request@~2.9"
+  "_from": "git://github.com/isaacs/request"
 }
index 921f512..5b7cb51 100644 (file)
@@ -51,11 +51,15 @@ exports.createPostValidator = function (text) {
     var r = '';
     req.on('data', function (chunk) {r += chunk})
     req.on('end', function () {
-    if (r !== text) console.log(r, text);
-    assert.equal(r, text)
-    resp.writeHead(200, {'content-type':'text/plain'})
-    resp.write('OK')
-    resp.end()
+      if (req.headers['content-type'] && req.headers['content-type'].indexOf('boundary=') >= 0) {
+        var boundary = req.headers['content-type'].split('boundary=')[1];
+        text = text.replace(/__BOUNDARY__/g, boundary);
+      }
+      if (r !== text) console.log(r, text);
+      assert.equal(r, text)
+      resp.writeHead(200, {'content-type':'text/plain'})
+      resp.write('OK')
+      resp.end()
     })
   }
   return l;
index e3fc75d..a624397 100644 (file)
@@ -30,6 +30,11 @@ var tests =
     , encoding: null
     , expectBody: new Buffer("TESTING!")
     }
+  , testGetEncoding :
+    { resp : server.createGetResponse(new Buffer('efa3bfcea9e29883', 'hex'))
+    , encoding: 'hex'
+    , expectBody: "efa3bfcea9e29883"
+    }
   , testGetJSON :
      { resp : server.createGetResponse('{"test":true}', 'application/json')
      , json : true
@@ -50,7 +55,39 @@ var tests =
     , method: "PUT"
     , json: {foo: 'bar'}
     }
-
+  , testPutMultipart :
+    { resp: server.createPostValidator(
+        '--__BOUNDARY__\r\n' +
+        'content-type: text/html\r\n' +
+        '\r\n' +
+        '<html><body>Oh hi.</body></html>' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
+        'Oh hi.' +
+        '\r\n--__BOUNDARY__--'
+        )
+    , method: "PUT"
+    , multipart:
+      [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+      , {'body': 'Oh hi.'}
+      ]
+    }
+  , testPutMultipartPreambleCRLF :
+    { resp: server.createPostValidator(
+        '\r\n--__BOUNDARY__\r\n' +
+        'content-type: text/html\r\n' +
+        '\r\n' +
+        '<html><body>Oh hi.</body></html>' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
+        'Oh hi.' +
+        '\r\n--__BOUNDARY__--'
+        )
+    , method: "PUT"
+    , preambleCRLF: true
+    , multipart:
+      [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+      , {'body': 'Oh hi.'}
+      ]
+    }
   }
 
 s.listen(s.port, function () {
index 6c8b58f..479abf2 100644 (file)
@@ -61,8 +61,39 @@ s.listen(s.port, function () {
   request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){
     if (e) throw e;
     counter += 1;
-    console.log(counter.toString() + " tests passed.")
-    s.close()
   });
 
+  s.on('/get_custom', function(req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.headers.x, 'y');
+    resp.writeHead(200, {'Content-Type': 'text/plain'});
+    resp.end();
+  });
+
+  // test custom request handler function
+  var defaultRequest = request.defaults({
+    headers:{foo:"bar"}
+    , body: 'TESTING!'
+  }, function(uri, options, callback) {
+    var params = request.initParams(uri, options, callback);
+    options = params.options;
+    options.headers.x = 'y';
+
+    return request(params.uri, params.options, params.callback);
+  });
+
+  var msg = 'defaults test failed. head request should throw earlier';
+  assert.throws(function() {
+    defaultRequest.head(s.url + '/get_custom', function(e, r, b) {
+      throw new Error(msg);
+    });
+    counter+=1;
+  }, msg);
+
+  defaultRequest.get(s.url + '/get_custom', function(e, r, b) {
+    if(e) throw e;
+    counter += 1;
+    console.log(counter.toString() + " tests passed.");
+    s.close();
+  });
 })
diff --git a/deps/npm/node_modules/request/tests/test-follow-all-303.js b/deps/npm/node_modules/request/tests/test-follow-all-303.js
new file mode 100644 (file)
index 0000000..5eec497
--- /dev/null
@@ -0,0 +1,30 @@
+var request = require('request');
+var http = require('http');
+var requests = 0;
+var assert = require('assert');
+
+var server = http.createServer(function (req, res) {
+  console.error(req.method, req.url);
+  requests ++;
+
+  if (req.method === 'POST') {
+    console.error('send 303');
+    res.setHeader('location', req.url);
+    res.statusCode = 303;
+    res.end('try again, i guess\n');
+  } else {
+    console.error('send 200')
+    res.end('ok: ' + requests);
+  }
+});
+server.listen(6767);
+
+request.post({ url: 'http://localhost:6767/foo',
+               followAllRedirects: true,
+               form: { foo: 'bar' } }, function (er, req, body) {
+  if (er) throw er;
+  assert.equal(body, 'ok: 2');
+  assert.equal(requests, 2);
+  console.error('ok - ' + process.version);
+  server.close();
+});
diff --git a/deps/npm/node_modules/request/tests/test-follow-all.js b/deps/npm/node_modules/request/tests/test-follow-all.js
new file mode 100644 (file)
index 0000000..4dbde61
--- /dev/null
@@ -0,0 +1,35 @@
+var request = require('request');
+var http = require('http');
+var requests = 0;
+var assert = require('assert');
+
+var server = http.createServer(function (req, res) {
+  requests ++;
+
+  // redirect everything 3 times, no matter what.
+  var c = req.headers.cookie;
+
+  if (!c) c = 0;
+  else c = +c.split('=')[1] || 0;
+
+  if (c > 3) {
+    res.end('ok: '+requests);
+    return;
+  }
+
+  res.setHeader('set-cookie', 'c=' + (c + 1));
+  res.setHeader('location', req.url);
+  res.statusCode = 302;
+  res.end('try again, i guess\n');
+});
+server.listen(6767);
+
+request.post({ url: 'http://localhost:6767/foo',
+               followAllRedirects: true,
+               form: { foo: 'bar' } }, function (er, req, body) {
+  if (er) throw er;
+  assert.equal(body, 'ok: 5');
+  assert.equal(requests, 5);
+  console.error('ok - ' + process.version);
+  server.close();
+});
index f53fc14..470b68d 100644 (file)
@@ -52,13 +52,13 @@ var tests =
     }
   , testPutMultipart :
     { resp: server.createPostValidator(
-        '--frontier\r\n' +
+        '--__BOUNDARY__\r\n' +
         'content-type: text/html\r\n' +
         '\r\n' +
         '<html><body>Oh hi.</body></html>' +
-        '\r\n--frontier\r\n\r\n' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
         'Oh hi.' +
-        '\r\n--frontier--'
+        '\r\n--__BOUNDARY__--'
         )
     , method: "PUT"
     , multipart:
index df7330b..58e7db9 100644 (file)
@@ -44,13 +44,13 @@ var tests =
     }
   , testPutMultipart :
     { resp: server.createPostValidator(
-        '--frontier\r\n' +
+        '--__BOUNDARY__\r\n' +
         'content-type: text/html\r\n' +
         '\r\n' +
         '<html><body>Oh hi.</body></html>' +
-        '\r\n--frontier\r\n\r\n' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
         'Oh hi.' +
-        '\r\n--frontier--'
+        '\r\n--__BOUNDARY__--'
         )
     , method: "PUT"
     , multipart:
index 8354f6d..5ddb311 100644 (file)
@@ -50,13 +50,13 @@ var tests =
       }
     , testPutMultipart :
       { resp: server.createPostValidator(
-          '--frontier\r\n' +
+          '--__BOUNDARY__\r\n' +
           'content-type: text/html\r\n' +
           '\r\n' +
           '<html><body>Oh hi.</body></html>' +
-          '\r\n--frontier\r\n\r\n' +
+          '\r\n--__BOUNDARY__\r\n\r\n' +
           'Oh hi.' +
-          '\r\n--frontier--'
+          '\r\n--__BOUNDARY__--'
           )
       , method: "PUT"
       , multipart:
diff --git a/deps/npm/node_modules/request/tests/test-protocol-changing-redirect.js b/deps/npm/node_modules/request/tests/test-protocol-changing-redirect.js
new file mode 100644 (file)
index 0000000..f74e196
--- /dev/null
@@ -0,0 +1,60 @@
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../main.js')
+
+
+var s = server.createServer()
+var ss = server.createSSLServer()
+var sUrl = 'http://localhost:' + s.port
+var ssUrl = 'https://localhost:' + ss.port
+
+s.listen(s.port, bouncy(s, ssUrl))
+ss.listen(ss.port, bouncy(ss, sUrl))
+
+var hits = {}
+var expect = {}
+var pending = 0
+function bouncy (s, server) { return function () {
+
+  var redirs = { a: 'b'
+               , b: 'c'
+               , c: 'd'
+               , d: 'e'
+               , e: 'f'
+               , f: 'g'
+               , g: 'h'
+               , h: 'end' }
+
+  var perm = true
+  Object.keys(redirs).forEach(function (p) {
+    var t = redirs[p]
+
+    // switch type each time
+    var type = perm ? 301 : 302
+    perm = !perm
+    s.on('/' + p, function (req, res) {
+      res.writeHead(type, { location: server + '/' + t })
+      res.end()
+    })
+  })
+
+  s.on('/end', function (req, res) {
+    var h = req.headers['x-test-key']
+    hits[h] = true
+    pending --
+    if (pending === 0) done()
+  })
+}}
+
+for (var i = 0; i < 5; i ++) {
+  pending ++
+  var val = 'test_' + i
+  expect[val] = true
+  request({ url: (i % 2 ? sUrl : ssUrl) + '/a'
+          , headers: { 'x-test-key': val } })
+}
+
+function done () {
+  assert.deepEqual(hits, expect)
+  process.exit(0)
+}
diff --git a/deps/npm/node_modules/request/tests/test-s3.js b/deps/npm/node_modules/request/tests/test-s3.js
deleted file mode 100644 (file)
index 5f59c4a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-var request = require('../main')
-
-var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', 
-  { aws: 
-    { key: 'AKIAI6KIQRRVMGK3WK5Q'
-    , secret: 'j4kaxM7TUiN7Ou0//v1ZqOVn3Aq7y1ccPh/tHTna'
-    , bucket: 'log.curlybracecast.com'
-    }
-  }, function (e, resp, body) {
-    console.log(r.headers)
-    console.log(body)
-  }
-)
\ No newline at end of file
index 58131b9..51e2126 100644 (file)
@@ -32,9 +32,10 @@ squid.stdout.on('data', function (c) {
 })
 
 squid.on('exit', function (c) {
-  console.error('exit '+c)
+  console.error('squid: exit '+c)
   if (c && !ready) {
     console.error('squid must be installed to run this test.')
+    console.error('skipping this test. please install squid and run again if you need to test tunneling.')
     c = null
     hadError = null
     process.exit(0)
@@ -49,8 +50,9 @@ squid.on('exit', function (c) {
 
 setTimeout(function F () {
   if (!ready) return setTimeout(F, 100)
-  request({ uri: 'https://registry.npmjs.org/request/'
+  request({ uri: 'https://registry.npmjs.org/'
           , proxy: 'http://localhost:3128'
+          , strictSSL: true
           , ca: ca
           , json: true }, function (er, body) {
     hadError = er
index 453786c..469c130 100644 (file)
@@ -188,6 +188,7 @@ function createSecureSocket(options, cb) {
   TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
     // 0 is dummy port for v0.6
     var secureSocket = tls.connect(0, mergeOptions({}, self.options, {
+      servername: options.host,
       socket: socket
     }));
     cb(secureSocket);
index d0b4d7b..71a77ab 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "version": "1.1.49",
+  "version": "1.1.55",
   "name": "npm",
   "publishConfig": {
     "proprietary-attribs": false
@@ -41,7 +41,6 @@
     "graceful-fs": "~1.1.1",
     "minimatch": "~0.2.6",
     "nopt": "~2.0",
-    "node-uuid": "~1.3",
     "rimraf": "2",
     "request": "~2.9",
     "which": "1",
@@ -50,7 +49,7 @@
     "block-stream": "*",
     "inherits": "1",
     "mkdirp": "~0.3.3",
-    "read": "~1.0.3",
+    "read": "~1.0.4",
     "lru-cache": "~2.0.0",
     "node-gyp": "~0.6.4",
     "fstream-npm": "0.1",
@@ -59,7 +58,7 @@
     "chownr": "0",
     "npmlog": "0",
     "ansi": "~0.1.2",
-    "npm-registry-client": "~0.1.4",
+    "npm-registry-client": "~0.2.4",
     "read-package-json": "~0.1.3",
     "read-installed": "0",
     "glob": "~3.1.12",
@@ -79,7 +78,6 @@
     "graceful-fs",
     "minimatch",
     "nopt",
-    "node-uuid",
     "rimraf",
     "request",
     "which",
     "tap": "~0.2.5"
   },
   "engines": {
-    "node": ">=0.8",
+    "node": ">=0.6",
     "npm": "1"
   },
   "scripts": {
diff --git a/deps/npm/test/tap/publish-config.js b/deps/npm/test/tap/publish-config.js
new file mode 100644 (file)
index 0000000..ac8c94a
--- /dev/null
@@ -0,0 +1,41 @@
+var test = require('tap').test
+var fs = require('fs')
+var pkg = process.env.npm_config_tmp || '/tmp'
+pkg += '/npm-test-publish-config'
+
+require('mkdirp').sync(pkg)
+
+fs.writeFileSync(pkg + '/package.json', JSON.stringify({
+  name: 'npm-test-publish-config',
+  version: '1.2.3',
+  publishConfig: { registry: 'http://localhost:13370' }
+}), 'utf8')
+
+var spawn = require('child_process').spawn
+var npm = require.resolve('../../bin/npm-cli.js')
+var node = process.execPath
+
+console.error('pkg=%j', pkg)
+
+test(function (t) {
+  var child
+  require('http').createServer(function (req, res) {
+    t.pass('got request on the fakey fake registry')
+    t.end()
+    this.close()
+    res.statusCode = 500
+    res.end('{"error":"sshhh. naptime nao. \\^O^/ <(YAWWWWN!)"}')
+    child.kill()
+  }).listen(13370, function () {
+    t.pass('server is listening')
+
+    // don't much care about listening to the child's results
+    // just wanna make sure it hits the server we just set up.
+    //
+    // there are plenty of other tests to verify that publish
+    // itself functions normally.
+    child = spawn(node, [npm, 'publish'], {
+      cwd: pkg
+    })
+  })
+})