summaryrefslogtreecommitdiff
path: root/deps/npm/lib
diff options
context:
space:
mode:
authorForrest L Norvell <forrest@npmjs.com>2015-03-13 02:07:27 -0700
committerJeremiah Senkpiel <fishrock123@rocketmail.com>2015-03-15 21:41:52 -0400
commit7d0baf174155195bcc93ec63716118a3696095d7 (patch)
tree7964cba8d07b6f0954e43497a4d40a9b5a4de814 /deps/npm/lib
parent4eb8810a27a710bcfdf15fc03fbb22a65e655aff (diff)
downloadandroid-node-v8-7d0baf174155195bcc93ec63716118a3696095d7.tar.gz
android-node-v8-7d0baf174155195bcc93ec63716118a3696095d7.tar.bz2
android-node-v8-7d0baf174155195bcc93ec63716118a3696095d7.zip
deps: upgrade npm to 2.7.1
PR-URL: https://github.com/iojs/io.js/pull/1142 Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Rod Vagg <rod@vagg.org>
Diffstat (limited to 'deps/npm/lib')
-rw-r--r--deps/npm/lib/cache/add-named.js7
-rw-r--r--deps/npm/lib/cache/add-remote-git.js532
-rw-r--r--deps/npm/lib/cache/add-remote-tarball.js2
-rw-r--r--deps/npm/lib/config/defaults.js15
-rw-r--r--deps/npm/lib/dedupe.js27
-rw-r--r--deps/npm/lib/install.js29
-rw-r--r--deps/npm/lib/npm.js1
-rw-r--r--deps/npm/lib/publish.js13
-rw-r--r--deps/npm/lib/stars.js11
-rw-r--r--deps/npm/lib/update.js20
-rw-r--r--deps/npm/lib/utils/error-handler.js3
-rw-r--r--deps/npm/lib/whoami.js24
12 files changed, 410 insertions, 274 deletions
diff --git a/deps/npm/lib/cache/add-named.js b/deps/npm/lib/cache/add-named.js
index d81b7b0da6..cb5a3fa8a6 100644
--- a/deps/npm/lib/cache/add-named.js
+++ b/deps/npm/lib/cache/add-named.js
@@ -12,7 +12,6 @@ var path = require("path")
, addRemoteTarball = require("./add-remote-tarball.js")
, cachedPackageRoot = require("./cached-package-root.js")
, mapToRegistry = require("../utils/map-to-registry.js")
- , warnStrict = require("../utils/warn-deprecated.js")("engineStrict")
module.exports = addNamed
@@ -92,12 +91,6 @@ function engineFilter (data) {
Object.keys(data.versions || {}).forEach(function (v) {
var eng = data.versions[v].engines
if (!eng) return
- if (data.versions[v].engineStrict) {
- warnStrict([
- "Per-package engineStrict (found in package.json for "+data.name+")",
- "won't be used in npm 3+. Use the config setting `engine-strict` instead."
- ], data.name)
- }
if (!strict && !data.versions[v].engineStrict) return
if (eng.node && !semver.satisfies(nodev, eng.node, true)
|| eng.npm && !semver.satisfies(npmv, eng.npm, true)) {
diff --git a/deps/npm/lib/cache/add-remote-git.js b/deps/npm/lib/cache/add-remote-git.js
index 974c158f9c..9eaf6b18a5 100644
--- a/deps/npm/lib/cache/add-remote-git.js
+++ b/deps/npm/lib/cache/add-remote-git.js
@@ -1,269 +1,330 @@
-var mkdir = require("mkdirp")
- , assert = require("assert")
- , git = require("../utils/git.js")
- , fs = require("graceful-fs")
- , log = require("npmlog")
- , path = require("path")
- , url = require("url")
- , chownr = require("chownr")
- , crypto = require("crypto")
- , npm = require("../npm.js")
- , rm = require("../utils/gently-rm.js")
- , inflight = require("inflight")
- , getCacheStat = require("./get-stat.js")
- , addLocal = require("./add-local.js")
- , realizePackageSpecifier = require("realize-package-specifier")
- , normalizeGitUrl = require("normalize-git-url")
- , randomBytes = require("crypto").pseudoRandomBytes // only need uniqueness
-
-var remotes = path.resolve(npm.config.get("cache"), "_git-remotes")
-var templates = path.join(remotes, "_templates")
+var mkdir = require('mkdirp')
+var assert = require('assert')
+var git = require('../utils/git.js')
+var fs = require('graceful-fs')
+var log = require('npmlog')
+var path = require('path')
+var url = require('url')
+var chownr = require('chownr')
+var crypto = require('crypto')
+var npm = require('../npm.js')
+var rm = require('../utils/gently-rm.js')
+var inflight = require('inflight')
+var getCacheStat = require('./get-stat.js')
+var addLocal = require('./add-local.js')
+var realizePackageSpecifier = require('realize-package-specifier')
+var normalizeGitUrl = require('normalize-git-url')
+var randomBytes = require('crypto').pseudoRandomBytes // only need uniqueness
+
+var remotes = path.resolve(npm.config.get('cache'), '_git-remotes')
+var templates = path.join(remotes, '_templates')
var VALID_VARIABLES = [
- "GIT_SSH",
- "GIT_SSL_NO_VERIFY",
- "GIT_PROXY_COMMAND",
- "GIT_SSL_CAINFO"
+ 'GIT_SSH',
+ 'GIT_SSL_NO_VERIFY',
+ 'GIT_PROXY_COMMAND',
+ 'GIT_SSL_CAINFO'
]
-// 1. cacheDir = path.join(cache,'_git-remotes',sha1(u))
-// 2. checkGitDir(cacheDir) ? 4. : 3. (rm cacheDir if necessary)
-// 3. git clone --mirror u cacheDir
-// 4. cd cacheDir && git fetch -a origin
-// 5. git archive /tmp/random.tgz
-// 6. addLocalTarball(/tmp/random.tgz) <gitref> --format=tar --prefix=package/
-// silent flag is used if this should error quietly
-module.exports = function addRemoteGit (u, silent, cb) {
- assert(typeof u === "string", "must have git URL")
- assert(typeof cb === "function", "must have callback")
-
- log.verbose("addRemoteGit", "u=%j silent=%j", u, silent)
- var normalized = normalizeGitUrl(u)
- log.silly("addRemoteGit", "normalized", normalized)
-
- var v = crypto.createHash("sha1").update(normalized.url).digest("hex").slice(0, 8)
- v = normalized.url.replace(/[^a-zA-Z0-9]+/g, "-")+"-"+v
- log.silly("addRemoteGit", "v", v)
-
- var p = path.join(remotes, v)
- cb = inflight(p, cb)
- if (!cb) return log.verbose("addRemoteGit", p, "already in flight; waiting")
- log.verbose("addRemoteGit", p, "not in flight; cloning")
+module.exports = function addRemoteGit (uri, silent, cb) {
+ assert(typeof uri === 'string', 'must have git URL')
+ assert(typeof cb === 'function', 'must have callback')
+
+ // reconstruct the URL as it was passed in – realizePackageSpecifier
+ // strips off `git+` and `maybeGithub` doesn't include it.
+ var originalURL
+ if (!/^git[+:]/.test(uri)) {
+ originalURL = 'git+' + uri
+ } else {
+ originalURL = uri
+ }
- getGitDir(function (er) {
- if (er) return cb(er)
- checkGitDir(p, normalized.url, normalized.branch, u, silent, function (er, data) {
- if (er) return cb(er, data)
+ // break apart the origin URL and the branch / tag / commitish
+ var normalized = normalizeGitUrl(uri)
+ var gitURL = normalized.url
+ var treeish = normalized.branch
- addModeRecursive(p, npm.modes.file, function (er) {
- return cb(er, data)
- })
- })
- })
-}
+ // ensure that similarly-named remotes don't collide
+ var repoID = gitURL.replace(/[^a-zA-Z0-9]+/g, '-') + '-' +
+ crypto.createHash('sha1').update(gitURL).digest('hex').slice(0, 8)
+ var cachedRemote = path.join(remotes, repoID)
-function getGitDir (cb) {
- getCacheStat(function (er, st) {
- if (er) return cb(er)
+ // set later, as the callback flow proceeds
+ var resolvedURL
+ var resolvedTreeish
+ var tmpdir
- // We don't need global templates when cloning. Use an empty directory for
- // the templates, creating it (and setting its permissions) if necessary.
- mkdir(templates, function (er) {
- if (er) return cb(er)
+ cb = inflight(repoID, cb)
+ if (!cb) {
+ return log.verbose('addRemoteGit', repoID, 'already in flight; waiting')
+ }
+ log.verbose('addRemoteGit', repoID, 'not in flight; caching')
- // Ensure that both the template and remotes directories have the correct
- // permissions.
- fs.chown(templates, st.uid, st.gid, function (er) {
- if (er) return cb(er)
+ // initialize the remotes cache with the correct perms
+ getGitDir(function (er) {
+ if (er) return cb(er)
+ fs.stat(cachedRemote, function (er, s) {
+ if (er) return mirrorRemote(finish)
+ if (!s.isDirectory()) return resetRemote(finish)
- fs.chown(remotes, st.uid, st.gid, function (er) {
- cb(er, st)
- })
- })
+ validateExistingRemote(finish)
})
+
+ // always set permissions on the cached remote
+ function finish (er, data) {
+ if (er) return cb(er, data)
+ addModeRecursive(cachedRemote, npm.modes.file, function (er) {
+ return cb(er, data)
+ })
+ }
})
-}
-function checkGitDir (p, u, co, origUrl, silent, cb) {
- fs.stat(p, function (er, s) {
- if (er) return cloneGitRemote(p, u, co, origUrl, silent, cb)
- if (!s.isDirectory()) return rm(p, function (er) {
+ // don't try too hard to hold on to a remote
+ function resetRemote (cb) {
+ log.info('addRemoteGit', 'resetting', cachedRemote)
+ rm(cachedRemote, function (er) {
if (er) return cb(er)
- cloneGitRemote(p, u, co, origUrl, silent, cb)
+ mirrorRemote(cb)
})
+ }
+ // reuse a cached remote when possible, but nuke it if it's in an
+ // inconsistent state
+ function validateExistingRemote (cb) {
git.whichAndExec(
- [ "config", "--get", "remote.origin.url" ],
- { cwd : p, env : gitEnv },
+ ['config', '--get', 'remote.origin.url'],
+ { cwd: cachedRemote, env: gitEnv() },
function (er, stdout, stderr) {
- var stdoutTrimmed = (stdout + "\n" + stderr).trim()
- if (er || u !== stdout.trim()) {
- log.warn( "`git config --get remote.origin.url` returned "
- + "wrong result ("+u+")", stdoutTrimmed )
- return rm(p, function (er){
- if (er) return cb(er)
- cloneGitRemote(p, u, co, origUrl, silent, cb)
- })
+ var originURL = stdout.trim()
+ stderr = stderr.trim()
+ log.verbose('addRemoteGit', 'remote.origin.url:', originURL)
+
+ if (stderr || er) {
+ log.warn('addRemoteGit', 'resetting remote', cachedRemote, 'because of error:', stderr || er)
+ return resetRemote(cb)
+ } else if (gitURL !== originURL) {
+ log.warn(
+ 'addRemoteGit',
+ 'pre-existing cached repo', cachedRemote, 'points to', originURL, 'and not', gitURL
+ )
+ return resetRemote(cb)
}
- log.verbose("git remote.origin.url", stdoutTrimmed)
- fetchRemote(p, u, co, origUrl, cb)
+
+ log.verbose('addRemoteGit', 'updating existing cached remote', cachedRemote)
+ updateRemote(cb)
}
)
- })
-}
+ }
-function cloneGitRemote (p, u, co, origUrl, silent, cb) {
- mkdir(p, function (er) {
- if (er) return cb(er)
+ // make a complete bare mirror of the remote repo
+ // NOTE: npm uses a blank template directory to prevent weird inconsistencies
+ // https://github.com/npm/npm/issues/5867
+ function mirrorRemote (cb) {
+ mkdir(cachedRemote, function (er) {
+ if (er) return cb(er)
- git.whichAndExec(
- [ "clone", "--template=" + templates, "--mirror", u, p ],
- { cwd : p, env : gitEnv() },
- function (er, stdout, stderr) {
- stdout = (stdout + "\n" + stderr).trim()
- if (er) {
- if (silent) {
- log.verbose("git clone " + u, stdout)
- } else {
- log.error("git clone " + u, stdout)
+ var args = [
+ 'clone',
+ '--template=' + templates,
+ '--mirror',
+ gitURL, cachedRemote
+ ]
+ git.whichAndExec(
+ ['clone', '--template=' + templates, '--mirror', gitURL, cachedRemote],
+ { cwd: cachedRemote, env: gitEnv() },
+ function (er, stdout, stderr) {
+ if (er) {
+ var combined = (stdout + '\n' + stderr).trim()
+ var command = 'git ' + args.join(' ') + ':'
+ if (silent) {
+ log.verbose(command, combined)
+ } else {
+ log.error(command, combined)
+ }
+ return cb(er)
}
- return cb(er)
+ log.verbose('addRemoteGit', 'git clone ' + gitURL, stdout.trim())
+ setPermissions(cb)
}
- log.verbose("git clone " + u, stdout)
- fetchRemote(p, u, co, origUrl, cb)
- }
- )
- })
-}
+ )
+ })
+ }
-function fetchRemote (p, u, co, origUrl, cb) {
- git.whichAndExec(
- [ "fetch", "-a", "origin" ],
- { cwd : p, env : gitEnv() },
- function (er, stdout, stderr) {
- stdout = (stdout + "\n" + stderr).trim()
- if (er) {
- log.error("git fetch -a origin ("+u+")", stdout)
- return cb(er)
- }
- log.verbose("git fetch -a origin ("+u+")", stdout)
+ function setPermissions (cb) {
+ if (process.platform === 'win32') {
+ log.verbose('addRemoteGit', 'skipping chownr on Windows')
+ resolveHead(cb)
+ } else {
+ getGitDir(function (er, cs) {
+ if (er) {
+ log.error('addRemoteGit', 'could not get cache stat')
+ return cb(er)
+ }
- if (process.platform === "win32") {
- log.silly("verifyOwnership", "skipping for windows")
- resolveHead(p, u, co, origUrl, cb)
- }
- else {
- getGitDir(function (er, cs) {
+ chownr(cachedRemote, cs.uid, cs.gid, function (er) {
if (er) {
- log.error("Could not get cache stat")
+ log.error(
+ 'addRemoteGit',
+ 'Failed to change folder ownership under npm cache for',
+ cachedRemote
+ )
return cb(er)
}
- chownr(p, cs.uid, cs.gid, function (er) {
- if (er) {
- log.error("Failed to change folder ownership under npm cache for %s", p)
- return cb(er)
- }
-
- resolveHead(p, u, co, origUrl, cb)
- })
+ log.verbose('addRemoteGit', 'set permissions on', cachedRemote)
+ resolveHead(cb)
})
- }
+ })
}
- )
-}
-
-function resolveHead (p, u, co, origUrl, cb) {
- git.whichAndExec(
- [ "rev-list", "-n1", co ],
- { cwd : p, env : gitEnv() },
- function (er, stdout, stderr) {
- stdout = (stdout + "\n" + stderr).trim()
- if (er) {
- log.error("Failed resolving git HEAD (" + u + ")", stderr)
- return cb(er)
- }
- log.verbose("git rev-list -n1 " + co, stdout)
- var parsed = url.parse(origUrl)
- parsed.hash = stdout
- var resolved = url.format(parsed)
+ }
- if (!/^git[+:]/.test(parsed.protocol)) {
- resolved = "git+" + resolved
- }
+ // always fetch the origin, even right after mirroring, because this way
+ // permissions will get set correctly
+ function updateRemote (cb) {
+ git.whichAndExec(
+ ['fetch', '-a', 'origin'],
+ { cwd: cachedRemote, env: gitEnv() },
+ function (er, stdout, stderr) {
+ if (er) {
+ var combined = (stdout + '\n' + stderr).trim()
+ log.error('git fetch -a origin (' + gitURL + ')', combined)
+ return cb(er)
+ }
+ log.verbose('addRemoteGit', 'git fetch -a origin (' + gitURL + ')', stdout.trim())
- // https://github.com/npm/npm/issues/3224
- // node incorrectly sticks a / at the start of the path We know that the
- // host won't change, so split and detect this
- var spo = origUrl.split(parsed.host)
- var spr = resolved.split(parsed.host)
- if (spo[1].charAt(0) === ":" && spr[1].charAt(0) === "/") {
- spr[1] = spr[1].slice(1)
+ setPermissions(cb)
}
- resolved = spr.join(parsed.host)
+ )
+ }
- log.verbose("resolved git url", resolved)
- cache(p, u, stdout, resolved, cb)
- }
- )
-}
+ // branches and tags are both symbolic labels that can be attached to different
+ // commits, so resolve the commitish to the current actual treeish the label
+ // corresponds to
+ //
+ // important for shrinkwrap
+ function resolveHead (cb) {
+ log.verbose('addRemoteGit', 'original treeish:', treeish)
+ var args = ['rev-list', '-n1', treeish]
+ git.whichAndExec(
+ args,
+ { cwd: cachedRemote, env: gitEnv() },
+ function (er, stdout, stderr) {
+ if (er) {
+ log.error('git ' + args.join(' ') + ':', stderr)
+ return cb(er)
+ }
-/**
- * Make an actual clone from the bare (mirrored) cache. There is no safe way to
- * do a one-step clone to a treeish that isn't guaranteed to be a branch, so
- * this has to be two steps.
- */
-function cache (p, u, treeish, resolved, cb) {
- // generate a unique filename
- randomBytes(6, function (er, random) {
- if (er) return cb(er)
+ resolvedTreeish = stdout.trim()
+ log.silly('addRemoteGit', 'resolved treeish:', resolvedTreeish)
- var tmp = path.join(
- npm.tmp,
- "git-cache-"+random.toString("hex"),
- treeish
- )
+ resolvedURL = getResolved(originalURL, resolvedTreeish)
+ log.verbose('addRemoteGit', 'resolved Git URL:', resolvedURL)
- mkdir(tmp, function (er) {
- if (er) return cb(er)
+ // generate a unique filename
+ tmpdir = path.join(
+ npm.tmp,
+ 'git-cache-' + randomBytes(6).toString('hex'),
+ resolvedTreeish
+ )
+ log.silly('addRemoteGit', 'Git working directory:', tmpdir)
- git.whichAndExec(["clone", p, tmp], { cwd : p, env : gitEnv() }, clone)
- })
+ mkdir(tmpdir, function (er) {
+ if (er) return cb(er)
- function clone (er, stdout, stderr) {
- stdout = (stdout + "\n" + stderr).trim()
- if (er) {
- log.error("Failed to clone "+resolved+" from "+u, stderr)
- return cb(er)
+ cloneResolved(cb)
+ })
}
- log.verbose("git clone", "from", p)
- log.verbose("git clone", stdout)
+ )
+ }
- git.whichAndExec(["checkout", treeish], { cwd : tmp, env : gitEnv() }, checkout)
- }
+ // make a clone from the mirrored cache so we have a temporary directory in
+ // which we can check out the resolved treeish
+ function cloneResolved (cb) {
+ var args = ['clone', cachedRemote, tmpdir]
+ git.whichAndExec(
+ args,
+ { cwd: cachedRemote, env: gitEnv() },
+ function (er, stdout, stderr) {
+ stdout = (stdout + '\n' + stderr).trim()
+ if (er) {
+ log.error('git ' + args.join(' ') + ':', stderr)
+ return cb(er)
+ }
+ log.verbose('addRemoteGit', 'clone', stdout)
- function checkout (er, stdout, stderr) {
- stdout = (stdout + "\n" + stderr).trim()
- if (er) {
- log.error("Failed to check out "+treeish, stderr)
- return cb(er)
+ checkoutTreeish(cb)
}
- log.verbose("git checkout", stdout)
+ )
+ }
- realizePackageSpecifier(tmp, function (er, spec) {
+ // there is no safe way to do a one-step clone to a treeish that isn't
+ // guaranteed to be a branch, so explicitly check out the treeish once it's
+ // cloned
+ function checkoutTreeish (cb) {
+ var args = ['checkout', resolvedTreeish]
+ git.whichAndExec(
+ args,
+ { cwd: tmpdir, env: gitEnv() },
+ function (er, stdout, stderr) {
+ stdout = (stdout + '\n' + stderr).trim()
if (er) {
- log.error("Failed to map", tmp, "to a package specifier")
+ log.error('git ' + args.join(' ') + ':', stderr)
return cb(er)
}
+ log.verbose('addRemoteGit', 'checkout', stdout)
- // https://github.com/npm/npm/issues/6400
- // ensure pack logic is applied
- addLocal(spec, null, function (er, data) {
- if (data) data._resolved = resolved
- cb(er, data)
+ // convince addLocal that the checkout is a local dependency
+ realizePackageSpecifier(tmpdir, function (er, spec) {
+ if (er) {
+ log.error('addRemoteGit', 'Failed to map', tmpdir, 'to a package specifier')
+ return cb(er)
+ }
+
+ // ensure pack logic is applied
+ // https://github.com/npm/npm/issues/6400
+ addLocal(spec, null, function (er, data) {
+ if (data) {
+ log.verbose('addRemoteGit', 'data._resolved:', resolvedURL)
+ data._resolved = resolvedURL
+
+ // the spec passed to addLocal is not what the user originally requested,
+ // so remap
+ // https://github.com/npm/npm/issues/7121
+ if (!data._fromGitHub) {
+ log.silly('addRemoteGit', 'data._from:', originalURL)
+ data._from = originalURL
+ } else {
+ log.silly('addRemoteGit', 'data._from:', data._from, '(GitHub)')
+ }
+ }
+
+ cb(er, data)
+ })
+ })
+ }
+ )
+ }
+}
+
+function getGitDir (cb) {
+ getCacheStat(function (er, stats) {
+ if (er) return cb(er)
+
+ // We don't need global templates when cloning. Use an empty directory for
+ // the templates, creating it (and setting its permissions) if necessary.
+ mkdir(templates, function (er) {
+ if (er) return cb(er)
+
+ // Ensure that both the template and remotes directories have the correct
+ // permissions.
+ fs.chown(templates, stats.uid, stats.gid, function (er) {
+ if (er) return cb(er)
+
+ fs.chown(remotes, stats.uid, stats.gid, function (er) {
+ cb(er, stats)
})
})
- }
+ })
})
}
@@ -280,41 +341,60 @@ function gitEnv () {
return gitEnv_
}
+function getResolved (uri, treeish) {
+ var parsed = url.parse(uri)
+ parsed.hash = treeish
+ if (!/^git[+:]/.test(parsed.protocol)) {
+ parsed.protocol = 'git+' + parsed.protocol
+ }
+ var resolved = url.format(parsed)
+
+ // node incorrectly sticks a / at the start of the path We know that the host
+ // won't change, so split and detect this
+ // https://github.com/npm/npm/issues/3224
+ var spo = uri.split(parsed.host)
+ var spr = resolved.split(parsed.host)
+ if (spo[1].charAt(0) === ':' && spr[1].charAt(0) === '/') {
+ spr[1] = spr[1].slice(1)
+ }
+ return spr.join(parsed.host)
+}
+
// similar to chmodr except it add permissions rather than overwriting them
// adapted from https://github.com/isaacs/chmodr/blob/master/chmodr.js
-function addModeRecursive(p, mode, cb) {
- fs.readdir(p, function (er, children) {
+function addModeRecursive (cachedRemote, mode, cb) {
+ fs.readdir(cachedRemote, function (er, children) {
// Any error other than ENOTDIR means it's not readable, or doesn't exist.
// Give up.
- if (er && er.code !== "ENOTDIR") return cb(er)
- if (er || !children.length) return addMode(p, mode, cb)
+ if (er && er.code !== 'ENOTDIR') return cb(er)
+ if (er || !children.length) return addMode(cachedRemote, mode, cb)
var len = children.length
var errState = null
children.forEach(function (child) {
- addModeRecursive(path.resolve(p, child), mode, then)
+ addModeRecursive(path.resolve(cachedRemote, child), mode, then)
})
function then (er) {
if (errState) return undefined
if (er) return cb(errState = er)
- if (--len === 0) return addMode(p, dirMode(mode), cb)
+ if (--len === 0) return addMode(cachedRemote, dirMode(mode), cb)
}
})
}
-function addMode(p, mode, cb) {
- fs.stat(p, function (er, stats) {
+function addMode (cachedRemote, mode, cb) {
+ fs.stat(cachedRemote, function (er, stats) {
if (er) return cb(er)
mode = stats.mode | mode
- fs.chmod(p, mode, cb)
+ fs.chmod(cachedRemote, mode, cb)
})
}
// taken from https://github.com/isaacs/chmodr/blob/master/chmodr.js
-function dirMode(mode) {
- if (mode & parseInt("0400", 8)) mode |= parseInt("0100", 8)
- if (mode & parseInt( "040", 8)) mode |= parseInt( "010", 8)
- if (mode & parseInt( "04", 8)) mode |= parseInt( "01", 8)
+function dirMode (mode) {
+ if (mode & parseInt('0400', 8)) mode |= parseInt('0100', 8)
+ if (mode & parseInt('040', 8)) mode |= parseInt('010', 8)
+ if (mode & parseInt('04', 8)) mode |= parseInt('01', 8)
return mode
}
diff --git a/deps/npm/lib/cache/add-remote-tarball.js b/deps/npm/lib/cache/add-remote-tarball.js
index e87ac54bb1..66d2200966 100644
--- a/deps/npm/lib/cache/add-remote-tarball.js
+++ b/deps/npm/lib/cache/add-remote-tarball.js
@@ -19,8 +19,8 @@ function addRemoteTarball (u, pkgData, shasum, auth, cb_) {
function cb (er, data) {
if (data) {
data._from = u
- data._shasum = data._shasum || shasum
data._resolved = u
+ data._shasum = data._shasum || shasum
}
cb_(er, data)
}
diff --git a/deps/npm/lib/config/defaults.js b/deps/npm/lib/config/defaults.js
index e49ce210b3..e5744772ed 100644
--- a/deps/npm/lib/config/defaults.js
+++ b/deps/npm/lib/config/defaults.js
@@ -32,12 +32,6 @@ function validateSemver (data, k, val) {
data[k] = semver.valid(val)
}
-function validateTag (data, k, val) {
- val = ("" + val).trim()
- if (!val || semver.validRange(val)) return false
- data[k] = val
-}
-
function validateStream (data, k, val) {
if (!(val instanceof Stream)) return false
data[k] = val
@@ -47,10 +41,6 @@ nopt.typeDefs.semver = { type: semver, validate: validateSemver }
nopt.typeDefs.Stream = { type: Stream, validate: validateStream }
nopt.typeDefs.Umask = { type: Umask, validate: validateUmask }
-// Don't let --tag=1.2.3 ever be a thing
-var tag = {}
-nopt.typeDefs.tag = { type: tag, validate: validateTag }
-
nopt.invalidHandler = function (k, val, type) {
log.warn("invalid config", k + "=" + JSON.stringify(val))
@@ -60,9 +50,6 @@ nopt.invalidHandler = function (k, val, type) {
}
switch (type) {
- case tag:
- log.warn("invalid config", "Tag must not be a SemVer range")
- break
case Umask:
log.warn("invalid config", "Must be umask, octal number in range 0000..0777")
break
@@ -312,7 +299,7 @@ exports.types =
, "sign-git-tag": Boolean
, spin: ["always", Boolean]
, "strict-ssl": Boolean
- , tag : tag
+ , tag : String
, tmp : path
, unicode : Boolean
, "unsafe-perm" : Boolean
diff --git a/deps/npm/lib/dedupe.js b/deps/npm/lib/dedupe.js
index 6a4abd7307..c63705e18d 100644
--- a/deps/npm/lib/dedupe.js
+++ b/deps/npm/lib/dedupe.js
@@ -314,11 +314,28 @@ function readInstalled (dir, counter, parent, cb) {
})
fs.readdir(path.resolve(dir, "node_modules"), function (er, c) {
- children = c || [] // error is ok, just means no children.
- children = children.filter(function (p) {
- return !p.match(/^[\._-]/)
- })
- next()
+ children = children || [] // error is ok, just means no children.
+ // check if there are scoped packages.
+ asyncMap(c || [], function (child, cb) {
+ if (child.indexOf('@') === 0) {
+ fs.readdir(path.resolve(dir, "node_modules", child), function (er, scopedChildren) {
+ // error is ok, just means no children.
+ (scopedChildren || []).forEach(function (sc) {
+ children.push(path.join(child, sc))
+ })
+ cb()
+ })
+ } else {
+ children.push(child)
+ cb()
+ }
+ }, function (er) {
+ if (er) return cb(er)
+ children = children.filter(function (p) {
+ return !p.match(/^[\._-]/)
+ })
+ next();
+ });
})
function next () {
diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js
index 73580e5afa..1a235793df 100644
--- a/deps/npm/lib/install.js
+++ b/deps/npm/lib/install.js
@@ -109,6 +109,7 @@ var npm = require("./npm.js")
, locker = require("./utils/locker.js")
, lock = locker.lock
, unlock = locker.unlock
+ , warnStrict = require("./utils/warn-deprecated.js")("engineStrict")
, warnPeers = require("./utils/warn-deprecated.js")("peerDependencies")
function install (args, cb_) {
@@ -117,7 +118,7 @@ function install (args, cb_) {
function cb (er, installed) {
if (er) return cb_(er)
- findPeerInvalid(where, function (er, problem) {
+ validateInstall(where, function (er, problem) {
if (er) return cb_(er)
if (problem) {
@@ -244,11 +245,24 @@ function install (args, cb_) {
})
}
-function findPeerInvalid (where, cb) {
- readInstalled(where, { log: log.warn, dev: true }, function (er, data) {
- if (er) return cb(er)
+function validateInstall (where, cb) {
+ readJson(path.resolve(where, 'package.json'), log.warn, function (er, data) {
+ if (er
+ && er.code !== 'ENOENT'
+ && er.code !== 'ENOTDIR') return cb(er)
+
+ if (data && data.engineStrict) {
+ warnStrict([
+ "Per-package engineStrict (found in this package's package.json) ",
+ "won't be used in npm 3+. Use the config setting `engine-strict` instead."
+ ], data.name)
+ }
+
+ readInstalled(where, { log: log.warn, dev: true }, function (er, data) {
+ if (er) return cb(er)
- cb(null, findPeerInvalid_(data.dependencies, []))
+ cb(null, findPeerInvalid_(data.dependencies, []))
+ })
})
}
@@ -854,8 +868,11 @@ function targetResolver (where, context, deps) {
function installOne (target, where, context, cb) {
// the --link flag makes this a "link" command if it's at the
// the top level.
+ var isGit = false
+ if (target && target._from) isGit = npa(target._from).type === 'git'
+
if (where === npm.prefix && npm.config.get("link")
- && !npm.config.get("global")) {
+ && !npm.config.get("global") && !isGit) {
return localLink(target, where, context, cb)
}
installOne_(target, where, context, function (er, installedWhat) {
diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js
index 3cd21cac1d..459a3c3245 100644
--- a/deps/npm/lib/npm.js
+++ b/deps/npm/lib/npm.js
@@ -66,6 +66,7 @@ var commandCache = {}
, "i" : "install"
, "isntall" : "install"
, "up" : "update"
+ , "upgrade" : "update"
, "c" : "config"
, "dist-tags" : "dist-tag"
, "info" : "view"
diff --git a/deps/npm/lib/publish.js b/deps/npm/lib/publish.js
index 06a3404af9..92a9a9b671 100644
--- a/deps/npm/lib/publish.js
+++ b/deps/npm/lib/publish.js
@@ -13,10 +13,12 @@ var npm = require("./npm.js")
, cachedPackageRoot = require("./cache/cached-package-root.js")
, createReadStream = require("graceful-fs").createReadStream
, npa = require("npm-package-arg")
+ , semver = require('semver')
-publish.usage = "npm publish <tarball>"
- + "\nnpm publish <folder>"
+publish.usage = "npm publish <tarball> [--tag <tagname>]"
+ + "\nnpm publish <folder> [--tag <tagname>]"
+ "\n\nPublishes '.' if no argument supplied"
+ + "\n\nSets tag `latest` if no --tag specified"
publish.completion = function (opts, cb) {
// publish can complete to a folder with a package.json
@@ -34,6 +36,13 @@ function publish (args, isRetry, cb) {
if (args.length !== 1) return cb(publish.usage)
log.verbose("publish", args)
+
+ var t = npm.config.get('tag').trim()
+ if (semver.validRange(t)) {
+ var er = new Error("Tag name must not be a valid SemVer range: " + t)
+ return cb(er)
+ }
+
var arg = args[0]
// if it's a local folder, then run the prepublish there, first.
readJson(path.resolve(arg, "package.json"), function (er, data) {
diff --git a/deps/npm/lib/stars.js b/deps/npm/lib/stars.js
index 087e8d9bf2..01ec76e42c 100644
--- a/deps/npm/lib/stars.js
+++ b/deps/npm/lib/stars.js
@@ -9,6 +9,17 @@ var npm = require("./npm.js")
function stars (args, cb) {
npm.commands.whoami([], true, function (er, username) {
var name = args.length === 1 ? args[0] : username
+
+ if (er) {
+ if (er.code === 'ENEEDAUTH' && !name) {
+ var needAuth = new Error("'npm stars' on your own user account requires auth")
+ needAuth.code = 'ENEEDAUTH'
+ return cb(needAuth)
+ }
+
+ if (er.code !== 'ENEEDAUTH') return cb(er)
+ }
+
mapToRegistry("", npm.config, function (er, uri, auth) {
if (er) return cb(er)
diff --git a/deps/npm/lib/update.js b/deps/npm/lib/update.js
index 06d199cc09..3e9438e923 100644
--- a/deps/npm/lib/update.js
+++ b/deps/npm/lib/update.js
@@ -22,10 +22,26 @@ update.completion = npm.commands.outdated.completion
function update (args, cb) {
npm.commands.outdated(args, true, function (er, outdated) {
- log.info("outdated", "updating", outdated)
if (er) return cb(er)
- asyncMap(outdated, function (ww, cb) {
+ var wanted = outdated.filter(function (ww) {
+ var dep = ww[1]
+ var current = ww[2]
+ var wanted = ww[3]
+ var latest = ww[4]
+ if (current === wanted && wanted !== latest) {
+ log.verbose(
+ 'outdated',
+ 'not updating', dep,
+ "because it's currently at the maximum version that matches its specified semver range"
+ )
+ }
+ return current !== wanted
+ })
+ if (wanted.length === 0) return cb()
+
+ log.info('outdated', 'updating', wanted)
+ asyncMap(wanted, function (ww, cb) {
// [[ dir, dep, has, want, req ]]
var where = ww[0]
, dep = ww[1]
diff --git a/deps/npm/lib/utils/error-handler.js b/deps/npm/lib/utils/error-handler.js
index de12c63632..1c80ab590f 100644
--- a/deps/npm/lib/utils/error-handler.js
+++ b/deps/npm/lib/utils/error-handler.js
@@ -287,6 +287,7 @@ function errorHandler (er) {
case "ECONNRESET":
case "ENOTFOUND":
case "ETIMEDOUT":
+ case "EAI_FAIL":
log.error("network", [er.message
,"This is most likely not a problem with npm itself"
,"and is related to network connectivity."
@@ -354,7 +355,7 @@ function errorHandler (er) {
default:
log.error("", er.message || er)
log.error("", ["", "If you need help, you may report this error at:"
- ," <http://github.com/npm/npm/issues>"
+ ," <https://github.com/npm/npm/issues>"
].join("\n"))
break
}
diff --git a/deps/npm/lib/whoami.js b/deps/npm/lib/whoami.js
index 42cede1b82..d92a6574a1 100644
--- a/deps/npm/lib/whoami.js
+++ b/deps/npm/lib/whoami.js
@@ -14,14 +14,6 @@ function whoami (args, silent, cb) {
var registry = npm.config.get("registry")
if (!registry) return cb(new Error("no default registry set"))
- function noUser () {
- // At this point, if they have a credentials object, it doesn't have a
- // token or auth in it. Probably just the default registry.
- var msg = "Not authed. Run 'npm adduser'"
- if (!silent) console.log(msg)
- cb(null, msg)
- }
-
var auth = npm.config.getCredentialsByURI(registry)
if (auth) {
if (auth.username) {
@@ -31,7 +23,13 @@ function whoami (args, silent, cb) {
else if (auth.token) {
return npm.registry.whoami(registry, { auth : auth }, function (er, username) {
if (er) return cb(er)
- if (!username) return noUser()
+ if (!username) {
+ var needNewSession = new Error(
+ "Your auth token is no longer valid. Please log in again."
+ )
+ needNewSession.code = 'ENEEDAUTH'
+ return cb(needNewSession)
+ }
if (!silent) console.log(username)
cb(null, username)
@@ -39,5 +37,11 @@ function whoami (args, silent, cb) {
}
}
- process.nextTick(noUser)
+ // At this point, if they have a credentials object, it doesn't have a token
+ // or auth in it. Probably just the default registry.
+ var needAuth = new Error(
+ "'npm whoami' requires you to be logged in."
+ )
+ needAuth.code = 'ENEEDAUTH'
+ process.nextTick(cb.bind(this, needAuth))
}