summaryrefslogtreecommitdiff
path: root/deps/npm/lib/install.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib/install.js')
-rw-r--r--deps/npm/lib/install.js103
1 files changed, 78 insertions, 25 deletions
diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js
index 029f806f83..42906f2394 100644
--- a/deps/npm/lib/install.js
+++ b/deps/npm/lib/install.js
@@ -106,6 +106,8 @@ var mkdirp = require('mkdirp')
var rimraf = require('rimraf')
var iferr = require('iferr')
var validate = require('aproba')
+var uniq = require('lodash.uniq')
+var Bluebird = require('bluebird')
// npm internal utils
var npm = require('./npm.js')
@@ -132,6 +134,7 @@ var decomposeActions = require('./install/decompose-actions.js')
var validateTree = require('./install/validate-tree.js')
var validateArgs = require('./install/validate-args.js')
var saveRequested = require('./install/save.js').saveRequested
+var saveShrinkwrap = require('./install/save.js').saveShrinkwrap
var getSaveType = require('./install/save.js').getSaveType
var doSerialActions = require('./install/actions.js').doSerial
var doReverseSerialActions = require('./install/actions.js').doReverseSerial
@@ -199,8 +202,9 @@ function install (where, args, cb) {
new Installer(where, dryrun, args).run(cb)
}
-function Installer (where, dryrun, args) {
- validate('SBA', arguments)
+function Installer (where, dryrun, args, opts) {
+ validate('SBA|SBAO', arguments)
+ if (!opts) opts = {}
this.where = where
this.dryrun = dryrun
this.args = args
@@ -215,23 +219,40 @@ function Installer (where, dryrun, args) {
this.progress = {}
this.noPackageJsonOk = !!args.length
this.topLevelLifecycles = !args.length
- this.dev = npm.config.get('dev') || (!/^prod(uction)?$/.test(npm.config.get('only')) && !npm.config.get('production')) || /^dev(elopment)?$/.test(npm.config.get('only'))
- this.prod = !/^dev(elopment)?$/.test(npm.config.get('only'))
- this.rollback = npm.config.get('rollback')
- this.link = npm.config.get('link')
- this.global = this.where === path.resolve(npm.globalDir, '..')
+
+ const dev = npm.config.get('dev')
+ const only = npm.config.get('only')
+ const onlyProd = /^prod(uction)?$/.test(only)
+ const onlyDev = /^dev(elopment)?$/.test(only)
+ const prod = npm.config.get('production')
+ this.dev = opts.dev != null ? opts.dev : dev || (!onlyProd && !prod) || onlyDev
+ this.prod = opts.prod != null ? opts.prod : !onlyDev
+
+ this.packageLockOnly = opts.packageLockOnly != null
+ ? opts.packageLockOnly : npm.config.get('package-lock-only')
+ this.rollback = opts.rollback != null ? opts.rollback : npm.config.get('rollback')
+ this.link = opts.link != null ? opts.link : npm.config.get('link')
+ this.saveOnlyLock = opts.saveOnlyLock
+ this.global = opts.global != null ? opts.global : this.where === path.resolve(npm.globalDir, '..')
this.started = Date.now()
}
Installer.prototype = {}
Installer.prototype.run = function (_cb) {
- validate('F', arguments)
-
- var cb = function (err) {
- saveMetrics(!err)
- return _cb.apply(this, arguments)
+ validate('F|', arguments)
+
+ var result
+ var cb
+ if (_cb) {
+ cb = function (err) {
+ saveMetrics(!err)
+ return _cb.apply(this, arguments)
+ }
+ } else {
+ result = new Promise((resolve, reject) => {
+ cb = (err, value) => err ? reject(err) : resolve(value)
+ })
}
-
// FIXME: This is bad and I should feel bad.
// lib/install needs to have some way of sharing _limited_
// state with the things it calls. Passing the object is too
@@ -274,7 +295,11 @@ Installer.prototype.run = function (_cb) {
[this, this.debugActions, 'diffTrees', 'differences'],
[this, this.debugActions, 'decomposeActions', 'todo'])
- if (!this.dryrun) {
+
+ if (this.packageLockOnly) {
+ postInstallSteps.push(
+ [this, this.saveToDependencies])
+ } else if (!this.dryrun) {
installSteps.push(
[this.newTracker(log, 'executeActions', 8)],
[this, this.executeActions],
@@ -296,6 +321,7 @@ Installer.prototype.run = function (_cb) {
// until after we extract them
[this, (next) => { computeMetadata(this.idealTree); next() }],
[this, this.pruneIdealTree],
+ [this, this.debugLogicalTree, 'saveTree', 'idealTree'],
[this, this.saveToDependencies])
}
}
@@ -319,6 +345,7 @@ Installer.prototype.run = function (_cb) {
cb(installEr || postInstallEr, self.getInstalledModules(), self.idealTree)
})
})
+ return result
}
Installer.prototype.loadArgMetadata = function (next) {
@@ -544,17 +571,15 @@ Installer.prototype.executeActions = function (cb) {
Installer.prototype.rollbackFailedOptional = function (staging, actionsToRun, cb) {
if (!this.rollback) return cb()
- var failed = actionsToRun.map(function (action) {
+ var failed = uniq(actionsToRun.map(function (action) {
return action[1]
}).filter(function (pkg) {
return pkg.failed && pkg.rollback
- })
+ }))
var top = this.currentTree && this.currentTree.path
- asyncMap(failed, function (pkg, next) {
- asyncMap(pkg.rollback, function (rollback, done) {
- rollback(top, staging, pkg, done)
- }, next)
- }, cb)
+ Bluebird.map(failed, (pkg) => {
+ return Bluebird.map(pkg.rollback, (rollback) => rollback(top, staging, pkg))
+ }).asCallback(cb)
}
Installer.prototype.commit = function (staging, actionsToRun, cb) {
@@ -609,7 +634,11 @@ Installer.prototype.saveToDependencies = function (cb) {
validate('F', arguments)
if (this.failing) return cb()
log.silly('install', 'saveToDependencies')
- saveRequested(this.idealTree, cb)
+ if (this.saveOnlyLock) {
+ saveShrinkwrap(this.idealTree, cb)
+ } else {
+ saveRequested(this.idealTree, cb)
+ }
}
Installer.prototype.readGlobalPackageData = function (cb) {
@@ -747,6 +776,8 @@ Installer.prototype.printInstalledForHuman = function (diffs, cb) {
var moved = 0
diffs.forEach(function (action) {
var mutation = action[0]
+ var pkg = action[1]
+ if (pkg.failed) return
if (mutation === 'remove') {
++removed
} else if (mutation === 'move') {
@@ -885,11 +916,33 @@ Installer.prototype.debugActions = function (name, actionListName, cb) {
// to define the arguments for use by chain before the property exists yet.
Installer.prototype.debugTree = function (name, treeName, cb) {
validate('SSF', arguments)
- log.silly(name, this.prettify(this[treeName]).trim())
+ log.silly(name, this.archyDebugTree(this[treeName]).trim())
+ cb()
+}
+
+Installer.prototype.archyDebugTree = function (tree) {
+ validate('O', arguments)
+ var seen = new Set()
+ function byName (aa, bb) {
+ return packageId(aa).localeCompare(packageId(bb))
+ }
+ function expandTree (tree) {
+ seen.add(tree)
+ return {
+ label: packageId(tree),
+ nodes: tree.children.filter((tree) => { return !seen.has(tree) && !tree.removed }).sort(byName).map(expandTree)
+ }
+ }
+ return archy(expandTree(tree), '', { unicode: npm.config.get('unicode') })
+}
+
+Installer.prototype.debugLogicalTree = function (name, treeName, cb) {
+ validate('SSF', arguments)
+ this[treeName] && log.silly(name, this.archyDebugLogicalTree(this[treeName]).trim())
cb()
}
-Installer.prototype.prettify = function (tree) {
+Installer.prototype.archyDebugLogicalTree = function (tree) {
validate('O', arguments)
var seen = new Set()
function byName (aa, bb) {
@@ -899,7 +952,7 @@ Installer.prototype.prettify = function (tree) {
seen.add(tree)
return {
label: packageId(tree),
- nodes: tree.children.filter((tree) => { return !seen.has(tree) && !tree.removed && !tree.failed }).sort(byName).map(expandTree)
+ nodes: tree.requires.filter((tree) => { return !seen.has(tree) && !tree.removed }).sort(byName).map(expandTree)
}
}
return archy(expandTree(tree), '', { unicode: npm.config.get('unicode') })