summaryrefslogtreecommitdiff
path: root/deps/npm/lib
diff options
context:
space:
mode:
authorRebecca Turner <me@re-becca.org>2017-04-12 21:47:49 -0700
committerJeremiah Senkpiel <fishrock123@rocketmail.com>2017-04-25 10:52:01 -0400
commit00842604483e4c2e622dfdb3a97440e07646158f (patch)
treef3346902636a44b6037652523767636bf7e4f2c9 /deps/npm/lib
parent061c5da010e0d249379618382a499840d38247b8 (diff)
downloadandroid-node-v8-00842604483e4c2e622dfdb3a97440e07646158f.tar.gz
android-node-v8-00842604483e4c2e622dfdb3a97440e07646158f.tar.bz2
android-node-v8-00842604483e4c2e622dfdb3a97440e07646158f.zip
deps: upgrade npm to 4.5.0
PR-URL: https://github.com/nodejs/node/pull/12480 Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Diffstat (limited to 'deps/npm/lib')
-rw-r--r--deps/npm/lib/adduser.js159
-rw-r--r--deps/npm/lib/auth/legacy.js142
-rw-r--r--deps/npm/lib/auth/oauth.js7
-rw-r--r--deps/npm/lib/auth/saml.js7
-rw-r--r--deps/npm/lib/auth/sso.js59
-rw-r--r--deps/npm/lib/bugs.js2
-rw-r--r--deps/npm/lib/config/core.js2
-rw-r--r--deps/npm/lib/config/defaults.js12
-rw-r--r--deps/npm/lib/docs.js2
-rw-r--r--deps/npm/lib/doctor/check-files-permission.js2
-rw-r--r--deps/npm/lib/doctor/get-latest-npm-version.js2
-rw-r--r--deps/npm/lib/fetch-package-metadata.js28
-rw-r--r--deps/npm/lib/install.js2
-rw-r--r--deps/npm/lib/install/action/extract.js75
-rw-r--r--deps/npm/lib/install/action/finalize.js24
-rw-r--r--deps/npm/lib/install/action/move.js12
-rw-r--r--deps/npm/lib/install/action/remove.js10
-rw-r--r--deps/npm/lib/install/action/test.js8
-rw-r--r--deps/npm/lib/install/actions.js7
-rw-r--r--deps/npm/lib/install/deps.js4
-rw-r--r--deps/npm/lib/install/inflate-bundled.js8
-rw-r--r--deps/npm/lib/install/inflate-shrinkwrap.js2
-rw-r--r--deps/npm/lib/install/validate-tree.js20
-rw-r--r--deps/npm/lib/ls.js121
-rw-r--r--deps/npm/lib/npm.js35
-rw-r--r--deps/npm/lib/outdated.js2
-rw-r--r--deps/npm/lib/repo.js2
-rw-r--r--deps/npm/lib/search/format-package-stream.js2
-rwxr-xr-xdeps/npm/lib/utils/completion.sh5
-rw-r--r--deps/npm/lib/utils/error-handler.js71
-rw-r--r--deps/npm/lib/utils/error-message.js9
-rw-r--r--deps/npm/lib/utils/lifecycle.js10
-rw-r--r--deps/npm/lib/utils/move.js19
-rw-r--r--deps/npm/lib/utils/rename.js21
-rw-r--r--deps/npm/lib/utils/tar.js4
35 files changed, 546 insertions, 351 deletions
diff --git a/deps/npm/lib/adduser.js b/deps/npm/lib/adduser.js
index 7f3975175a..0aac6b7fbb 100644
--- a/deps/npm/lib/adduser.js
+++ b/deps/npm/lib/adduser.js
@@ -2,11 +2,7 @@ module.exports = adduser
var log = require('npmlog')
var npm = require('./npm.js')
-var read = require('read')
-var userValidate = require('npm-user-validate')
-var output = require('./utils/output')
var usage = require('./utils/usage')
-var chain = require('slide').chain
var crypto
try {
@@ -15,7 +11,7 @@ try {
adduser.usage = usage(
'adduser',
- 'npm adduser [--registry=url] [--scope=@orgname] [--always-auth]'
+ 'npm adduser [--registry=url] [--scope=@orgname] [--auth-type=legacy] [--always-auth]'
)
function adduser (args, cb) {
@@ -25,154 +21,29 @@ function adduser (args, cb) {
))
}
- var creds = npm.config.getCredentialsByURI(npm.config.get('registry'))
- var c = {
- u: creds.username || '',
- p: creds.password || '',
- e: creds.email || ''
- }
- var u = {}
-
- log.disableProgress()
- chain([
- [readUsername, c, u],
- [readPassword, c, u],
- [readEmail, c, u],
- [save, c, u]
- ], cb)
-}
-
-function readUsername (c, u, cb) {
- var v = userValidate.username
- read({prompt: 'Username: ', default: c.u || ''}, function (er, un) {
- if (er) {
- return cb(er.message === 'cancelled' ? er.message : er)
- }
-
- // make sure it's valid. we have to do this here, because
- // couchdb will only ever say "bad password" with a 401 when
- // you try to PUT a _users record that the validate_doc_update
- // rejects for *any* reason.
-
- if (!un) {
- return readUsername(c, u, cb)
- }
-
- var error = v(un)
- if (error) {
- log.warn(error.message)
- return readUsername(c, u, cb)
- }
-
- c.changed = c.u !== un
- u.u = un
- cb(er)
- })
-}
-
-function readPassword (c, u, cb) {
- var v = userValidate.pw
-
- var prompt
- if (c.p && !c.changed) {
- prompt = 'Password: (or leave unchanged) '
- } else {
- prompt = 'Password: '
- }
-
- read({prompt: prompt, silent: true}, function (er, pw) {
- if (er) {
- return cb(er.message === 'cancelled' ? er.message : er)
- }
-
- if (!c.changed && pw === '') {
- // when the username was not changed,
- // empty response means "use the old value"
- pw = c.p
- }
-
- if (!pw) {
- return readPassword(c, u, cb)
- }
-
- var error = v(pw)
- if (error) {
- log.warn(error.message)
- return readPassword(c, u, cb)
- }
-
- c.changed = c.changed || c.p !== pw
- u.p = pw
- cb(er)
- })
-}
-
-function readEmail (c, u, cb) {
- var v = userValidate.email
- var r = { prompt: 'Email: (this IS public) ', default: c.e || '' }
- read(r, function (er, em) {
- if (er) {
- return cb(er.message === 'cancelled' ? er.message : er)
- }
-
- if (!em) {
- return readEmail(c, u, cb)
- }
-
- var error = v(em)
- if (error) {
- log.warn(error.message)
- return readEmail(c, u, cb)
- }
-
- u.e = em
- cb(er)
- })
-}
-
-function save (c, u, cb) {
- // save existing configs, but yank off for this PUT
- var uri = npm.config.get('registry')
+ var registry = npm.config.get('registry')
var scope = npm.config.get('scope')
+ var creds = npm.config.getCredentialsByURI(npm.config.get('registry'))
- // there may be a saved scope and no --registry (for login)
if (scope) {
var scopedRegistry = npm.config.get(scope + ':registry')
var cliRegistry = npm.config.get('registry', 'cli')
- if (scopedRegistry && !cliRegistry) uri = scopedRegistry
- }
-
- var params = {
- auth: {
- username: u.u,
- password: u.p,
- email: u.e
- }
+ if (scopedRegistry && !cliRegistry) registry = scopedRegistry
}
- npm.registry.adduser(uri, params, function (er, doc) {
- if (er) return cb(er)
-
- // don't want this polluting the configuration
- npm.config.del('_token', 'user')
- if (scope) npm.config.set(scope + ':registry', uri, 'user')
+ log.disableProgress()
- if (doc && doc.token) {
- npm.config.setCredentialsByURI(uri, {
- token: doc.token
- })
- } else {
- npm.config.setCredentialsByURI(uri, {
- username: u.u,
- password: u.p,
- email: u.e,
- alwaysAuth: npm.config.get('always-auth')
- })
- }
+ try {
+ var auth = require('./auth/' + npm.config.get('auth-type'))
+ } catch (e) {
+ return cb(new Error('no such auth module'))
+ }
+ auth.login(creds, registry, scope, function (err, newCreds) {
+ if (err) return cb(err)
- log.info('adduser', 'Authorized user %s', u.u)
- var scopeMessage = scope ? ' to scope ' + scope : ''
- output('Logged in as %s%s on %s.', u.u, scopeMessage, uri)
+ npm.config.del('_token', 'user') // prevent legacy pollution
+ if (scope) npm.config.set(scope + ':registry', registry, 'user')
+ npm.config.setCredentialsByURI(registry, newCreds)
npm.config.save('user', cb)
})
}
diff --git a/deps/npm/lib/auth/legacy.js b/deps/npm/lib/auth/legacy.js
new file mode 100644
index 0000000000..2fa4a26e35
--- /dev/null
+++ b/deps/npm/lib/auth/legacy.js
@@ -0,0 +1,142 @@
+var log = require('npmlog')
+var npm = require('../npm.js')
+var read = require('read')
+var userValidate = require('npm-user-validate')
+var output = require('../utils/output')
+var chain = require('slide').chain
+
+module.exports.login = function login (creds, registry, scope, cb) {
+ var c = {
+ u: creds.username || '',
+ p: creds.password || '',
+ e: creds.email || ''
+ }
+ var u = {}
+
+ chain([
+ [readUsername, c, u],
+ [readPassword, c, u],
+ [readEmail, c, u],
+ [save, c, u, registry, scope]
+ ], function (err, res) {
+ cb(err, res && res[res.length - 1])
+ })
+}
+
+function readUsername (c, u, cb) {
+ var v = userValidate.username
+ read({prompt: 'Username: ', default: c.u || ''}, function (er, un) {
+ if (er) {
+ return cb(er.message === 'cancelled' ? er.message : er)
+ }
+
+ // make sure it's valid. we have to do this here, because
+ // couchdb will only ever say "bad password" with a 401 when
+ // you try to PUT a _users record that the validate_doc_update
+ // rejects for *any* reason.
+
+ if (!un) {
+ return readUsername(c, u, cb)
+ }
+
+ var error = v(un)
+ if (error) {
+ log.warn(error.message)
+ return readUsername(c, u, cb)
+ }
+
+ c.changed = c.u !== un
+ u.u = un
+ cb(er)
+ })
+}
+
+function readPassword (c, u, cb) {
+ var v = userValidate.pw
+
+ var prompt
+ if (c.p && !c.changed) {
+ prompt = 'Password: (or leave unchanged) '
+ } else {
+ prompt = 'Password: '
+ }
+
+ read({prompt: prompt, silent: true}, function (er, pw) {
+ if (er) {
+ return cb(er.message === 'cancelled' ? er.message : er)
+ }
+
+ if (!c.changed && pw === '') {
+ // when the username was not changed,
+ // empty response means "use the old value"
+ pw = c.p
+ }
+
+ if (!pw) {
+ return readPassword(c, u, cb)
+ }
+
+ var error = v(pw)
+ if (error) {
+ log.warn(error.message)
+ return readPassword(c, u, cb)
+ }
+
+ c.changed = c.changed || c.p !== pw
+ u.p = pw
+ cb(er)
+ })
+}
+
+function readEmail (c, u, cb) {
+ var v = userValidate.email
+ var r = { prompt: 'Email: (this IS public) ', default: c.e || '' }
+ read(r, function (er, em) {
+ if (er) {
+ return cb(er.message === 'cancelled' ? er.message : er)
+ }
+
+ if (!em) {
+ return readEmail(c, u, cb)
+ }
+
+ var error = v(em)
+ if (error) {
+ log.warn(error.message)
+ return readEmail(c, u, cb)
+ }
+
+ u.e = em
+ cb(er)
+ })
+}
+
+function save (c, u, registry, scope, cb) {
+ var params = {
+ auth: {
+ username: u.u,
+ password: u.p,
+ email: u.e
+ }
+ }
+ npm.registry.adduser(registry, params, function (er, doc) {
+ if (er) return cb(er)
+
+ var newCreds = (doc && doc.token)
+ ? {
+ token: doc.token
+ }
+ : {
+ username: u.u,
+ password: u.p,
+ email: u.e,
+ alwaysAuth: npm.config.get('always-auth')
+ }
+
+ log.info('adduser', 'Authorized user %s', u.u)
+ var scopeMessage = scope ? ' to scope ' + scope : ''
+ output('Logged in as %s%s on %s.', u.u, scopeMessage, registry)
+
+ cb(null, newCreds)
+ })
+}
diff --git a/deps/npm/lib/auth/oauth.js b/deps/npm/lib/auth/oauth.js
new file mode 100644
index 0000000000..1cb3ffec6f
--- /dev/null
+++ b/deps/npm/lib/auth/oauth.js
@@ -0,0 +1,7 @@
+var ssoAuth = require('./sso')
+var npm = require('../npm')
+
+module.exports.login = function login () {
+ npm.config.set('sso-type', 'oauth')
+ ssoAuth.login.apply(this, arguments)
+}
diff --git a/deps/npm/lib/auth/saml.js b/deps/npm/lib/auth/saml.js
new file mode 100644
index 0000000000..ae92ea5bbf
--- /dev/null
+++ b/deps/npm/lib/auth/saml.js
@@ -0,0 +1,7 @@
+var ssoAuth = require('./sso')
+var npm = require('../npm')
+
+module.exports.login = function login () {
+ npm.config.set('sso-type', 'saml')
+ ssoAuth.login.apply(this, arguments)
+}
diff --git a/deps/npm/lib/auth/sso.js b/deps/npm/lib/auth/sso.js
new file mode 100644
index 0000000000..faffe2fa59
--- /dev/null
+++ b/deps/npm/lib/auth/sso.js
@@ -0,0 +1,59 @@
+var log = require('npmlog')
+var npm = require('../npm.js')
+var output = require('../utils/output')
+var opener = require('opener')
+
+module.exports.login = function login (creds, registry, scope, cb) {
+ var ssoType = npm.config.get('sso-type')
+ if (!ssoType) { return cb(new Error('Missing option: sso-type')) }
+
+ var params = {
+ // We're reusing the legacy login endpoint, so we need some dummy
+ // stuff here to pass validation. They're never used.
+ auth: {
+ username: 'npm_' + ssoType + '_auth_dummy_user',
+ password: 'placeholder',
+ email: 'support@npmjs.com',
+ authType: ssoType
+ }
+ }
+ npm.registry.adduser(registry, params, function (er, doc) {
+ if (er) return cb(er)
+ if (!doc || !doc.token) return cb(new Error('no SSO token returned'))
+ if (!doc.sso) return cb(new Error('no SSO URL returned by services'))
+
+ output('If your browser doesn\'t open, visit ' +
+ doc.sso +
+ ' to complete authentication')
+ opener(doc.sso, { command: npm.config.get('browser') }, function () {
+ pollForSession(registry, doc.token, function (err, username) {
+ if (err) return cb(err)
+
+ log.info('adduser', 'Authorized user %s', username)
+ var scopeMessage = scope ? ' to scope ' + scope : ''
+ output('Logged in as %s%s on %s.', username, scopeMessage, registry)
+
+ cb(null, { token: doc.token })
+ })
+ })
+ })
+}
+
+function pollForSession (registry, token, cb) {
+ log.info('adduser', 'Polling for validated SSO session')
+ npm.registry.whoami(registry, {
+ auth: {
+ token: token
+ }
+ }, function (er, username) {
+ if (er && er.statusCode !== 401) {
+ cb(er)
+ } else if (!username) {
+ setTimeout(function () {
+ pollForSession(registry, token, cb)
+ }, npm.config.get('sso-poll-frequency'))
+ } else {
+ cb(null, username)
+ }
+ })
+}
diff --git a/deps/npm/lib/bugs.js b/deps/npm/lib/bugs.js
index 003ce7f8cb..5f166c33f6 100644
--- a/deps/npm/lib/bugs.js
+++ b/deps/npm/lib/bugs.js
@@ -19,7 +19,7 @@ bugs.completion = function (opts, cb) {
function bugs (args, cb) {
var n = args.length ? args[0] : '.'
- fetchPackageMetadata(n, '.', function (er, d) {
+ fetchPackageMetadata(n, '.', {fullMetadata: true}, function (er, d) {
if (er) return cb(er)
var url = d.bugs && ((typeof d.bugs === 'string') ? d.bugs : d.bugs.url)
diff --git a/deps/npm/lib/config/core.js b/deps/npm/lib/config/core.js
index b833b75409..15a1674b3d 100644
--- a/deps/npm/lib/config/core.js
+++ b/deps/npm/lib/config/core.js
@@ -208,7 +208,7 @@ inherits(Conf, CC)
function Conf (base) {
if (!(this instanceof Conf)) return new Conf(base)
- CC.apply(this)
+ CC.call(this)
if (base) {
if (base instanceof Conf) {
diff --git a/deps/npm/lib/config/defaults.js b/deps/npm/lib/config/defaults.js
index a79c8a0fa0..96499d1718 100644
--- a/deps/npm/lib/config/defaults.js
+++ b/deps/npm/lib/config/defaults.js
@@ -108,6 +108,7 @@ Object.defineProperty(exports, 'defaults', {get: function () {
access: null,
'always-auth': false,
also: null,
+ 'auth-type': 'legacy',
'bin-links': true,
browser: null,
@@ -148,6 +149,7 @@ Object.defineProperty(exports, 'defaults', {get: function () {
'global-style': false,
group: process.platform === 'win32' ? 0
: process.env.SUDO_GID || (process.getgid && process.getgid()),
+ 'ham-it-up': false,
heading: 'npm',
'if-present': false,
'ignore-scripts': false,
@@ -168,7 +170,7 @@ Object.defineProperty(exports, 'defaults', {get: function () {
long: false,
maxsockets: 50,
message: '%s',
- 'metrics-registry': 'https://registry.npmjs.org/',
+ 'metrics-registry': null,
'node-version': process.version,
'onload-script': false,
only: null,
@@ -203,6 +205,8 @@ Object.defineProperty(exports, 'defaults', {get: function () {
shell: osenv.shell(),
shrinkwrap: true,
'sign-git-tag': false,
+ 'sso-poll-frequency': 500,
+ 'sso-type': 'oauth',
'strict-ssl': true,
tag: 'latest',
'tag-version-prefix': 'v',
@@ -231,6 +235,7 @@ exports.types = {
access: [null, 'restricted', 'public'],
'always-auth': Boolean,
also: [null, 'dev', 'development'],
+ 'auth-type': ['legacy', 'sso', 'saml', 'oauth'],
'bin-links': Boolean,
browser: [null, String],
ca: [null, String, Array],
@@ -262,6 +267,7 @@ exports.types = {
group: [Number, String],
'https-proxy': [null, url],
'user-agent': String,
+ 'ham-it-up': Boolean,
'heading': String,
'if-present': Boolean,
'ignore-scripts': Boolean,
@@ -284,7 +290,7 @@ exports.types = {
long: Boolean,
maxsockets: Number,
message: String,
- 'metrics-registry': String,
+ 'metrics-registry': [null, String],
'node-version': [null, semver],
'onload-script': [null, String],
only: [null, 'dev', 'development', 'prod', 'production'],
@@ -314,6 +320,8 @@ exports.types = {
shell: String,
shrinkwrap: Boolean,
'sign-git-tag': Boolean,
+ 'sso-poll-frequency': Number,
+ 'sso-type': [null, 'oauth', 'saml'],
'strict-ssl': Boolean,
tag: String,
tmp: path,
diff --git a/deps/npm/lib/docs.js b/deps/npm/lib/docs.js
index 19dcce163c..2248702a46 100644
--- a/deps/npm/lib/docs.js
+++ b/deps/npm/lib/docs.js
@@ -33,7 +33,7 @@ function docs (args, cb) {
function getDoc (project, cb) {
log.silly('getDoc', project)
- fetchPackageMetadata(project, '.', function (er, d) {
+ fetchPackageMetadata(project, '.', {fullMetadata: true}, function (er, d) {
if (er) return cb(er)
var url = d.homepage
if (!url) url = 'https://www.npmjs.org/package/' + d.name
diff --git a/deps/npm/lib/doctor/check-files-permission.js b/deps/npm/lib/doctor/check-files-permission.js
index ac3bb40bc6..74393596f6 100644
--- a/deps/npm/lib/doctor/check-files-permission.js
+++ b/deps/npm/lib/doctor/check-files-permission.js
@@ -34,7 +34,7 @@ function checkFilesPermission (root, mask, cb) {
function checkFile (f, next) {
var file = path.join(root, f)
tracker.silly('checkFilePermissions', f)
- fs.stat(file, function (e, stat) {
+ fs.lstat(file, function (e, stat) {
tracker.completeWork(1)
if (e) return next(e)
if (!stat.isFile()) return next()
diff --git a/deps/npm/lib/doctor/get-latest-npm-version.js b/deps/npm/lib/doctor/get-latest-npm-version.js
index 4df0fee0fa..aba9b773cd 100644
--- a/deps/npm/lib/doctor/get-latest-npm-version.js
+++ b/deps/npm/lib/doctor/get-latest-npm-version.js
@@ -4,7 +4,7 @@ var fetchPackageMetadata = require('../fetch-package-metadata')
function getLatestNpmVersion (cb) {
var tracker = log.newItem('getLatestNpmVersion', 1)
tracker.info('getLatestNpmVersion', 'Getting npm package information')
- fetchPackageMetadata('npm@latest', '.', function (e, d) {
+ fetchPackageMetadata('npm@latest', '.', {fullMetadata: true}, function (e, d) {
tracker.finish()
cb(e, d.version)
})
diff --git a/deps/npm/lib/fetch-package-metadata.js b/deps/npm/lib/fetch-package-metadata.js
index bd6e47e17c..ae22004e5b 100644
--- a/deps/npm/lib/fetch-package-metadata.js
+++ b/deps/npm/lib/fetch-package-metadata.js
@@ -16,6 +16,7 @@ var clone = require('lodash.clonedeep')
var validate = require('aproba')
var unpipe = require('unpipe')
var normalizePackageData = require('normalize-package-data')
+var limit = require('call-limit')
var npm = require('./npm.js')
var mapToRegistry = require('./utils/map-to-registry.js')
@@ -39,12 +40,16 @@ function andLogAndFinish (spec, tracker, done) {
}
}
-module.exports = function fetchPackageMetadata (spec, where, tracker, done) {
+module.exports = limit(fetchPackageMetadata, npm.limit.fetch)
+
+function fetchPackageMetadata (spec, where, opts, done) {
+ validate('SSOF|SSFZ|OSOF|OSFZ', [spec, where, opts, done])
+
if (!done) {
- done = tracker || where
- tracker = null
- if (done === where) where = null
+ done = opts
+ opts = {}
}
+ var tracker = opts.tracker
if (typeof spec === 'object') {
var dep = spec
spec = dep.raw
@@ -53,11 +58,11 @@ module.exports = function fetchPackageMetadata (spec, where, tracker, done) {
if (!dep) {
log.silly('fetchPackageMetaData', spec)
return realizePackageSpecifier(spec, where, iferr(logAndFinish, function (dep) {
- fetchPackageMetadata(dep, where, tracker, done)
+ fetchPackageMetadata(dep, where, {tracker: tracker}, done)
}))
}
if (dep.type === 'version' || dep.type === 'range' || dep.type === 'tag') {
- fetchNamedPackageData(dep, addRequestedAndFinish)
+ fetchNamedPackageData(dep, opts, addRequestedAndFinish)
} else if (dep.type === 'directory') {
fetchDirectoryPackageData(dep, where, addRequestedAndFinish)
} else {
@@ -105,14 +110,15 @@ function fetchDirectoryPackageData (dep, where, next) {
var regCache = {}
-function fetchNamedPackageData (dep, next) {
- validate('OF', arguments)
+function fetchNamedPackageData (dep, opts, next) {
+ validate('OOF', arguments)
log.silly('fetchNamedPackageData', dep.name || dep.rawSpec)
mapToRegistry(dep.name || dep.rawSpec, npm.config, iferr(next, function (url, auth) {
if (regCache[url]) {
pickVersionFromRegistryDocument(clone(regCache[url]))
} else {
- npm.registry.get(url, {auth: auth}, pulseTillDone('fetchMetadata', iferr(next, pickVersionFromRegistryDocument)))
+ var fullMetadata = opts.fullMetadata == null ? true : opts.fullMetadata
+ npm.registry.get(url, {auth: auth, fullMetadata: fullMetadata}, pulseTillDone('fetchMetadata', iferr(next, pickVersionFromRegistryDocument)))
}
function thenAddMetadata (pkg) {
pkg._from = dep.raw
@@ -180,6 +186,10 @@ function retryWithCached (pkg, asserter, next) {
module.exports.addShrinkwrap = function addShrinkwrap (pkg, next) {
validate('OF', arguments)
if (pkg._shrinkwrap !== undefined) return next(null, pkg)
+ if (pkg._hasShrinkwrap === false) {
+ pkg._shrinkwrap = null
+ return next(null, pkg)
+ }
if (retryWithCached(pkg, addShrinkwrap, next)) return
pkg._shrinkwrap = null
// FIXME: cache the shrinkwrap directly
diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js
index 1b0601d9f4..43ba436630 100644
--- a/deps/npm/lib/install.js
+++ b/deps/npm/lib/install.js
@@ -508,7 +508,7 @@ Installer.prototype.rollbackFailedOptional = function (staging, actionsToRun, cb
}).filter(function (pkg) {
return pkg.failed && pkg.rollback
})
- var top = this.currentTree.path
+ var top = this.currentTree && this.currentTree.path
asyncMap(failed, function (pkg, next) {
asyncMap(pkg.rollback, function (rollback, done) {
rollback(top, staging, pkg, done)
diff --git a/deps/npm/lib/install/action/extract.js b/deps/npm/lib/install/action/extract.js
index 2c8a995af6..fd9562c184 100644
--- a/deps/npm/lib/install/action/extract.js
+++ b/deps/npm/lib/install/action/extract.js
@@ -3,7 +3,8 @@ var path = require('path')
var iferr = require('iferr')
var asyncMap = require('slide').asyncMap
var fs = require('graceful-fs')
-var rename = require('../../utils/rename.js')
+var mkdirp = require('mkdirp')
+var move = require('../../utils/move.js')
var gentlyRm = require('../../utils/gently-rm.js')
var updatePackageJson = require('../update-package-json')
var npm = require('../../npm.js')
@@ -11,6 +12,7 @@ var moduleName = require('../../utils/module-name.js')
var packageId = require('../../utils/package-id.js')
var cache = require('../../cache.js')
var moduleStagingPath = require('../module-staging-path.js')
+var readPackageJson = require('read-package-json')
module.exports = function (staging, pkg, log, next) {
log.silly('extract', packageId(pkg))
@@ -19,31 +21,45 @@ module.exports = function (staging, pkg, log, next) {
var group = up ? null : npm.config.get('group')
var extractTo = moduleStagingPath(staging, pkg)
cache.unpack(pkg.package.name, pkg.package.version, extractTo, null, null, user, group,
- andUpdatePackageJson(pkg, staging, extractTo, andStageBundledChildren(pkg, staging, extractTo, log, next)))
+ andUpdatePackageJson(pkg, staging, extractTo,
+ andStageBundledChildren(pkg, staging, extractTo, log,
+ andRemoveExtraneousBundles(extractTo, next))))
}
function andUpdatePackageJson (pkg, staging, extractTo, next) {
return iferr(next, function () {
- updatePackageJson(pkg, extractTo, next)
+ readPackageJson(path.join(extractTo, 'package.json'), false, function (err, metadata) {
+ if (!err) {
+ // Copy _ keys (internal to npm) and any missing keys from the possibly incomplete
+ // registry metadata over to the full package metadata read off of disk.
+ Object.keys(pkg.package).forEach(function (key) {
+ if (key[0] === '_' || !(key in metadata)) metadata[key] = pkg.package[key]
+ })
+ metadata.name = pkg.package.name // things go wrong if these don't match
+ pkg.package = metadata
+ }
+ updatePackageJson(pkg, extractTo, next)
+ })
})
}
function andStageBundledChildren (pkg, staging, extractTo, log, next) {
return iferr(next, function () {
- for (var i = 0; i < pkg.children.length; ++i) {
- var c = pkg.children[i]
- if (!c.package.name) return next(c.error)
- }
+ if (!pkg.package.bundleDependencies) return next()
- asyncMap(pkg.children, andStageBundledModule(pkg, staging, extractTo), cleanupBundled)
+ asyncMap(pkg.children, andStageBundledModule(pkg, staging, extractTo), next)
})
- function cleanupBundled () {
+}
+
+function andRemoveExtraneousBundles (extractTo, next) {
+ return iferr(next, function () {
gentlyRm(path.join(extractTo, 'node_modules'), next)
- }
+ })
}
function andStageBundledModule (bundler, staging, parentPath) {
return function (child, next) {
+ if (child.error) return next(child.error)
stageBundledModule(bundler, child, staging, parentPath, next)
}
}
@@ -64,25 +80,36 @@ function stageBundledModule (bundler, child, staging, parentPath, next) {
var stageFrom = path.join(parentPath, 'node_modules', child.package.name)
var stageTo = moduleStagingPath(staging, child)
- asyncMap(child.children, andStageBundledModule(bundler, staging, stageFrom), iferr(next, moveModule))
+ return asyncMap(child.children, andStageBundledModule(bundler, staging, stageFrom), iferr(next, finishModule))
- function moveModule () {
- if (child.fromBundle) {
- return rename(stageFrom, stageTo, iferr(next, updateMovedPackageJson))
+ function finishModule () {
+ // If we were the one's who bundled this moduleā€¦
+ if (child.fromBundle === bundler) {
+ return moveModule()
} else {
- return fs.stat(stageFrom, function (notExists, exists) {
- if (exists) {
- warn(bundler, 'EBUNDLEOVERRIDE', 'In ' + packageId(bundler) +
- ' replacing bundled version of ' + moduleName(child) +
- ' with ' + packageId(child))
- return gentlyRm(stageFrom, next)
- } else {
- return next()
- }
- })
+ return checkForReplacement()
}
}
+ function moveModule () {
+ return mkdirp(path.dirname(stageTo), iferr(next, function () {
+ return move(stageFrom, stageTo, iferr(next, updateMovedPackageJson))
+ }))
+ }
+
+ function checkForReplacement () {
+ return fs.stat(stageFrom, function (notExists, exists) {
+ if (exists) {
+ warn(bundler, 'EBUNDLEOVERRIDE', 'In ' + packageId(bundler) +
+ ' replacing bundled version of ' + moduleName(child) +
+ ' with ' + packageId(child))
+ return gentlyRm(stageFrom, next)
+ } else {
+ return next()
+ }
+ })
+ }
+
function updateMovedPackageJson () {
updatePackageJson(child, stageTo, next)
}
diff --git a/deps/npm/lib/install/action/finalize.js b/deps/npm/lib/install/action/finalize.js
index acc11cc4a7..03a71f4cc0 100644
--- a/deps/npm/lib/install/action/finalize.js
+++ b/deps/npm/lib/install/action/finalize.js
@@ -4,7 +4,7 @@ var rimraf = require('rimraf')
var fs = require('graceful-fs')
var mkdirp = require('mkdirp')
var asyncMap = require('slide').asyncMap
-var rename = require('../../utils/rename.js')
+var move = require('../../utils/move.js')
var gentlyRm = require('../../utils/gently-rm')
var moduleStagingPath = require('../module-staging-path.js')
@@ -26,31 +26,31 @@ module.exports = function (staging, pkg, log, next) {
function destStatted (doesNotExist) {
if (doesNotExist) {
- rename(extractedTo, pkg.path, whenMoved)
+ move(extractedTo, pkg.path, whenMoved)
} else {
moveAway()
}
}
- function whenMoved (renameEr) {
- if (!renameEr) return next()
- if (renameEr.code !== 'ENOTEMPTY') return next(renameEr)
+ function whenMoved (moveEr) {
+ if (!moveEr) return next()
+ if (moveEr.code !== 'ENOTEMPTY' && moveEr.code !== 'EEXIST') return next(moveEr)
moveAway()
}
function moveAway () {
- rename(pkg.path, delpath, whenOldMovedAway)
+ move(pkg.path, delpath, whenOldMovedAway)
}
- function whenOldMovedAway (renameEr) {
- if (renameEr) return next(renameEr)
- rename(extractedTo, pkg.path, whenConflictMoved)
+ function whenOldMovedAway (moveEr) {
+ if (moveEr) return next(moveEr)
+ move(extractedTo, pkg.path, whenConflictMoved)
}
- function whenConflictMoved (renameEr) {
+ function whenConflictMoved (moveEr) {
// if we got an error we'll try to put back the original module back,
// succeed or fail though we want the original error that caused this
- if (renameEr) return rename(delpath, pkg.path, function () { next(renameEr) })
+ if (moveEr) return move(delpath, pkg.path, function () { next(moveEr) })
fs.readdir(path.join(delpath, 'node_modules'), makeTarget)
}
@@ -65,7 +65,7 @@ module.exports = function (staging, pkg, log, next) {
asyncMap(files, function (file, done) {
var from = path.join(delpath, 'node_modules', file)
var to = path.join(pkg.path, 'node_modules', file)
- rename(from, to, done)
+ move(from, to, done)
}, cleanup)
}
diff --git a/deps/npm/lib/install/action/move.js b/deps/npm/lib/install/action/move.js
index 3f29379f2b..07649c3556 100644
--- a/deps/npm/lib/install/action/move.js
+++ b/deps/npm/lib/install/action/move.js
@@ -8,7 +8,7 @@ var mkdirp = require('mkdirp')
var rmStuff = require('../../unbuild.js').rmStuff
var lifecycle = require('../../utils/lifecycle.js')
var updatePackageJson = require('../update-package-json.js')
-var rename = require('../../utils/rename.js')
+var move = require('../../utils/move.js')
/*
Move a module from one point in the node_modules tree to another.
@@ -46,7 +46,7 @@ function moveModuleOnly (from, to, log, done) {
log.silly('move', 'move existing destination node_modules away', toModules)
- rename(toModules, tempToModules, removeDestination(done))
+ move(toModules, tempToModules, removeDestination(done))
function removeDestination (next) {
return function (er) {
@@ -62,7 +62,7 @@ function moveModuleOnly (from, to, log, done) {
function moveToModulesBack (next) {
return function () {
log.silly('move', 'move existing destination node_modules back', toModules)
- rename(tempToModules, toModules, iferr(done, next))
+ move(tempToModules, toModules, iferr(done, next))
}
}
@@ -76,14 +76,14 @@ function moveModuleOnly (from, to, log, done) {
function moveNodeModules (next) {
return function () {
log.silly('move', 'move source node_modules away', fromModules)
- rename(fromModules, tempFromModules, iferr(doMove(next), doMove(moveNodeModulesBack(next))))
+ move(fromModules, tempFromModules, iferr(doMove(next), doMove(moveNodeModulesBack(next))))
}
}
function doMove (next) {
return function () {
log.silly('move', 'move module dir to final dest', from, to)
- rename(from, to, iferr(done, next))
+ move(from, to, iferr(done, next))
}
}
@@ -91,7 +91,7 @@ function moveModuleOnly (from, to, log, done) {
return function () {
mkdirp(from, iferr(done, function () {
log.silly('move', 'put source node_modules back', fromModules)
- rename(tempFromModules, fromModules, iferr(done, next))
+ move(tempFromModules, fromModules, iferr(done, next))
}))
}
}
diff --git a/deps/npm/lib/install/action/remove.js b/deps/npm/lib/install/action/remove.js
index 47d5b766f7..9fe77c35e0 100644
--- a/deps/npm/lib/install/action/remove.js
+++ b/deps/npm/lib/install/action/remove.js
@@ -6,7 +6,7 @@ var asyncMap = require('slide').asyncMap
var mkdirp = require('mkdirp')
var npm = require('../../npm.js')
var andIgnoreErrors = require('../and-ignore-errors.js')
-var rename = require('../../utils/rename.js')
+var move = require('../../utils/move.js')
// This is weird because we want to remove the module but not it's node_modules folder
// allowing for this allows us to not worry about the order of operations
@@ -26,11 +26,11 @@ function removeLink (pkg, next) {
function removeDir (pkg, log, next) {
var modpath = path.join(path.dirname(pkg.path), '.' + path.basename(pkg.path) + '.MODULES')
- rename(path.join(pkg.path, 'node_modules'), modpath, unbuildPackage)
+ move(path.join(pkg.path, 'node_modules'), modpath, unbuildPackage)
- function unbuildPackage (renameEr) {
+ function unbuildPackage (moveEr) {
npm.commands.unbuild(pkg.path, true, function () {
- rimraf(pkg.path, renameEr ? andRemoveEmptyParents(pkg.path) : moveModulesBack)
+ rimraf(pkg.path, moveEr ? andRemoveEmptyParents(pkg.path) : moveModulesBack)
})
}
@@ -58,7 +58,7 @@ function removeDir (pkg, log, next) {
var to = path.join(pkg.path, 'node_modules', file)
// we ignore errors here, because they can legitimately happen, for instance,
// bundled modules will be in both node_modules folders
- rename(from, to, andIgnoreErrors(done))
+ move(from, to, andIgnoreErrors(done))
}, cleanup)
}
diff --git a/deps/npm/lib/install/action/test.js b/deps/npm/lib/install/action/test.js
deleted file mode 100644
index 29f26f3ecf..0000000000
--- a/deps/npm/lib/install/action/test.js
+++ /dev/null
@@ -1,8 +0,0 @@
-'use strict'
-var lifecycle = require('../../utils/lifecycle.js')
-var packageId = require('../../utils/package-id.js')
-
-module.exports = function (staging, pkg, log, next) {
- log.silly('test', packageId(pkg))
- lifecycle(pkg.package, 'test', pkg.path, false, false, next)
-}
diff --git a/deps/npm/lib/install/actions.js b/deps/npm/lib/install/actions.js
index 6e9c1a0b65..cb41217c02 100644
--- a/deps/npm/lib/install/actions.js
+++ b/deps/npm/lib/install/actions.js
@@ -2,7 +2,9 @@
var validate = require('aproba')
var chain = require('slide').chain
var asyncMap = require('slide').asyncMap
+var limit = require('call-limit')
var iferr = require('iferr')
+var npm = require('../npm.js')
var andFinishTracker = require('./and-finish-tracker.js')
var andAddParentToErrors = require('./and-add-parent-to-errors.js')
var failedDependency = require('./deps.js').failedDependency
@@ -15,7 +17,6 @@ var actions = {}
actions.fetch = require('./action/fetch.js')
actions.extract = require('./action/extract.js')
actions.build = require('./action/build.js')
-actions.test = require('./action/test.js')
actions.preinstall = require('./action/preinstall.js')
actions.install = require('./action/install.js')
actions.postinstall = require('./action/postinstall.js')
@@ -32,7 +33,7 @@ actions['global-link'] = require('./action/global-link.js')
Object.keys(actions).forEach(function (actionName) {
var action = actions[actionName]
- actions[actionName] = function (staging, pkg, log, next) {
+ actions[actionName] = limit(function (staging, pkg, log, next) {
// top, buildpath, pkg, log
validate('SOOF', arguments)
// refuse to run actions for failed packages
@@ -62,7 +63,7 @@ Object.keys(actions).forEach(function (actionName) {
function andDone (cb) {
return andFinishTracker(log, andAddParentToErrors(pkg.parent, andHandleOptionalDepErrors(pkg, cb)))
}
- }
+ }, npm.limit.action)
})
function markAsFailed (pkg) {
diff --git a/deps/npm/lib/install/deps.js b/deps/npm/lib/install/deps.js
index a31976a50d..d1feb6cd4b 100644
--- a/deps/npm/lib/install/deps.js
+++ b/deps/npm/lib/install/deps.js
@@ -462,7 +462,7 @@ function addDependency (name, versionSpec, tree, log, done) {
}
}))
} else {
- fetchPackageMetadata(req, packageRelativePath(tree), log.newItem('fetchMetadata'), iferr(next, function (pkg) {
+ fetchPackageMetadata(req, packageRelativePath(tree), {tracker: log.newItem('fetchMetadata')}, iferr(next, function (pkg) {
resolveWithNewModule(pkg, tree, log, next)
}))
}
@@ -547,7 +547,7 @@ function resolveWithNewModule (pkg, tree, log, next) {
if (tree.parent && parent !== tree) updatePhantomChildren(tree.parent, child)
if (hasBundled) {
- inflateBundled(child, child.children)
+ inflateBundled(child, child, child.children)
}
if (pkg._shrinkwrap && pkg._shrinkwrap.dependencies) {
diff --git a/deps/npm/lib/install/inflate-bundled.js b/deps/npm/lib/install/inflate-bundled.js
index f91e9112b9..5694841290 100644
--- a/deps/npm/lib/install/inflate-bundled.js
+++ b/deps/npm/lib/install/inflate-bundled.js
@@ -3,15 +3,15 @@ var validate = require('aproba')
var childPath = require('../utils/child-path.js')
var reset = require('./node.js').reset
-module.exports = function inflateBundled (parent, children) {
- validate('OA', arguments)
+module.exports = function inflateBundled (bundler, parent, children) {
+ validate('OOA', arguments)
children.forEach(function (child) {
reset(child)
- child.fromBundle = true
+ child.fromBundle = bundler
child.parent = parent
child.path = childPath(parent.path, child)
child.realpath = childPath(parent.path, child)
child.isLink = child.isLink || parent.isLink || parent.target
- inflateBundled(child, child.children)
+ inflateBundled(bundler, child, child.children)
})
}
diff --git a/deps/npm/lib/install/inflate-shrinkwrap.js b/deps/npm/lib/install/inflate-shrinkwrap.js
index 497bbe3348..aca4204930 100644
--- a/deps/npm/lib/install/inflate-shrinkwrap.js
+++ b/deps/npm/lib/install/inflate-shrinkwrap.js
@@ -89,7 +89,7 @@ function inflateShrinkwrap (topPath, tree, swdeps, finishInflating) {
tree.children.push(child)
if (pkg._bundled) {
delete pkg._bundled
- inflateBundled(child, child.children)
+ inflateBundled(child, child, child.children)
}
inflateShrinkwrap(topPath, child, dependencies || {}, next)
}
diff --git a/deps/npm/lib/install/validate-tree.js b/deps/npm/lib/install/validate-tree.js
index e89cd6fdd2..ccd4e2e310 100644
--- a/deps/npm/lib/install/validate-tree.js
+++ b/deps/npm/lib/install/validate-tree.js
@@ -26,7 +26,8 @@ module.exports = function (idealTree, log, next) {
], done)
}],
[thenValidateAllPeerDeps, idealTree],
- [thenCheckTop, idealTree]
+ [thenCheckTop, idealTree],
+ [thenCheckDuplicateDeps, idealTree]
], andFinishTracker(log, next))
}
@@ -73,5 +74,22 @@ function thenCheckTop (idealTree, next) {
warnObj.code = 'ENODEPRE'
idealTree.warnings.push(warnObj)
}
+
+ next()
+}
+
+// check for deps duplciated between devdeps and regular deps
+function thenCheckDuplicateDeps (idealTree, next) {
+ var deps = idealTree.package.dependencies || {}
+ var devDeps = idealTree.package.devDependencies || {}
+
+ for (var pkg in devDeps) {
+ if (pkg in deps) {
+ var warnObj = new Error('The package ' + pkg + ' is included as both a dev and production dependency.')
+ warnObj.code = 'EDUPLICATEDEP'
+ idealTree.warnings.push(warnObj)
+ }
+ }
+
next()
}
diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js
index ba5ab16e51..3c0e4384dd 100644
--- a/deps/npm/lib/ls.js
+++ b/deps/npm/lib/ls.js
@@ -15,6 +15,8 @@ var semver = require('semver')
var color = require('ansicolors')
var npa = require('npm-package-arg')
var iferr = require('iferr')
+var sortedObject = require('sorted-object')
+var extend = Object.assign || require('util')._extend
var npm = require('./npm.js')
var mutateIntoLogicalTree = require('./install/mutate-into-logical-tree.js')
var recalculateMetadata = require('./install/deps.js').recalculateMetadata
@@ -76,8 +78,8 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
pruneNestedExtraneous(data)
filterByEnv(data)
- var bfs = filterFound(bfsify(data), args)
- var lite = getLite(bfs)
+ var unlooped = filterFound(unloop(data), args)
+ var lite = getLite(unlooped)
if (silent) return cb(null, data, lite)
@@ -86,7 +88,7 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
var out
if (json) {
var seen = []
- var d = long ? bfs : lite
+ var d = long ? unlooped : lite
// the raw data can be circular
out = JSON.stringify(d, function (k, o) {
if (typeof o === 'object') {
@@ -96,9 +98,9 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
return o
}, 2)
} else if (npm.config.get('parseable')) {
- out = makeParseable(bfs, long, dir)
+ out = makeParseable(unlooped, long, dir)
} else if (data) {
- out = makeArchy(bfs, long, dir)
+ out = makeArchy(unlooped, long, dir)
}
output(out)
@@ -247,18 +249,10 @@ function getLite (data, noname, depth) {
return lite
}
-function bfsify (root) {
- // walk over the data, and turn it from this:
- // +-- a
- // | `-- b
- // | `-- a (truncated)
- // `--b (truncated)
- // into this:
- // +-- a
- // `-- b
- // which looks nicer
+function unloop (root) {
var queue = [root]
- var seen = [root]
+ var seen = {}
+ seen[root.path] = true
while (queue.length) {
var current = queue.shift()
@@ -266,17 +260,14 @@ function bfsify (root) {
Object.keys(deps).forEach(function (d) {
var dep = deps[d]
if (dep.missing) return
- if (inList(seen, dep)) {
- if (npm.config.get('parseable') || !npm.config.get('long')) {
- delete deps[d]
- return
- } else {
- dep = deps[d] = Object.create(dep)
- dep.dependencies = {}
- }
+ if (dep.path && seen[dep.path]) {
+ dep = deps[d] = extend({}, dep)
+ dep.dependencies = {}
+ dep._deduped = path.relative(root.path, dep.path).replace(/node_modules\//g, '')
+ return
}
+ seen[dep.path] = true
queue.push(dep)
- seen.push(dep)
})
}
@@ -285,18 +276,23 @@ function bfsify (root) {
function filterFound (root, args) {
if (!args.length) return root
- var deps = root.dependencies
- if (deps) {
- Object.keys(deps).forEach(function (depName) {
- var dep = filterFound(deps[depName], args)
+ if (!root.dependencies) return root
+
+ // Mark all deps
+ var toMark = [root]
+ while (toMark.length) {
+ var markPkg = toMark.shift()
+ var markDeps = markPkg.dependencies
+ if (!markDeps) continue
+ Object.keys(markDeps).forEach(function (depName) {
+ var dep = markDeps[depName]
if (dep.peerMissing) return
-
- // see if this one itself matches
- var found = false
- for (var ii = 0; !found && ii < args.length; ii++) {
+ dep._parent = markPkg
+ for (var ii = 0; ii < args.length; ii++) {
var argName = args[ii][0]
var argVersion = args[ii][1]
var argRaw = args[ii][2]
+ var found
if (depName === argName && argVersion) {
found = semver.satisfies(dep.version, argVersion, true)
} else if (depName === argName) {
@@ -305,16 +301,33 @@ function filterFound (root, args) {
} else if (dep.path === argRaw) {
found = true
}
+ if (found) {
+ dep._found = 'explicit'
+ var parent = dep._parent
+ while (parent && !parent._found && !parent._deduped) {
+ parent._found = 'implicit'
+ parent = parent._parent
+ }
+ break
+ }
}
- // included explicitly
- if (found) dep._found = true
- // included because a child was included
- if (dep._found && !root._found) root._found = 1
- // not included
- if (!dep._found) delete deps[depName]
+ toMark.push(dep)
+ })
+ }
+ var toTrim = [root]
+ while (toTrim.length) {
+ var trimPkg = toTrim.shift()
+ var trimDeps = trimPkg.dependencies
+ if (!trimDeps) continue
+ trimPkg.dependencies = {}
+ Object.keys(trimDeps).forEach(function (name) {
+ var dep = trimDeps[name]
+ if (!dep._found) return
+ if (dep._found === 'implicit' && dep._deduped) return
+ trimPkg.dependencies[name] = dep
+ toTrim.push(dep)
})
}
- if (!root._found) root._found = false
return root
}
@@ -345,7 +358,7 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
var out = {}
// the top level is a bit special.
out.label = data._id || ''
- if (data._found === true && data._id) {
+ if (data._found === 'explicit' && data._id) {
if (npm.color) {
out.label = color.bgBlack(color.yellow(out.label.trim())) + ' '
} else {
@@ -354,6 +367,14 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
}
if (data.link) out.label += ' -> ' + data.link
+ if (data._deduped) {
+ if (npm.color) {
+ out.label += ' ' + color.brightBlack('deduped')
+ } else {
+ out.label += ' deduped'
+ }
+ }
+
if (data.invalid) {
if (data.realName !== data.name) out.label += ' (' + data.realName + ')'
var invalid = 'invalid'
@@ -369,6 +390,7 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
if (data.peerMissing) {
var peerMissing = 'UNMET PEER DEPENDENCY'
+
if (npm.color) peerMissing = color.bgBlack(color.red(peerMissing))
out.label = peerMissing + ' ' + out.label
}
@@ -415,7 +437,7 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
.sort(alphasort).filter(function (d) {
return !isCruft(data.dependencies[d])
}).map(function (d) {
- return makeArchy_(data.dependencies[d], long, dir, depth + 1, data, d)
+ return makeArchy_(sortedObject(data.dependencies[d]), long, dir, depth + 1, data, d)
})
}
@@ -444,19 +466,20 @@ function getExtras (data) {
}
function makeParseable (data, long, dir, depth, parent, d) {
+ if (data._deduped) return []
depth = depth || 0
if (depth > npm.config.get('depth')) return [ makeParseable_(data, long, dir, depth, parent, d) ]
return [ makeParseable_(data, long, dir, depth, parent, d) ]
- .concat(Object.keys(data.dependencies || {})
- .sort(alphasort).map(function (d) {
- return makeParseable(data.dependencies[d], long, dir, depth + 1, data, d)
- }))
- .filter(function (x) { return x })
- .join('\n')
+ .concat(Object.keys(data.dependencies || {})
+ .sort(alphasort).map(function (d) {
+ return makeParseable(data.dependencies[d], long, dir, depth + 1, data, d)
+ }))
+ .filter(function (x) { return x })
+ .join('\n')
}
function makeParseable_ (data, long, dir, depth, parent, d) {
- if (data.hasOwnProperty('_found') && data._found !== true) return ''
+ if (data.hasOwnProperty('_found') && data._found !== 'explicit') return ''
if (data.missing) {
if (depth < npm.config.get('depth')) {
diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js
index 890c369cc6..f852886433 100644
--- a/deps/npm/lib/npm.js
+++ b/deps/npm/lib/npm.js
@@ -31,7 +31,7 @@
var which = require('which')
var glob = require('glob')
var rimraf = require('rimraf')
- var CachingRegClient = require('./cache/caching-client.js')
+ var lazyProperty = require('lazy-property')
var parseJSON = require('./utils/parse-json.js')
var aliases = require('./config/cmd-list').aliases
var cmdList = require('./config/cmd-list').cmdList
@@ -51,6 +51,13 @@
npm.commands = {}
+ // TUNING
+ npm.limit = {
+ fetch: 10,
+ action: 10
+ }
+ // ***
+
npm.rollbacks = []
try {
@@ -79,6 +86,9 @@
return littleGuys.indexOf(c) === -1
})
+ var registryRefer
+ var registryLoaded
+
Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) {
Object.defineProperty(npm.commands, c, { get: function () {
if (!loaded) {
@@ -112,9 +122,8 @@
}
})
- npm.registry.version = npm.version
- if (!npm.registry.refer) {
- npm.registry.refer = [a].concat(args[0]).map(function (arg) {
+ if (!registryRefer) {
+ registryRefer = [a].concat(args[0]).map(function (arg) {
// exclude anything that might be a URL, path, or private module
// Those things will always have a slash in them somewhere
if (arg && arg.match && arg.match(/\/|\\/)) {
@@ -125,6 +134,7 @@
}).filter(function (arg) {
return arg && arg.match
}).join(' ')
+ if (registryLoaded) npm.registry.refer = registryRefer
}
cmd.apply(npm, args)
@@ -253,6 +263,10 @@
ua = ua.replace(/\{arch\}/gi, process.arch)
config.set('user-agent', ua)
+ if (config.get('metrics-registry') == null) {
+ config.set('metrics-registry', config.get('registry'))
+ }
+
var color = config.get('color')
log.level = config.get('loglevel')
@@ -299,10 +313,6 @@
log.resume()
- // at this point the configs are all set.
- // go ahead and spin up the registry client.
- npm.registry = new CachingRegClient(npm.config)
-
var umask = npm.config.get('umask')
npm.modes = {
exec: parseInt('0777', 8) & (~umask),
@@ -322,7 +332,14 @@
// at this point the configs are all set.
// go ahead and spin up the registry client.
- npm.registry = new CachingRegClient(npm.config)
+ lazyProperty(npm, 'registry', function () {
+ registryLoaded = true
+ var CachingRegClient = require('./cache/caching-client.js')
+ var registry = new CachingRegClient(npm.config)
+ registry.version = npm.version
+ registry.refer = registryRefer
+ return registry
+ })
startMetrics()
diff --git a/deps/npm/lib/outdated.js b/deps/npm/lib/outdated.js
index a4a0d15abb..546d14b134 100644
--- a/deps/npm/lib/outdated.js
+++ b/deps/npm/lib/outdated.js
@@ -357,7 +357,7 @@ function shouldUpdate (args, tree, dep, has, req, depth, pkgpath, cb, type) {
}
}
- if (curr.version !== wanted) {
+ if (!curr || curr.version !== wanted) {
doIt(wanted, latest)
} else {
skip()
diff --git a/deps/npm/lib/repo.js b/deps/npm/lib/repo.js
index caaf422cfe..d7e79d76ab 100644
--- a/deps/npm/lib/repo.js
+++ b/deps/npm/lib/repo.js
@@ -16,7 +16,7 @@ repo.completion = function (opts, cb) {
function repo (args, cb) {
var n = args.length ? args[0] : '.'
- fetchPackageMetadata(n, '.', function (er, d) {
+ fetchPackageMetadata(n, '.', {fullMetadata: true}, function (er, d) {
if (er) return cb(er)
getUrlAndOpen(d, cb)
})
diff --git a/deps/npm/lib/search/format-package-stream.js b/deps/npm/lib/search/format-package-stream.js
index caa46cb898..a312e3f483 100644
--- a/deps/npm/lib/search/format-package-stream.js
+++ b/deps/npm/lib/search/format-package-stream.js
@@ -161,7 +161,7 @@ function normalizePackage (data, opts) {
: typeof data.keywords === 'string'
? data.keywords.replace(/[,\s]+/, ' ')
: '',
- version: Object.keys(data.versions || {})[0] || [],
+ version: data.version,
date: data.date &&
(data.date.toISOString() // remove time
.split('T').join(' ')
diff --git a/deps/npm/lib/utils/completion.sh b/deps/npm/lib/utils/completion.sh
index 25bef2c17b..c549b31c96 100755
--- a/deps/npm/lib/utils/completion.sh
+++ b/deps/npm/lib/utils/completion.sh
@@ -11,7 +11,7 @@ if type complete &>/dev/null; then
_npm_completion () {
local words cword
if type _get_comp_words_by_ref &>/dev/null; then
- _get_comp_words_by_ref -n = -n @ -w words -i cword
+ _get_comp_words_by_ref -n = -n @ -n : -w words -i cword
else
cword="$COMP_CWORD"
words=("${COMP_WORDS[@]}")
@@ -24,6 +24,9 @@ if type complete &>/dev/null; then
npm completion -- "${words[@]}" \
2>/dev/null)) || return $?
IFS="$si"
+ if type __ltrim_colon_completions &>/dev/null; then
+ __ltrim_colon_completions "${words[cword]}"
+ fi
}
complete -o default -F _npm_completion npm
elif type compdef &>/dev/null; then
diff --git a/deps/npm/lib/utils/error-handler.js b/deps/npm/lib/utils/error-handler.js
index a2911a101a..1213902886 100644
--- a/deps/npm/lib/utils/error-handler.js
+++ b/deps/npm/lib/utils/error-handler.js
@@ -4,17 +4,16 @@ module.exports = errorHandler
var cbCalled = false
var log = require('npmlog')
var npm = require('../npm.js')
-var rm = require('rimraf')
var itWorked = false
var path = require('path')
var wroteLogFile = false
var exitCode = 0
var rollbacks = npm.rollbacks
var chain = require('slide').chain
-var writeStreamAtomic = require('fs-write-stream-atomic')
+var writeFileAtomic = require('write-file-atomic')
var errorMessage = require('./error-message.js')
var stopMetrics = require('./metrics.js').stop
-var mkdir = require('mkdirp')
+var mkdirp = require('mkdirp')
var logFileName
function getLogFile () {
@@ -32,10 +31,15 @@ process.on('exit', function (code) {
stopMetrics()
if (code) itWorked = false
- if (itWorked) log.info('ok')
- else {
+ if (itWorked) {
+ log.info('ok')
+ } else {
if (!cbCalled) {
log.error('', 'cb() never called!')
+ console.error('')
+ log.error('', 'This is an error with npm itself. Please report this error at:')
+ log.error('', ' <https://github.com/npm/npm/issues>')
+ writeLogFile()
}
if (wroteLogFile) {
@@ -45,7 +49,7 @@ process.on('exit', function (code) {
log.error(
'',
[
- 'Please include the following file with any support request:',
+ 'A complete log of this run can be found in:',
' ' + getLogFile()
].join('\n')
)
@@ -83,19 +87,22 @@ function exit (code, noLog) {
}), function (er) {
if (er) {
log.error('error rolling back', er)
- if (!code) errorHandler(er)
- else if (noLog) rm('npm-debug.log', reallyExit.bind(null, er))
- else writeLogFile(reallyExit.bind(this, er))
+ if (!code) {
+ errorHandler(er)
+ } else {
+ if (!noLog) writeLogFile()
+ reallyExit(er)
+ }
} else {
- if (!noLog && code) writeLogFile(reallyExit)
- else rm(getLogFile(), reallyExit)
+ if (!noLog && code) writeLogFile()
+ reallyExit()
}
})
rollbacks.length = 0
} else if (code && !noLog) {
writeLogFile(reallyExit)
} else {
- rm('npm-debug.log', reallyExit)
+ reallyExit()
}
function reallyExit (er) {
@@ -115,7 +122,6 @@ function exit (code, noLog) {
function errorHandler (er) {
log.disableProgress()
- // console.error('errorHandler', er)
if (!npm.config || !npm.config.loaded) {
// logging won't work unless we pretend that it's ready
er = er || new Error('Exit prior to config file resolving.')
@@ -163,14 +169,10 @@ function errorHandler (er) {
log.verbose('cwd', process.cwd())
var os = require('os')
- // log.error('System', os.type() + ' ' + os.release())
- // log.error('command', process.argv.map(JSON.stringify).join(' '))
- // log.error('node -v', process.version)
- // log.error('npm -v', npm.version)
- log.error('', os.type() + ' ' + os.release())
- log.error('argv', process.argv.map(JSON.stringify).join(' '))
- log.error('node', process.version)
- log.error('npm ', 'v' + npm.version)
+ log.verbose('', os.type() + ' ' + os.release())
+ log.verbose('argv', process.argv.map(JSON.stringify).join(' '))
+ log.verbose('node', process.version)
+ log.verbose('npm ', 'v' + npm.version)
;[
'file',
@@ -183,9 +185,6 @@ function errorHandler (er) {
if (v) log.error(k, v)
})
- // just a line break
- if (log.levels[log.level] <= log.levels.error) console.error('')
-
var msg = errorMessage(er)
msg.summary.concat(msg.detail).forEach(function (errline) {
log.error.apply(log, errline)
@@ -194,20 +193,15 @@ function errorHandler (er) {
exit(typeof er.errno === 'number' ? er.errno : 1)
}
-var writingLogFile = false
-function writeLogFile (cb) {
- if (writingLogFile) return cb()
- writingLogFile = true
+function writeLogFile () {
+ if (wroteLogFile) return
wroteLogFile = true
var os = require('os')
- mkdir(path.resolve(npm.config.get('cache'), '_logs'), function (er) {
- if (er) {
- cb(er)
- return
- }
- var fstr = writeStreamAtomic(getLogFile())
+ try {
+ mkdirp.sync(path.resolve(npm.config.get('cache'), '_logs'))
+ var logOutput = ''
log.record.forEach(function (m) {
var pref = [m.id, m.level]
if (m.prefix) pref.push(m.prefix)
@@ -216,10 +210,11 @@ function writeLogFile (cb) {
m.message.trim().split(/\r?\n/).map(function (line) {
return (pref + ' ' + line).trim()
}).forEach(function (line) {
- fstr.write(line + os.EOL)
+ logOutput += line + os.EOL
})
})
- fstr.end()
- fstr.on('close', cb)
- })
+ writeFileAtomic.sync(getLogFile(), logOutput)
+ } catch (ex) {
+ return
+ }
}
diff --git a/deps/npm/lib/utils/error-message.js b/deps/npm/lib/utils/error-message.js
index 5c7ce15bf1..f19d0bf6d3 100644
--- a/deps/npm/lib/utils/error-message.js
+++ b/deps/npm/lib/utils/error-message.js
@@ -268,7 +268,6 @@ function errorMessage (er) {
detail.push([
'enoent',
[
- er.message,
'This is most likely not a problem with npm itself',
'and is related to npm not being able to find a file.',
er.file ? "\nCheck if the file '" + er.file + "' is present." : ''
@@ -304,14 +303,6 @@ function errorMessage (er) {
default:
short.push(['', er.message || er])
- detail.push([
- '',
- [
- '',
- 'If you need help, you may report this error at:',
- ' <https://github.com/npm/npm/issues>'
- ].join('\n')
- ])
break
}
if (er.optional) {
diff --git a/deps/npm/lib/utils/lifecycle.js b/deps/npm/lib/utils/lifecycle.js
index f48d5e2a3b..4ab5e0979a 100644
--- a/deps/npm/lib/utils/lifecycle.js
+++ b/deps/npm/lib/utils/lifecycle.js
@@ -282,6 +282,7 @@ function runCmd_ (cmd, pkg, env, wd, stage, unsafe, uid, gid, cb_) {
procError(er)
})
process.once('SIGTERM', procKill)
+ process.once('SIGINT', procInterupt)
function procError (er) {
if (er) {
@@ -302,11 +303,20 @@ function runCmd_ (cmd, pkg, env, wd, stage, unsafe, uid, gid, cb_) {
er.pkgname = pkg.name
}
process.removeListener('SIGTERM', procKill)
+ process.removeListener('SIGTERM', procInterupt)
+ process.removeListener('SIGINT', procKill)
return cb(er)
}
function procKill () {
proc.kill()
}
+ function procInterupt () {
+ proc.kill('SIGINT')
+ proc.on('exit', function () {
+ process.exit()
+ })
+ process.once('SIGINT', procKill)
+ }
}
function runHookLifecycle (pkg, env, wd, unsafe, cb) {
diff --git a/deps/npm/lib/utils/move.js b/deps/npm/lib/utils/move.js
new file mode 100644
index 0000000000..242e87d37f
--- /dev/null
+++ b/deps/npm/lib/utils/move.js
@@ -0,0 +1,19 @@
+'use strict'
+module.exports = wrappedMove
+
+var fs = require('graceful-fs')
+var move = require('move-concurrently')
+var Bluebird = require('bluebird')
+
+function wrappedMove (from, to, cb) {
+ var movePromise = move(from, to, {fs: fs, Promise: Bluebird, maxConcurrency: 4})
+ if (cb) {
+ return movePromise.then(function (value) {
+ cb(value)
+ }, function (err) {
+ cb(err)
+ })
+ } else {
+ return movePromise
+ }
+}
diff --git a/deps/npm/lib/utils/rename.js b/deps/npm/lib/utils/rename.js
index 8a44428984..43a2f7e104 100644
--- a/deps/npm/lib/utils/rename.js
+++ b/deps/npm/lib/utils/rename.js
@@ -1,16 +1,9 @@
-'use strict'
-var fs = require('graceful-fs')
-var SaveStack = require('./save-stack.js')
+/*
-module.exports = rename
+This is a stub file to ensure that the following hack doesn't break. This can be removed w/ npm@5.
-function rename (from, to, cb) {
- var saved = new SaveStack(rename)
- fs.rename(from, to, function (er) {
- if (er) {
- return cb(saved.completeWith(er))
- } else {
- return cb()
- }
- })
-}
+# Fix bug https://github.com/npm/npm/issues/9863
+RUN cd $(npm root -g)/npm \
+ && npm install fs-extra \
+ && sed -i -e s/graceful-fs/fs-extra/ -e s/fs\.rename/fs.move/ ./lib/utils/rename.js
+*/
diff --git a/deps/npm/lib/utils/tar.js b/deps/npm/lib/utils/tar.js
index f580c8e05d..88cfc6b805 100644
--- a/deps/npm/lib/utils/tar.js
+++ b/deps/npm/lib/utils/tar.js
@@ -136,8 +136,10 @@ BundledPacker.prototype.applyIgnores = function (entry, partial, entryObj) {
// the package root.
var p = this.parent
- // the package before this one.
+ // the directory before this one.
var pp = p && p.parent
+ // the directory before that (if this is scoped)
+ if (pp && pp.basename[0] === '@') pp = pp && pp.parent
// if this entry has already been bundled, and is a symlink,
// and it is the *same* symlink as this one, then exclude it.