aboutsummaryrefslogtreecommitdiff
path: root/deps/npm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib')
-rw-r--r--deps/npm/lib/cache/add-local.js15
-rw-r--r--deps/npm/lib/cache/add-remote-git.js1
-rw-r--r--deps/npm/lib/config.js3
-rw-r--r--deps/npm/lib/config/cmd-list.js1
-rw-r--r--deps/npm/lib/edit.js5
-rw-r--r--deps/npm/lib/fetch-package-metadata.js11
-rw-r--r--deps/npm/lib/init.js6
-rw-r--r--deps/npm/lib/install.js55
-rw-r--r--deps/npm/lib/install/action/update-linked.js6
-rw-r--r--deps/npm/lib/install/actions.js26
-rw-r--r--deps/npm/lib/install/deps.js165
-rw-r--r--deps/npm/lib/install/flatten-tree.js16
-rw-r--r--deps/npm/lib/install/inflate-shrinkwrap.js117
-rw-r--r--deps/npm/lib/install/is-dev-dep.js8
-rw-r--r--deps/npm/lib/install/is-dev.js26
-rw-r--r--deps/npm/lib/install/is-opt-dep.js8
-rw-r--r--deps/npm/lib/install/is-prod-dep.js9
-rw-r--r--deps/npm/lib/install/is-registry-specifier.js6
-rw-r--r--deps/npm/lib/install/realize-shrinkwrap-specifier.js25
-rw-r--r--deps/npm/lib/install/report-optional-failure.js31
-rw-r--r--deps/npm/lib/install/save.js27
-rw-r--r--deps/npm/lib/shrinkwrap.js92
-rw-r--r--deps/npm/lib/utils/correct-mkdir.js10
-rw-r--r--deps/npm/lib/utils/error-message.js22
-rw-r--r--deps/npm/lib/utils/lifecycle.js19
-rw-r--r--deps/npm/lib/utils/tar.js15
26 files changed, 465 insertions, 260 deletions
diff --git a/deps/npm/lib/cache/add-local.js b/deps/npm/lib/cache/add-local.js
index 075ca5fc61..0794b92144 100644
--- a/deps/npm/lib/cache/add-local.js
+++ b/deps/npm/lib/cache/add-local.js
@@ -20,7 +20,7 @@ module.exports = addLocal
function addLocal (p, pkgData, cb_) {
assert(typeof p === 'object', 'must have spec info')
- assert(typeof cb === 'function', 'must have callback')
+ assert(typeof cb_ === 'function', 'must have callback')
pkgData = pkgData || {}
@@ -91,10 +91,10 @@ function addLocalDirectory (p, pkgData, shasum, cb) {
getCacheStat(function (er, cs) {
mkdir(path.dirname(pj), function (er, made) {
- if (er) return cb(er)
+ if (er) return wrapped(er)
var doPrePublish = !pathIsInside(p, npm.tmp)
if (doPrePublish) {
- lifecycle(data, 'prepublish', p, iferr(cb, thenPack))
+ lifecycle(data, 'prepublish', p, iferr(wrapped, thenPack))
} else {
thenPack()
}
@@ -102,12 +102,15 @@ function addLocalDirectory (p, pkgData, shasum, cb) {
tar.pack(tgz, p, data, function (er) {
if (er) {
log.error('addLocalDirectory', 'Could not pack', p, 'to', tgz)
- return cb(er)
+ return wrapped(er)
}
- if (!cs || isNaN(cs.uid) || isNaN(cs.gid)) wrapped()
+ if (!cs || isNaN(cs.uid) || isNaN(cs.gid)) return wrapped()
- chownr(made || tgz, cs.uid, cs.gid, wrapped)
+ chownr(made || tgz, cs.uid, cs.gid, function (er) {
+ if (er && er.code === 'ENOENT') return wrapped()
+ wrapped(er)
+ })
})
}
})
diff --git a/deps/npm/lib/cache/add-remote-git.js b/deps/npm/lib/cache/add-remote-git.js
index d8f64a85be..0da1554f80 100644
--- a/deps/npm/lib/cache/add-remote-git.js
+++ b/deps/npm/lib/cache/add-remote-git.js
@@ -26,6 +26,7 @@ var templates = path.join(remotes, '_templates')
var VALID_VARIABLES = [
'GIT_ASKPASS',
+ 'GIT_EXEC_PATH',
'GIT_PROXY_COMMAND',
'GIT_SSH',
'GIT_SSH_COMMAND',
diff --git a/deps/npm/lib/config.js b/deps/npm/lib/config.js
index 7112e88c5f..0426546274 100644
--- a/deps/npm/lib/config.js
+++ b/deps/npm/lib/config.js
@@ -12,6 +12,7 @@ var os = require('os')
var umask = require('./utils/umask')
var usage = require('./utils/usage')
var output = require('./utils/output')
+var noProgressTillDone = require('./utils/no-progress-while-running').tillDone
config.usage = usage(
'config',
@@ -106,7 +107,7 @@ function edit (cb) {
data,
function (er) {
if (er) return cb(er)
- editor(f, { editor: e }, cb)
+ editor(f, { editor: e }, noProgressTillDone(cb))
}
)
})
diff --git a/deps/npm/lib/config/cmd-list.js b/deps/npm/lib/config/cmd-list.js
index 34ebeed448..d66a5722db 100644
--- a/deps/npm/lib/config/cmd-list.js
+++ b/deps/npm/lib/config/cmd-list.js
@@ -66,6 +66,7 @@ var cmdList = [
'stars',
'tag',
'adduser',
+ 'login', // This is an alias for `adduser` but it can be confusing
'logout',
'unpublish',
'owner',
diff --git a/deps/npm/lib/edit.js b/deps/npm/lib/edit.js
index 155db6fd97..8e9bbd1797 100644
--- a/deps/npm/lib/edit.js
+++ b/deps/npm/lib/edit.js
@@ -10,6 +10,7 @@ var npm = require('./npm.js')
var path = require('path')
var fs = require('graceful-fs')
var editor = require('editor')
+var noProgressTillDone = require('./utils/no-progress-while-running').tillDone
function edit (args, cb) {
var p = args[0]
@@ -26,9 +27,9 @@ function edit (args, cb) {
var f = path.resolve(npm.dir, p)
fs.lstat(f, function (er) {
if (er) return cb(er)
- editor(f, { editor: e }, function (er) {
+ editor(f, { editor: e }, noProgressTillDone(function (er) {
if (er) return cb(er)
npm.commands.rebuild(args, cb)
- })
+ }))
})
}
diff --git a/deps/npm/lib/fetch-package-metadata.js b/deps/npm/lib/fetch-package-metadata.js
index d4f02bb278..85322304d5 100644
--- a/deps/npm/lib/fetch-package-metadata.js
+++ b/deps/npm/lib/fetch-package-metadata.js
@@ -122,7 +122,15 @@ function fetchNamedPackageData (dep, next) {
}
function pickVersionFromRegistryDocument (pkg) {
if (!regCache[url]) regCache[url] = pkg
- var versions = Object.keys(pkg.versions).sort(semver.rcompare)
+ var versions = Object.keys(pkg.versions)
+
+ var invalidVersions = versions.filter(function (v) { return !semver.valid(v) })
+ if (invalidVersions.length > 0) {
+ log.warn('pickVersion', 'The package %s has invalid semver-version(s): %s. This usually only happens for unofficial private registries. ' +
+ 'You should delete or re-publish the invalid versions.', pkg.name, invalidVersions.join(', '))
+ }
+
+ versions = versions.filter(function (v) { return semver.valid(v) }).sort(semver.rcompare)
if (dep.type === 'tag') {
var tagVersion = pkg['dist-tags'][dep.spec]
@@ -169,6 +177,7 @@ function fetchNamedPackageData (dep, next) {
: 'No valid targets found.'
var er = new Error('No compatible version found: ' +
dep.raw + '\n' + targets)
+ er.code = 'ETARGET'
return next(er)
}
}))
diff --git a/deps/npm/lib/init.js b/deps/npm/lib/init.js
index a5d102c1f3..df5615e476 100644
--- a/deps/npm/lib/init.js
+++ b/deps/npm/lib/init.js
@@ -6,13 +6,13 @@ var log = require('npmlog')
var npm = require('./npm.js')
var initJson = require('init-package-json')
var output = require('./utils/output.js')
+var noProgressTillDone = require('./utils/no-progress-while-running').tillDone
init.usage = 'npm init [--force|-f|--yes|-y]'
function init (args, cb) {
var dir = process.cwd()
log.pause()
- log.disableProgress()
var initFile = npm.config.get('init-module')
if (!initJson.yes(npm.config)) {
output([
@@ -28,7 +28,7 @@ function init (args, cb) {
'Press ^C at any time to quit.'
].join('\n'))
}
- initJson(dir, initFile, npm.config, function (er, data) {
+ initJson(dir, initFile, npm.config, noProgressTillDone(function (er, data) {
log.resume()
log.silly('package data', data)
if (er && er.message === 'canceled') {
@@ -37,5 +37,5 @@ function init (args, cb) {
}
log.info('init', 'written successfully')
cb(er, data)
- })
+ }))
}
diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js
index 1fb5a4f4e6..4c3d0def78 100644
--- a/deps/npm/lib/install.js
+++ b/deps/npm/lib/install.js
@@ -1,8 +1,8 @@
'use strict'
// npm install <pkg> <pkg> <pkg>
//
-// See doc/install.md for more description
-
+// See doc/cli/npm-install.md for more description
+//
// Managing contexts...
// there's a lot of state associated with an "install" operation, including
// packages that are already installed, parent packages, current shrinkwrap, and
@@ -259,6 +259,9 @@ Installer.prototype.run = function (cb) {
[this, this.debugActions, 'decomposeActions', 'todo'])
if (!this.dryrun) {
installSteps.push(
+ [this.newTracker(log, 'runTopLevelLifecycles', 2)],
+ [this, this.runPreinstallTopLevelLifecycles],
+
[this.newTracker(log, 'executeActions', 8)],
[this, this.executeActions],
[this, this.finishTracker, 'executeActions'])
@@ -269,10 +272,9 @@ Installer.prototype.run = function (cb) {
[this, this.rollbackFailedOptional, staging, this.todo],
[this, this.finishTracker, 'rollbackFailedOptional'],
[this, this.commit, staging, this.todo],
- [this.newTracker(log, 'runTopLevelLifecycles', 2)],
- [this, this.runTopLevelLifecycles],
- [this, this.finishTracker, 'runTopLevelLifecycles'])
+ [this, this.runPostinstallTopLevelLifecycles],
+ [this, this.finishTracker, 'runTopLevelLifecycles'])
if (getSaveType(this.args)) {
postInstallSteps.push(
[this, this.saveToDependencies])
@@ -289,9 +291,13 @@ Installer.prototype.run = function (cb) {
self.idealTree.warnings.forEach(function (warning) {
if (warning.code === 'EPACKAGEJSON' && self.global) return
if (warning.code === 'ENOTDIR') return
- errorMessage(warning).summary.forEach(function (logline) {
+ var output = errorMessage(warning)
+ output.summary.forEach(function (logline) {
log.warn.apply(log, logline)
})
+ output.detail.forEach(function (logline) {
+ log.verbose.apply(log, logline)
+ })
})
}
if (installEr && postInstallEr) {
@@ -310,7 +316,7 @@ Installer.prototype.run = function (cb) {
Installer.prototype.loadArgMetadata = function (next) {
var self = this
- getAllMetadata(this.args, this.currentTree, iferr(next, function (args) {
+ getAllMetadata(this.args, this.currentTree, process.cwd(), iferr(next, function (args) {
self.args = args
next()
}))
@@ -520,19 +526,29 @@ Installer.prototype.commit = function (staging, actionsToRun, cb) {
}, cb)
}
-Installer.prototype.runTopLevelLifecycles = function (cb) {
+Installer.prototype.runPreinstallTopLevelLifecycles = function (cb) {
validate('F', arguments)
if (this.failing) return cb()
- log.silly('install', 'runTopLevelLifecycles')
+ if (!this.topLevelLifecycles) return cb()
+ log.silly('install', 'runPreinstallTopLevelLifecycles')
+ var steps = []
+ var trackLifecycle = this.progress.runTopLevelLifecycles
+
+ steps.push(
+ [doOneAction, 'preinstall', this.idealTree.path, this.idealTree, trackLifecycle.newGroup('preinstall:.')]
+ )
+ chain(steps, cb)
+}
+
+Installer.prototype.runPostinstallTopLevelLifecycles = function (cb) {
+ validate('F', arguments)
+ if (this.failing) return cb()
+ if (!this.topLevelLifecycles) return cb()
+ log.silly('install', 'runPostinstallTopLevelLifecycles')
var steps = []
var trackLifecycle = this.progress.runTopLevelLifecycles
- if (!this.topLevelLifecycles) {
- trackLifecycle.finish()
- return cb()
- }
steps.push(
- [doOneAction, 'preinstall', this.idealTree.path, this.idealTree, trackLifecycle.newGroup('preinstall:.')],
[doOneAction, 'build', this.idealTree.path, this.idealTree, trackLifecycle.newGroup('build:.')],
[doOneAction, 'install', this.idealTree.path, this.idealTree, trackLifecycle.newGroup('install:.')],
[doOneAction, 'postinstall', this.idealTree.path, this.idealTree, trackLifecycle.newGroup('postinstall:.')])
@@ -591,18 +607,19 @@ Installer.prototype.readLocalPackageData = function (cb) {
return cb(er)
}
if (!currentTree.package) currentTree.package = {}
- self.loadArgMetadata(iferr(cb, function () {
- if (currentTree.package._shrinkwrap) return cb()
+ if (currentTree.package._shrinkwrap) {
+ self.loadArgMetadata(cb)
+ } else {
fs.readFile(path.join(self.where, 'npm-shrinkwrap.json'), function (er, data) {
- if (er) return cb()
+ if (er) return self.loadArgMetadata(cb)
try {
currentTree.package._shrinkwrap = parseJSON(data)
} catch (ex) {
return cb(ex)
}
- return cb()
+ return self.loadArgMetadata(cb)
})
- }))
+ }
}))
}))
}
diff --git a/deps/npm/lib/install/action/update-linked.js b/deps/npm/lib/install/action/update-linked.js
index 46c4cdfadd..b37f477e17 100644
--- a/deps/npm/lib/install/action/update-linked.js
+++ b/deps/npm/lib/install/action/update-linked.js
@@ -2,7 +2,9 @@
var path = require('path')
module.exports = function (top, buildpath, pkg, log, next) {
- log.warn('update-linked', path.relative(top, pkg.path), 'needs updating to', pkg.package.version,
- 'from', pkg.oldPkg.package.version, "but we can't, as it's a symlink")
+ if (pkg.package.version !== pkg.oldPkg.package.version) {
+ log.warn('update-linked', path.relative(top, pkg.path), 'needs updating to', pkg.package.version,
+ 'from', pkg.oldPkg.package.version, "but we can't, as it's a symlink")
+ }
next()
}
diff --git a/deps/npm/lib/install/actions.js b/deps/npm/lib/install/actions.js
index 1c7462030c..7c3f97cefc 100644
--- a/deps/npm/lib/install/actions.js
+++ b/deps/npm/lib/install/actions.js
@@ -3,13 +3,14 @@ var path = require('path')
var validate = require('aproba')
var chain = require('slide').chain
var asyncMap = require('slide').asyncMap
-var log = require('npmlog')
+var iferr = require('iferr')
var andFinishTracker = require('./and-finish-tracker.js')
var andAddParentToErrors = require('./and-add-parent-to-errors.js')
var failedDependency = require('./deps.js').failedDependency
-var packageId = require('../utils/package-id.js')
var moduleName = require('../utils/module-name.js')
var buildPath = require('./build-path.js')
+var reportOptionalFailure = require('./report-optional-failure.js')
+var isInstallable = require('./validate-args.js').isInstallable
var actions = {}
@@ -45,7 +46,23 @@ Object.keys(actions).forEach(function (actionName) {
if (!pkg.commit) pkg.commit = []
pkg.commit.push(action.commit)
}
- return action(top, buildpath, pkg, log, andFinishTracker(log, andAddParentToErrors(pkg.parent, andHandleOptionalDepErrors(pkg, next))))
+ if (pkg.knownInstallable) {
+ return thenRunAction()
+ } else {
+ return isInstallable(pkg.package, iferr(andDone(next), andMarkInstallable(thenRunAction)))
+ }
+ function andMarkInstallable (cb) {
+ return function () {
+ pkg.knownInstallable = true
+ cb()
+ }
+ }
+ function thenRunAction () {
+ action(top, buildpath, pkg, log, andDone(next))
+ }
+ function andDone (cb) {
+ return andFinishTracker(log, andAddParentToErrors(pkg.parent, andHandleOptionalDepErrors(pkg, cb)))
+ }
}
})
@@ -70,8 +87,7 @@ function andHandleOptionalDepErrors (pkg, next) {
if (isFatal) anyFatal = true
}
if (anyFatal) return next.apply(null, arguments)
- log.warn('install:' + packageId(pkg), er.message)
- log.verbose('install:' + packageId(pkg), er.stack)
+ reportOptionalFailure(pkg, null, er)
next()
}
}
diff --git a/deps/npm/lib/install/deps.js b/deps/npm/lib/install/deps.js
index 886e841913..762f396752 100644
--- a/deps/npm/lib/install/deps.js
+++ b/deps/npm/lib/install/deps.js
@@ -1,7 +1,6 @@
'use strict'
var assert = require('assert')
var path = require('path')
-var url = require('url')
var semver = require('semver')
var asyncMap = require('slide').asyncMap
var chain = require('slide').chain
@@ -10,6 +9,7 @@ var iferr = require('iferr')
var npa = require('npm-package-arg')
var validate = require('aproba')
var realizePackageSpecifier = require('realize-package-specifier')
+var realizeShrinkwrapSpecifier = require('./realize-shrinkwrap-specifier')
var asap = require('asap')
var dezalgo = require('dezalgo')
var fetchPackageMetadata = require('../fetch-package-metadata.js')
@@ -21,13 +21,16 @@ var inflateShrinkwrap = require('./inflate-shrinkwrap.js')
var inflateBundled = require('./inflate-bundled.js')
var andFinishTracker = require('./and-finish-tracker.js')
var npm = require('../npm.js')
-var flatName = require('./flatten-tree.js').flatName
+var flatNameFromTree = require('./flatten-tree.js').flatNameFromTree
var createChild = require('./node.js').create
var resetMetadata = require('./node.js').reset
var andIgnoreErrors = require('./and-ignore-errors.js')
var isInstallable = require('./validate-args.js').isInstallable
var packageId = require('../utils/package-id.js')
var moduleName = require('../utils/module-name.js')
+var isDevDep = require('./is-dev-dep.js')
+var isProdDep = require('./is-prod-dep.js')
+var reportOptionalFailure = require('./report-optional-failure.js')
// The export functions in this module mutate a dependency tree, adding
// items to them.
@@ -50,16 +53,6 @@ function isDep (tree, child, cb) {
})
}
-function isDevDep (tree, name, cb) {
- var devDeps = tree.package.devDependencies || {}
- return devDeps[name]
-}
-
-function isProdDep (tree, name, cb) {
- var deps = tree.package.dependencies || {}
- return deps[name]
-}
-
var registryTypes = { range: true, version: true }
function doesChildVersionMatch (child, requested, requestor) {
@@ -212,26 +205,29 @@ function getShrinkwrap (tree, name) {
return tree.package._shrinkwrap && tree.package._shrinkwrap.dependencies && tree.package._shrinkwrap.dependencies[name]
}
-exports.getAllMetadata = function (args, tree, next) {
- asyncMap(args, function (spec, done) {
- if (tree && spec.lastIndexOf('@') <= 0) {
- var sw = getShrinkwrap(tree, spec)
+exports.getAllMetadata = function (args, tree, where, next) {
+ asyncMap(args, function (arg, done) {
+ function fetchMetadataWithVersion () {
+ var version = matchingDep(tree, arg)
+ var spec = version == null ? arg : arg + '@' + version
+ return fetchPackageMetadata(spec, where, done)
+ }
+ if (tree && arg.lastIndexOf('@') <= 0) {
+ var sw = getShrinkwrap(tree, arg)
if (sw) {
- // FIXME: This is duplicated in inflate-shrinkwrap and should be factoed
- // into a shared function
- spec = sw.resolved
- ? spec + '@' + sw.resolved
- : (sw.from && url.parse(sw.from).protocol)
- ? spec + '@' + sw.from
- : spec + '@' + sw.version
+ return realizeShrinkwrapSpecifier(arg, sw, where, function (err, spec) {
+ if (err) {
+ return fetchMetadataWithVersion()
+ } else {
+ return fetchPackageMetadata(spec, where, done)
+ }
+ })
} else {
- var version = matchingDep(tree, spec)
- if (version != null) {
- spec += '@' + version
- }
+ return fetchMetadataWithVersion()
}
+ } else {
+ return fetchPackageMetadata(arg, where, done)
}
- fetchPackageMetadata(spec, packageRelativePath(tree), done)
}, next)
}
@@ -354,18 +350,6 @@ var failedDependency = exports.failedDependency = function (tree, name_pkg) {
return false
}
-function top (tree) {
- if (tree.parent) return top(tree.parent)
- return tree
-}
-
-function treeWarn (tree, what, error) {
- var topTree = top(tree)
- if (!topTree.warnings) topTree.warnings = []
- error.optional = flatNameFromTree(tree) + '/' + what
- topTree.warnings.push(error)
-}
-
function andHandleOptionalErrors (log, tree, name, done) {
validate('OOSF', arguments)
return function (er, child, childLog) {
@@ -374,7 +358,7 @@ function andHandleOptionalErrors (log, tree, name, done) {
var isFatal = failedDependency(tree, name)
if (er && !isFatal) {
tree.children = tree.children.filter(noModuleNameMatches(name))
- treeWarn(tree, name, er)
+ reportOptionalFailure(tree, name, er)
return done()
} else {
return done(er, child, childLog)
@@ -449,7 +433,9 @@ function addDependency (name, versionSpec, tree, log, done) {
}
}))
} else {
- resolveWithNewModule(req, tree, log, next)
+ fetchPackageMetadata(req, packageRelativePath(tree), log.newItem('fetchMetadata'), iferr(next, function (pkg) {
+ resolveWithNewModule(pkg, tree, log, next)
+ }))
}
}))
}
@@ -471,14 +457,6 @@ var updatePhantomChildren = exports.updatePhantomChildren = function (current, c
}
}
-function flatNameFromTree (tree) {
- validate('O', arguments)
- if (tree.isTop) return '/'
- var path = flatNameFromTree(tree.parent)
- if (path !== '/') path += '/'
- return flatName(path, tree)
-}
-
exports._replaceModuleByPath = replaceModuleByPath
function replaceModuleByPath (obj, key, child) {
return replaceModule(obj, key, child, function (replacing, child) {
@@ -511,56 +489,47 @@ function replaceModule (obj, key, child, matchBy) {
function resolveWithNewModule (pkg, tree, log, next) {
validate('OOOF', arguments)
- if (pkg.type) {
- return fetchPackageMetadata(pkg, packageRelativePath(tree), log.newItem('fetchMetadata'), iferr(next, function (pkg) {
- resolveWithNewModule(pkg, tree, log, next)
- }))
- }
-
- if (!pkg._installable) {
- log.silly('resolveWithNewModule', packageId(pkg), 'checking installable status')
- return isInstallable(pkg, iferr(next, function () {
- pkg._installable = true
- resolveWithNewModule(pkg, tree, log, next)
- }))
- }
-
- if (!pkg._from) {
- pkg._from = pkg._requested.name + '@' + pkg._requested.spec
- }
- addShrinkwrap(pkg, iferr(next, function () {
- addBundled(pkg, iferr(next, function () {
- var parent = earliestInstallable(tree, tree, pkg) || tree
- var child = createChild({
- package: pkg,
- parent: parent,
- path: path.join(parent.path, 'node_modules', pkg.name),
- realpath: path.resolve(parent.realpath, 'node_modules', pkg.name),
- children: pkg._bundled || [],
- isLink: tree.isLink
- })
- delete pkg._bundled
- var hasBundled = child.children.length
-
- var replaced = replaceModuleByName(parent, 'children', child)
- if (replaced) removeObsoleteDep(replaced)
- addRequiredDep(tree, child, function () {
- child.location = flatNameFromTree(child)
- if (tree.parent && parent !== tree) updatePhantomChildren(tree.parent, child)
-
- if (hasBundled) {
- inflateBundled(child, child.children)
- }
-
- if (pkg._shrinkwrap && pkg._shrinkwrap.dependencies) {
- return inflateShrinkwrap(child, pkg._shrinkwrap.dependencies, function (er) {
- next(er, child, log)
- })
- }
+ log.silly('resolveWithNewModule', packageId(pkg), 'checking installable status')
+ return isInstallable(pkg, iferr(next, function () {
+ if (!pkg._from) {
+ pkg._from = pkg._requested.name + '@' + pkg._requested.spec
+ }
+ addShrinkwrap(pkg, iferr(next, function () {
+ addBundled(pkg, iferr(next, function () {
+ var parent = earliestInstallable(tree, tree, pkg) || tree
+ var child = createChild({
+ package: pkg,
+ parent: parent,
+ path: path.join(parent.path, 'node_modules', pkg.name),
+ realpath: path.resolve(parent.realpath, 'node_modules', pkg.name),
+ children: pkg._bundled || [],
+ isLink: tree.isLink,
+ knownInstallable: true
+ })
+ delete pkg._bundled
+ var hasBundled = child.children.length
+
+ var replaced = replaceModuleByName(parent, 'children', child)
+ if (replaced) removeObsoleteDep(replaced)
+ addRequiredDep(tree, child, function () {
+ child.location = flatNameFromTree(child)
+
+ if (tree.parent && parent !== tree) updatePhantomChildren(tree.parent, child)
+
+ if (hasBundled) {
+ inflateBundled(child, child.children)
+ }
+
+ if (pkg._shrinkwrap && pkg._shrinkwrap.dependencies) {
+ return inflateShrinkwrap(child, pkg._shrinkwrap.dependencies, function (er) {
+ next(er, child, log)
+ })
+ }
- next(null, child, log)
- })
+ next(null, child, log)
+ })
+ }))
}))
}))
}
diff --git a/deps/npm/lib/install/flatten-tree.js b/deps/npm/lib/install/flatten-tree.js
index 869685a4e8..b6ceb30f2f 100644
--- a/deps/npm/lib/install/flatten-tree.js
+++ b/deps/npm/lib/install/flatten-tree.js
@@ -2,7 +2,11 @@
var validate = require('aproba')
var moduleName = require('../utils/module-name.js')
-module.exports = function (tree) {
+module.exports = flattenTree
+module.exports.flatName = flatName
+module.exports.flatNameFromTree = flatNameFromTree
+
+function flattenTree (tree) {
validate('O', arguments)
var seen = {}
var flat = {}
@@ -24,7 +28,15 @@ module.exports = function (tree) {
return flat
}
-var flatName = module.exports.flatName = function (path, child) {
+function flatName (path, child) {
validate('SO', arguments)
return path + (moduleName(child) || 'TOP')
}
+
+function flatNameFromTree (tree) {
+ validate('O', arguments)
+ if (tree.isTop) return '/'
+ var path = flatNameFromTree(tree.parent)
+ if (path !== '/') path += '/'
+ return flatName(path, tree)
+}
diff --git a/deps/npm/lib/install/inflate-shrinkwrap.js b/deps/npm/lib/install/inflate-shrinkwrap.js
index 1853f2c068..ab1bdd1f19 100644
--- a/deps/npm/lib/install/inflate-shrinkwrap.js
+++ b/deps/npm/lib/install/inflate-shrinkwrap.js
@@ -1,9 +1,9 @@
'use strict'
-var url = require('url')
var asyncMap = require('slide').asyncMap
var validate = require('aproba')
var iferr = require('iferr')
-var realizePackageSpecifier = require('realize-package-specifier')
+var realizeShrinkwrapSpecifier = require('./realize-shrinkwrap-specifier.js')
+var isRegistrySpecifier = require('./is-registry-specifier.js')
var fetchPackageMetadata = require('../fetch-package-metadata.js')
var annotateMetadata = require('../fetch-package-metadata.js').annotateMetadata
var addShrinkwrap = require('../fetch-package-metadata.js').addShrinkwrap
@@ -14,53 +14,80 @@ var createChild = require('./node.js').create
var moduleName = require('../utils/module-name.js')
var childPath = require('../utils/child-path.js')
-var inflateShrinkwrap = module.exports = function (tree, swdeps, finishInflating) {
- validate('OOF', arguments)
+module.exports = function (tree, swdeps, finishInflating) {
if (!npm.config.get('shrinkwrap')) return finishInflating()
+ return inflateShrinkwrap(tree.path, tree, swdeps, finishInflating)
+}
+
+function inflateShrinkwrap (topPath, tree, swdeps, finishInflating) {
+ validate('SOOF', arguments)
var onDisk = {}
tree.children.forEach(function (child) { onDisk[moduleName(child)] = child })
tree.children = []
- asyncMap(Object.keys(swdeps), function (name, next) {
- var sw = swdeps[name]
- var spec = sw.resolved
- ? name + '@' + sw.resolved
- : (sw.from && url.parse(sw.from).protocol)
- ? name + '@' + sw.from
- : name + '@' + sw.version
- var child = onDisk[name]
- if (child && (child.fromShrinkwrap ||
- (sw.resolved && child.package._resolved === sw.resolved) ||
- (sw.from && url.parse(sw.from).protocol && child.package._from === sw.from) ||
- child.package.version === sw.version)) {
- if (!child.fromShrinkwrap) child.fromShrinkwrap = spec
- tree.children.push(child)
+ var dev = npm.config.get('dev') || (!/^prod(uction)?$/.test(npm.config.get('only')) && !npm.config.get('production')) || /^dev(elopment)?$/.test(npm.config.get('only'))
+ var prod = !/^dev(elopment)?$/.test(npm.config.get('only'))
+ return asyncMap(Object.keys(swdeps), doRealizeAndInflate, finishInflating)
+
+ function doRealizeAndInflate (name, next) {
+ return realizeShrinkwrapSpecifier(name, swdeps[name], topPath, iferr(next, andInflate(name, next)))
+ }
- return realizePackageSpecifier(spec, tree.path, iferr(next, function (requested) {
- annotateMetadata(child.package, requested, spec, tree.path)
- return inflateShrinkwrap(child, sw.dependencies || {}, next)
- }))
+ function andInflate (name, next) {
+ return function (requested) {
+ var sw = swdeps[name]
+ var dependencies = sw.dependencies || {}
+ if ((!prod && !sw.dev) || (!dev && sw.dev)) return next()
+ var child = onDisk[name]
+ if (childIsEquivalent(sw, requested, child)) {
+ if (!child.fromShrinkwrap) child.fromShrinkwrap = requested.raw
+ tree.children.push(child)
+ annotateMetadata(child.package, requested, requested.raw, topPath)
+ return inflateShrinkwrap(topPath, child, dependencies || {}, next)
+ } else {
+ var from = sw.from || requested.raw
+ return fetchPackageMetadata(requested, topPath, iferr(next, andAddShrinkwrap(from, dependencies, next)))
+ }
}
- fetchPackageMetadata(spec, tree.path, iferr(next, function (pkg) {
- pkg._from = sw.from || spec
- addShrinkwrap(pkg, iferr(next, function () {
- addBundled(pkg, iferr(next, function () {
- var child = createChild({
- package: pkg,
- loaded: false,
- parent: tree,
- fromShrinkwrap: spec,
- path: childPath(tree.path, pkg),
- realpath: childPath(tree.realpath, pkg),
- children: pkg._bundled || []
- })
- tree.children.push(child)
- if (pkg._bundled) {
- delete pkg._bundled
- inflateBundled(child, child.children)
- }
- inflateShrinkwrap(child, sw.dependencies || {}, next)
- }))
- }))
- }))
- }, finishInflating)
+ }
+
+ function andAddShrinkwrap (from, dependencies, next) {
+ return function (pkg) {
+ pkg._from = from
+ addShrinkwrap(pkg, iferr(next, andAddBundled(pkg, dependencies, next)))
+ }
+ }
+
+ function andAddBundled (pkg, dependencies, next) {
+ return function () {
+ return addBundled(pkg, iferr(next, andAddChild(pkg, dependencies, next)))
+ }
+ }
+
+ function andAddChild (pkg, dependencies, next) {
+ return function () {
+ var child = createChild({
+ package: pkg,
+ loaded: false,
+ parent: tree,
+ fromShrinkwrap: pkg._from,
+ path: childPath(tree.path, pkg),
+ realpath: childPath(tree.realpath, pkg),
+ children: pkg._bundled || []
+ })
+ tree.children.push(child)
+ if (pkg._bundled) {
+ delete pkg._bundled
+ inflateBundled(child, child.children)
+ }
+ inflateShrinkwrap(topPath, child, dependencies || {}, next)
+ }
+ }
+}
+
+function childIsEquivalent (sw, requested, child) {
+ if (!child) return false
+ if (child.fromShrinkwrap) return true
+ if (sw.resolved) return child.package._resolved === sw.resolved
+ if (!isRegistrySpecifier(requested) && sw.from) return child.package._from === sw.from
+ return child.package.version === sw.version
}
diff --git a/deps/npm/lib/install/is-dev-dep.js b/deps/npm/lib/install/is-dev-dep.js
new file mode 100644
index 0000000000..c7a7982c5e
--- /dev/null
+++ b/deps/npm/lib/install/is-dev-dep.js
@@ -0,0 +1,8 @@
+'use strict'
+module.exports = isDevDep
+
+function isDevDep (node, name) {
+ return node.package &&
+ node.package.devDependencies &&
+ node.package.devDependencies[name]
+}
diff --git a/deps/npm/lib/install/is-dev.js b/deps/npm/lib/install/is-dev.js
deleted file mode 100644
index e0fae4eb82..0000000000
--- a/deps/npm/lib/install/is-dev.js
+++ /dev/null
@@ -1,26 +0,0 @@
-'use strict'
-var moduleName = require('../utils/module-name.js')
-
-function andIsDev (name) {
- return function (req) {
- return req.package &&
- req.package.devDependencies &&
- req.package.devDependencies[name]
- }
-}
-
-exports.isDev = function (node) {
- return node.requiredBy.some(andIsDev(moduleName(node)))
-}
-
-function andIsOnlyDev (name) {
- var isThisDev = andIsDev(name)
- return function (req) {
- return isThisDev(req) &&
- (!req.package.dependencies || !req.package.dependencies[name])
- }
-}
-
-exports.isOnlyDev = function (node) {
- return node.requiredBy.every(andIsOnlyDev(moduleName(node)))
-}
diff --git a/deps/npm/lib/install/is-opt-dep.js b/deps/npm/lib/install/is-opt-dep.js
new file mode 100644
index 0000000000..807b8ab998
--- /dev/null
+++ b/deps/npm/lib/install/is-opt-dep.js
@@ -0,0 +1,8 @@
+'use strict'
+module.exports = isOptDep
+
+function isOptDep (node, name) {
+ return node.package &&
+ node.package.optionalDependencies &&
+ node.package.optionalDependencies[name]
+}
diff --git a/deps/npm/lib/install/is-prod-dep.js b/deps/npm/lib/install/is-prod-dep.js
new file mode 100644
index 0000000000..1e2a0b4e49
--- /dev/null
+++ b/deps/npm/lib/install/is-prod-dep.js
@@ -0,0 +1,9 @@
+'use strict'
+
+module.exports = isProdDep
+
+function isProdDep (node, name) {
+ return node.package &&
+ node.package.dependencies &&
+ node.package.dependencies[name]
+}
diff --git a/deps/npm/lib/install/is-registry-specifier.js b/deps/npm/lib/install/is-registry-specifier.js
new file mode 100644
index 0000000000..606be2bd13
--- /dev/null
+++ b/deps/npm/lib/install/is-registry-specifier.js
@@ -0,0 +1,6 @@
+'use strict'
+module.exports = isRegistrySpecifier
+
+function isRegistrySpecifier (spec) {
+ return spec.type === 'range' || spec.type === 'version' || spec.type === 'tag'
+}
diff --git a/deps/npm/lib/install/realize-shrinkwrap-specifier.js b/deps/npm/lib/install/realize-shrinkwrap-specifier.js
new file mode 100644
index 0000000000..0c491a6028
--- /dev/null
+++ b/deps/npm/lib/install/realize-shrinkwrap-specifier.js
@@ -0,0 +1,25 @@
+'use strict'
+var realizePackageSpecifier = require('realize-package-specifier')
+var isRegistrySpecifier = require('./is-registry-specifier.js')
+
+module.exports = function (name, sw, where, cb) {
+ function lookup (ver, cb) {
+ realizePackageSpecifier(name + '@' + ver, where, cb)
+ }
+ if (sw.resolved) {
+ return lookup(sw.resolved, cb)
+ } else if (sw.from) {
+ return lookup(sw.from, function (err, spec) {
+ if (err || isRegistrySpecifier(spec)) {
+ return thenUseVersion()
+ } else {
+ return cb(null, spec)
+ }
+ })
+ } else {
+ return thenUseVersion()
+ }
+ function thenUseVersion () {
+ lookup(sw.version, cb)
+ }
+}
diff --git a/deps/npm/lib/install/report-optional-failure.js b/deps/npm/lib/install/report-optional-failure.js
new file mode 100644
index 0000000000..41c7c535bd
--- /dev/null
+++ b/deps/npm/lib/install/report-optional-failure.js
@@ -0,0 +1,31 @@
+'use strict'
+var path = require('path')
+var moduleName = require('../utils/module-name.js')
+
+module.exports = reportOptionalFailure
+
+function top (tree) {
+ if (tree.parent) return top(tree.parent)
+ return tree
+}
+
+function reportOptionalFailure (tree, what, error) {
+ var topTree = top(tree)
+ if (!topTree.warnings) topTree.warnings = []
+ var id
+ if (what) {
+ var depVer = tree.package.dependencies && tree.package.dependencies[what]
+ var optDepVer = tree.package.optionalDependencies && tree.package.optionalDependencies[what]
+ var devDepVer = tree.package.devDependencies && tree.package.devDependencies[what]
+ var version = depVer || optDepVer || devDepVer
+ id = what + (version ? '@' + version : '')
+ } else {
+ id = tree._id || moduleName(tree) + (tree.package.version ? '@' + tree.package.version : '')
+ }
+ var location = path.relative(topTree.path, tree.path)
+ if (what) location = path.join(location, 'node_modules', what)
+
+ error.optional = id
+ error.location = location
+ topTree.warnings.push(error)
+}
diff --git a/deps/npm/lib/install/save.js b/deps/npm/lib/install/save.js
index 708da61c8a..d5c97bfaa2 100644
--- a/deps/npm/lib/install/save.js
+++ b/deps/npm/lib/install/save.js
@@ -12,7 +12,8 @@ var npm = require('../npm.js')
var deepSortObject = require('../utils/deep-sort-object.js')
var parseJSON = require('../utils/parse-json.js')
var moduleName = require('../utils/module-name.js')
-var isOnlyDev = require('./is-dev.js').isOnlyDev
+var isDevDep = require('./is-dev-dep.js')
+var createShrinkwrap = require('../shrinkwrap.js').createShrinkwrap
// if the -S|--save option is specified, then write installed packages
// as dependencies to a package.json file.
@@ -49,25 +50,17 @@ function saveShrinkwrap (tree, next) {
var saveOptional = npm.config.get('save-optional')
var shrinkwrap = tree.package._shrinkwrap || {dependencies: {}}
- var hasDevOnlyDeps = tree.requires.filter(function (dep) {
- return isOnlyDev(dep)
- }).some(function (dep) {
- return shrinkwrap.dependencies[dep.package.name] != null
+ var shrinkwrapHasAnyDevOnlyDeps = tree.requires.some(function (dep) {
+ var name = moduleName(dep)
+ return isDevDep(tree, name) &&
+ shrinkwrap.dependencies[name] != null
})
- if (!saveOptional && saveDev && !hasDevOnlyDeps) return next()
- if (saveOptional || !save) return next()
+ if (!saveOptional && saveDev && !shrinkwrapHasAnyDevOnlyDeps) return next()
+ if (saveOptional || !(save || saveDev)) return next()
- if (hasDevOnlyDeps) {
- var dev = npm.config.get('dev')
- npm.config.set('dev', true)
- npm.commands.shrinkwrap([], true, function () {
- npm.config.set('dev', dev)
- next.apply(this, arguments)
- })
- } else {
- npm.commands.shrinkwrap([], true, next)
- }
+ var silent = false
+ createShrinkwrap(tree.path, tree.package, shrinkwrapHasAnyDevOnlyDeps, silent, next)
})
}
diff --git a/deps/npm/lib/shrinkwrap.js b/deps/npm/lib/shrinkwrap.js
index c6a41842fc..02481a235e 100644
--- a/deps/npm/lib/shrinkwrap.js
+++ b/deps/npm/lib/shrinkwrap.js
@@ -15,11 +15,13 @@ var npm = require('./npm.js')
var recalculateMetadata = require('./install/deps.js').recalculateMetadata
var validatePeerDeps = require('./install/deps.js').validatePeerDeps
var isExtraneous = require('./install/is-extraneous.js')
-var isOnlyDev = require('./install/is-dev.js').isOnlyDev
var packageId = require('./utils/package-id.js')
var moduleName = require('./utils/module-name.js')
var output = require('./utils/output.js')
var lifecycle = require('./utils/lifecycle.js')
+var isDevDep = require('./install/is-dev-dep.js')
+var isProdDep = require('./install/is-prod-dep.js')
+var isOptDep = require('./install/is-opt-dep.js')
shrinkwrap.usage = 'npm shrinkwrap'
@@ -35,25 +37,31 @@ function shrinkwrap (args, silent, cb) {
var dir = path.resolve(npm.dir, '..')
var packagePath = path.join(npm.localPrefix, 'package.json')
- npm.config.set('production', true)
-
- readPackageJson(packagePath, iferr(cb, function (data) {
- lifecycle(data, 'preshrinkwrap', function () {
- readPackageTree(dir, andRecalculateMetadata(iferr(cb, function (tree) {
- var pkginfo = treeToShrinkwrap(tree, !!npm.config.get('dev') || /^dev(elopment)?$/.test(npm.config.get('also')))
-
- chain([
- [lifecycle, tree.package, 'shrinkwrap'],
- [shrinkwrap_, pkginfo, silent],
- [lifecycle, tree.package, 'postshrinkwrap']
- ], iferr(cb, function (data) {
- cb(null, data[0])
- }))
- })))
- })
+ var dev = !!npm.config.get('dev') || /^dev(elopment)?$/.test(npm.config.get('also'))
+
+ readPackageJson(packagePath, iferr(cb, function (pkg) {
+ createShrinkwrap(dir, pkg, dev, silent, cb)
}))
}
+module.exports.createShrinkwrap = createShrinkwrap
+
+function createShrinkwrap (dir, pkg, dev, silent, cb) {
+ lifecycle(pkg, 'preshrinkwrap', function () {
+ readPackageTree(dir, andRecalculateMetadata(iferr(cb, function (tree) {
+ var pkginfo = treeToShrinkwrap(tree, dev)
+
+ chain([
+ [lifecycle, tree.package, 'shrinkwrap'],
+ [shrinkwrap_, pkginfo, silent],
+ [lifecycle, tree.package, 'postshrinkwrap']
+ ], iferr(cb, function (data) {
+ cb(null, data[0])
+ }))
+ })))
+ })
+}
+
function andRecalculateMetadata (next) {
validate('F', arguments)
return function (er, tree) {
@@ -92,14 +100,17 @@ function shrinkwrapDeps (dev, problems, deps, tree, seen) {
}
})
tree.children.sort(function (aa, bb) { return moduleName(aa).localeCompare(moduleName(bb)) }).forEach(function (child) {
- if (!dev && isOnlyDev(child)) {
- log.warn('shrinkwrap', 'Excluding devDependency: %s', packageId(child), child.parent.package.dependencies)
+ var childIsOnlyDev = isOnlyDev(child)
+ if (!dev && childIsOnlyDev) {
+ log.warn('shrinkwrap', 'Excluding devDependency: %s', child.location)
return
}
var pkginfo = deps[moduleName(child)] = {}
pkginfo.version = child.package.version
pkginfo.from = child.package._from
pkginfo.resolved = child.package._resolved
+ if (dev && childIsOnlyDev) pkginfo.dev = true
+ if (isOptional(child)) pkginfo.optional = true
if (isExtraneous(child)) {
problems.push('extraneous: ' + child.package._id + ' ' + child.path)
}
@@ -143,3 +154,46 @@ function save (pkginfo, silent, cb) {
cb(null, pkginfo)
})
}
+
+// Returns true if the module `node` is only required direcctly as a dev
+// dependency of the top level or transitively _from_ top level dev
+// dependencies.
+// Dual mode modules (that are both dev AND prod) should return false.
+function isOnlyDev (node, seen) {
+ if (!seen) seen = {}
+ return node.requiredBy.length && node.requiredBy.every(andIsOnlyDev(moduleName(node), seen))
+}
+
+// There is a known limitation with this implementation: If a dependency is
+// ONLY required by cycles that are detached from the top level then it will
+// ultimately return ture.
+//
+// This is ok though: We don't allow shrinkwraps with extraneous deps and
+// these situation is caught by the extraneous checker before we get here.
+function andIsOnlyDev (name, seen) {
+ return function (req) {
+ var isDev = isDevDep(req, name)
+ var isProd = isProdDep(req, name)
+ if (req.isTop) {
+ return isDev && !isProd
+ } else {
+ if (seen[req.path]) return true
+ seen[req.path] = true
+ return isOnlyDev(req, seen)
+ }
+ }
+}
+
+function isOptional (node, seen) {
+ if (!seen) seen = {}
+ // If a node is not required by anything, then we've reached
+ // the top level package.
+ if (seen[node.path] || node.requiredBy.length === 0) {
+ return false
+ }
+ seen[node.path] = true
+
+ return node.requiredBy.every(function (req) {
+ return isOptDep(req, node.package.name) || isOptional(req, seen)
+ })
+}
diff --git a/deps/npm/lib/utils/correct-mkdir.js b/deps/npm/lib/utils/correct-mkdir.js
index c0a31bdc58..68c4a4ad79 100644
--- a/deps/npm/lib/utils/correct-mkdir.js
+++ b/deps/npm/lib/utils/correct-mkdir.js
@@ -43,8 +43,13 @@ function calculateOwner () {
if (!effectiveOwner) {
effectiveOwner = { uid: 0, gid: 0 }
- if (process.getuid) effectiveOwner.uid = +process.getuid()
- if (process.getgid) effectiveOwner.gid = +process.getgid()
+ // Pretty much only on windows
+ if (!process.getuid) {
+ return effectiveOwner
+ }
+
+ effectiveOwner.uid = +process.getuid()
+ effectiveOwner.gid = +process.getgid()
if (effectiveOwner.uid === 0) {
if (process.env.SUDO_UID) effectiveOwner.uid = +process.env.SUDO_UID
@@ -112,6 +117,7 @@ function makeDirectory (path, cb) {
function setPermissions (path, st, cb) {
chownr(path, st.uid, st.gid, function (er) {
+ if (er && er.code === 'ENOENT') return cb(null, st)
return cb(er, st)
})
}
diff --git a/deps/npm/lib/utils/error-message.js b/deps/npm/lib/utils/error-message.js
index fca92ee4cb..5c7ce15bf1 100644
--- a/deps/npm/lib/utils/error-message.js
+++ b/deps/npm/lib/utils/error-message.js
@@ -8,9 +8,6 @@ module.exports = errorMessage
function errorMessage (er) {
var short = []
var detail = []
- if (er.optional) {
- short.push(['optional', 'Skipping failed optional dependency ' + er.optional + ':'])
- }
switch (er.code) {
case 'ECONNREFUSED':
short.push(['', er])
@@ -150,17 +147,21 @@ function errorMessage (er) {
break
case 'EBADPLATFORM':
+ var validOs = er.os.join ? er.os.join(',') : er.os
+ var validArch = er.cpu.join ? er.cpu.join(',') : er.cpu
+ var expected = {os: validOs, arch: validArch}
+ var actual = {os: process.platform, arch: process.arch}
short.push([
'notsup',
[
- 'Not compatible with your operating system or architecture: ' + er.pkgid
+ util.format('Unsupported platform for %s: wanted %j (current: %j)', er.pkgid, expected, actual)
].join('\n')
])
detail.push([
'notsup',
[
- 'Valid OS: ' + (er.os.join ? er.os.join(',') : util.inspect(er.os)),
- 'Valid Arch: ' + (er.cpu.join ? er.cpu.join(',') : util.inspect(er.cpu)),
+ 'Valid OS: ' + validOs,
+ 'Valid Arch: ' + validArch,
'Actual OS: ' + process.platform,
'Actual Arch: ' + process.arch
].join('\n')
@@ -284,7 +285,7 @@ function errorMessage (er) {
'typeerror',
[
'This is an error with npm itself. Please report this error at:',
- ' <http://github.com/npm/npm/issues>'
+ ' <https://github.com/npm/npm/issues>'
].join('\n')
])
break
@@ -313,5 +314,12 @@ function errorMessage (er) {
])
break
}
+ if (er.optional) {
+ short.unshift(['optional', er.optional + ' (' + er.location + '):'])
+ short.concat(detail).forEach(function (msg) {
+ if (!msg[0]) msg[0] = 'optional'
+ if (msg[1]) msg[1] = msg[1].toString().replace(/(^|\n)/g, '$1SKIPPING OPTIONAL DEPENDENCY: ')
+ })
+ }
return {summary: short, detail: detail}
}
diff --git a/deps/npm/lib/utils/lifecycle.js b/deps/npm/lib/utils/lifecycle.js
index 6a862366f2..adf534d882 100644
--- a/deps/npm/lib/utils/lifecycle.js
+++ b/deps/npm/lib/utils/lifecycle.js
@@ -15,6 +15,7 @@ var uidNumber = require('uid-number')
var umask = require('./umask')
var usage = require('./usage')
var output = require('./output.js')
+var which = require('which')
// windows calls it's path 'Path' usually, but this is not guaranteed.
if (process.platform === 'win32') {
@@ -88,7 +89,7 @@ function _incorrectWorkingDirectory (wd, pkg) {
function lifecycle_ (pkg, stage, wd, env, unsafe, failOk, cb) {
var pathArr = []
- var p = wd.split('node_modules')
+ var p = wd.split(/[\\\/]node_modules[\\\/]/)
var acc = path.resolve(p.shift())
p.forEach(function (pp) {
@@ -101,8 +102,10 @@ function lifecycle_ (pkg, stage, wd, env, unsafe, failOk, cb) {
// the bundled one will be used for installing things.
pathArr.unshift(path.join(__dirname, '..', '..', 'bin', 'node-gyp-bin'))
- // prefer current node interpreter in child scripts
- pathArr.push(path.dirname(process.execPath))
+ if (shouldPrependCurrentNodeDirToPATH()) {
+ // prefer current node interpreter in child scripts
+ pathArr.push(path.dirname(process.execPath))
+ }
if (env[PATH]) pathArr.push(env[PATH])
env[PATH] = pathArr.join(process.platform === 'win32' ? ';' : ':')
@@ -138,6 +141,16 @@ function lifecycle_ (pkg, stage, wd, env, unsafe, failOk, cb) {
)
}
+function shouldPrependCurrentNodeDirToPATH () {
+ var isWindows = process.platform === 'win32'
+ try {
+ var foundExecPath = which.sync(path.basename(process.execPath), {pathExt: isWindows ? ';' : ':'})
+ return process.execPath.toUpperCase() !== foundExecPath.toUpperCase()
+ } catch (e) {
+ return true
+ }
+}
+
function validWd (d, cb) {
fs.stat(d, function (er, st) {
if (er || !st.isDirectory()) {
diff --git a/deps/npm/lib/utils/tar.js b/deps/npm/lib/utils/tar.js
index 1e00040dbb..f580c8e05d 100644
--- a/deps/npm/lib/utils/tar.js
+++ b/deps/npm/lib/utils/tar.js
@@ -102,7 +102,8 @@ BundledPacker.prototype.applyIgnores = function (entry, partial, entryObj) {
entry === '.npmrc' ||
entry.match(/^\..*\.swp$/) ||
entry === '.DS_Store' ||
- entry.match(/^\._/)
+ entry.match(/^\._/) ||
+ entry.match(/^.*\.orig$/)
) {
return false
}
@@ -117,7 +118,17 @@ BundledPacker.prototype.applyIgnores = function (entry, partial, entryObj) {
// if they're not already present at a higher level.
if (this.bundleMagic) {
// bubbling up. stop here and allow anything the bundled pkg allows
- if (entry.indexOf('/') !== -1) return true
+ if (entry.charAt(0) === '@') {
+ var firstSlash = entry.indexOf('/')
+ // continue to list the packages in this scope
+ if (firstSlash === -1) return true
+
+ // bubbling up. stop here and allow anything the bundled pkg allows
+ if (entry.indexOf('/', firstSlash + 1) !== -1) return true
+ // bubbling up. stop here and allow anything the bundled pkg allows
+ } else if (entry.indexOf('/') !== -1) {
+ return true
+ }
// never include the .bin. It's typically full of platform-specific
// stuff like symlinks and .cmd files anyway.