Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKat Marchán <kzm@sykosomatic.org>2017-05-12 12:33:31 +0300
committerRebecca Turner <me@re-becca.org>2017-05-26 04:55:19 +0300
commitd27c18195478462d7e5dcdbdba220e790e07af12 (patch)
treeb1346c0cd092cc96e5a3876f51037876f241d97e
parentdaa77708adeb4fed5067472732deeee05b7930cd (diff)
actions: converted actions.js to use mainly promises
-rw-r--r--lib/install/actions.js213
-rw-r--r--test/tap/install-actions.js12
2 files changed, 122 insertions, 103 deletions
diff --git a/lib/install/actions.js b/lib/install/actions.js
index 23f0c93cb..912985e2c 100644
--- a/lib/install/actions.js
+++ b/lib/install/actions.js
@@ -1,18 +1,16 @@
'use strict'
-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
-var moduleName = require('../utils/module-name.js')
-var reportOptionalFailure = require('./report-optional-failure.js')
-var isInstallable = require('./validate-args.js').isInstallable
-
-var actions = {}
+
+const BB = require('bluebird')
+
+const andAddParentToErrors = require('./and-add-parent-to-errors.js')
+const failedDependency = require('./deps.js').failedDependency
+const isInstallable = BB.promisify(require('./validate-args.js').isInstallable)
+const moduleName = require('../utils/module-name.js')
+const npm = require('../npm.js')
+const reportOptionalFailure = require('./report-optional-failure.js')
+const validate = require('aproba')
+
+const actions = {}
actions.fetch = require('./action/fetch.js')
actions.extract = require('./action/extract.js')
@@ -33,11 +31,10 @@ actions['refresh-package-json'] = require('./action/refresh-package-json.js')
Object.keys(actions).forEach(function (actionName) {
var action = actions[actionName]
- actions[actionName] = limit(function (staging, pkg, log, next) {
- // top, buildpath, pkg, log
- validate('SOOF', arguments)
+ actions[actionName] = (staging, pkg, log) => {
+ validate('SOO', [staging, pkg, log])
// refuse to run actions for failed packages
- if (pkg.failed) return next()
+ if (pkg.failed) return BB.resolve()
if (action.rollback) {
if (!pkg.rollback) pkg.rollback = []
pkg.rollback.unshift(action.rollback)
@@ -46,119 +43,137 @@ Object.keys(actions).forEach(function (actionName) {
if (!pkg.commit) pkg.commit = []
pkg.commit.push(action.commit)
}
+
+ let actionP
if (pkg.knownInstallable) {
- return thenRunAction()
+ actionP = runAction(action, staging, pkg, log)
} else {
- return isInstallable(pkg.package, iferr(andDone(next), andMarkInstallable(thenRunAction)))
- }
- function andMarkInstallable (cb) {
- return function () {
+ actionP = isInstallable(pkg.package).then(() => {
pkg.knownInstallable = true
- cb()
- }
- }
- function thenRunAction () {
- var done = andDone(next)
- var result = action(staging, pkg, log, done)
- if (result && result.then) result.then(() => done(), done)
- }
- function andDone (cb) {
- return andFinishTracker(log, andAddParentToErrors(pkg.parent, andHandleOptionalDepErrors(pkg, cb)))
+ return runAction(action, staging, pkg, log)
+ })
}
- }, npm.limit.action)
+
+ return actionP.then(() => {
+ log.finish()
+ }, (err) => {
+ return BB.fromNode((cb) => {
+ andAddParentToErrors(pkg.parent, cb)(err)
+ }).catch((err) => {
+ return handleOptionalDepErrors(pkg, err)
+ })
+ })
+ }
})
+exports.actions = actions
+
+function runAction (action, staging, pkg, log) {
+ return BB.fromNode((cb) => {
+ const result = action(staging, pkg, log, cb)
+ if (result && result.then) {
+ result.then(() => cb(), cb)
+ }
+ })
+}
function markAsFailed (pkg) {
pkg.failed = true
- pkg.requires.forEach(function (req) {
- req.requiredBy = req.requiredBy.filter(function (reqReqBy) { return reqReqBy !== pkg })
+ pkg.requires.forEach((req) => {
+ req.requiredBy = req.requiredBy.filter((reqReqBy) => {
+ return reqReqBy !== pkg
+ })
if (req.requiredBy.length === 0 && !req.userRequired) {
markAsFailed(req)
}
})
}
-function andHandleOptionalDepErrors (pkg, next) {
- return function (er) {
- if (!er) return next.apply(null, arguments)
- markAsFailed(pkg)
- var anyFatal = pkg.userRequired || pkg.isTop
- for (var ii = 0; ii < pkg.requiredBy.length; ++ii) {
- var parent = pkg.requiredBy[ii]
- var isFatal = failedDependency(parent, pkg)
- if (isFatal) anyFatal = true
- }
- if (anyFatal) return next.apply(null, arguments)
- reportOptionalFailure(pkg, null, er)
- next()
+function handleOptionalDepErrors (pkg, err) {
+ markAsFailed(pkg)
+ var anyFatal = pkg.userRequired || pkg.isTop
+ for (var ii = 0; ii < pkg.requiredBy.length; ++ii) {
+ var parent = pkg.requiredBy[ii]
+ var isFatal = failedDependency(parent, pkg)
+ if (isFatal) anyFatal = true
}
-}
-
-function prepareAction (staging, log) {
- validate('SO', arguments)
- return function (action) {
- validate('SO', action)
- var cmd = action[0]
- var pkg = action[1]
- if (!actions[cmd]) throw new Error('Unknown decomposed command "' + cmd + '" (is it new?)')
- return [actions[cmd], staging, pkg, log.newGroup(cmd + ':' + moduleName(pkg))]
+ if (anyFatal) {
+ throw err
+ } else {
+ reportOptionalFailure(pkg, null, err)
}
}
-exports.actions = actions
-
-function execAction (todo, done) {
- validate('AF', arguments)
- var cmd = todo.shift()
- todo.push(done)
- cmd.apply(null, todo)
-}
-
-exports.doOne = function (cmd, staging, pkg, log, next) {
+exports.doOne = doOne
+function doOne (cmd, staging, pkg, log, next) {
validate('SSOOF', arguments)
- execAction(prepareAction(staging, log)([cmd, pkg]), next)
+ execAction(prepareAction([cmd, pkg], staging, log)).then(() => next(), next)
}
-function time (log) {
- process.emit('time', 'action:' + log.name)
-}
-function timeEnd (log) {
- process.emit('timeEnd', 'action:' + log.name)
+exports.doParallel = doParallel
+function doParallel (type, staging, actionsToRun, log, next) {
+ validate('SSAOF', arguments)
+ const acts = actionsToRun.reduce((acc, todo) => {
+ if (todo[0] === type) {
+ acc.push(prepareAction(todo, staging, log))
+ }
+ return acc
+ }, [])
+ log.silly('doParallel', type + ' ' + actionsToRun.length)
+ time(log)
+ BB.map(acts, execAction, {
+ concurrency: npm.limit.action
+ }).nodeify((err) => {
+ log.finish()
+ timeEnd(log)
+ next(err)
+ })
}
-exports.doSerial = function (type, staging, actionsToRun, log, next) {
+exports.doSerial = doSerial
+function doSerial (type, staging, actionsToRun, log, next) {
validate('SSAOF', arguments)
- actionsToRun = actionsToRun
- .filter(function (value) { return value[0] === type })
log.silly('doSerial', '%s %d', type, actionsToRun.length)
- time(log)
- chain(actionsToRun.map(prepareAction(staging, log)), andFinishTracker(log, function () {
- timeEnd(log)
- next.apply(null, arguments)
- }))
+ runSerial(type, staging, actionsToRun, log, next)
}
-exports.doReverseSerial = function (type, staging, actionsToRun, log, next) {
+exports.doReverseSerial = doReverseSerial
+function doReverseSerial (type, staging, actionsToRun, log, next) {
validate('SSAOF', arguments)
- actionsToRun = actionsToRun
- .filter(function (value) { return value[0] === type })
- .reverse()
log.silly('doReverseSerial', '%s %d', type, actionsToRun.length)
+ runSerial(type, staging, actionsToRun.reverse(), log, next)
+}
+
+function runSerial (type, staging, actionsToRun, log, next) {
+ const acts = actionsToRun.reduce((acc, todo) => {
+ if (todo[0] === type) {
+ acc.push(prepareAction(todo, staging, log))
+ }
+ return acc
+ }, [])
time(log)
- chain(actionsToRun.map(prepareAction(staging, log)), andFinishTracker(log, function () {
+ BB.each(acts, execAction).nodeify((err) => {
+ log.finish()
timeEnd(log)
- next.apply(null, arguments)
- }))
+ next(err)
+ })
}
-exports.doParallel = function (type, staging, actionsToRun, log, next) {
- validate('SSAOF', arguments)
- actionsToRun = actionsToRun.filter(function (value) { return value[0] === type })
- log.silly('doParallel', type + ' ' + actionsToRun.length)
- time(log)
+function time (log) {
+ process.emit('time', 'action:' + log.name)
+}
+function timeEnd (log) {
+ process.emit('timeEnd', 'action:' + log.name)
+}
- asyncMap(actionsToRun.map(prepareAction(staging, log)), execAction, andFinishTracker(log, function () {
- timeEnd(log)
- next.apply(null, arguments)
- }))
+function prepareAction (action, staging, log) {
+ validate('ASO', arguments)
+ validate('SO', action)
+ var cmd = action[0]
+ var pkg = action[1]
+ if (!actions[cmd]) throw new Error('Unknown decomposed command "' + cmd + '" (is it new?)')
+ return [actions[cmd], staging, pkg, log.newGroup(cmd + ':' + moduleName(pkg))]
+}
+
+function execAction (todo) {
+ return todo[0].apply(null, todo.slice(1))
}
diff --git a/test/tap/install-actions.js b/test/tap/install-actions.js
index 824a31c1b..6ca6e3353 100644
--- a/test/tap/install-actions.js
+++ b/test/tap/install-actions.js
@@ -56,8 +56,10 @@ test('->optdep:a->dep:b', function (t) {
moduleB.parent = tree
t.plan(3)
- actions.postinstall('/', moduleA, mockLog, function (er) {
- t.is(er && er.code, 'ELIFECYCLE', 'Lifecycle failed')
+ return actions.postinstall('/', moduleA, mockLog).then(() => {
+ throw new Error('was not supposed to succeed')
+ }, (err) => {
+ t.is(err && err.code, 'ELIFECYCLE', 'Lifecycle failed')
t.ok(moduleA.failed, 'moduleA (optional dep) is marked failed')
t.ok(moduleB.failed, 'moduleB (direct dep of moduleA) is marked as failed')
t.end()
@@ -108,8 +110,10 @@ test('->dep:b,->optdep:a->dep:b', function (t) {
moduleB.parent = tree
t.plan(3)
- actions.postinstall('/', moduleA, mockLog, function (er) {
- t.ok(er && er.code === 'ELIFECYCLE', 'Lifecycle failed')
+ return actions.postinstall('/', moduleA, mockLog).then(() => {
+ throw new Error('was not supposed to succeed')
+ }, (err) => {
+ t.ok(err && err.code === 'ELIFECYCLE', 'Lifecycle failed')
t.ok(moduleA.failed, 'moduleA (optional dep) is marked failed')
t.ok(!moduleB.failed, 'moduleB (direct dep of moduleA) is marked as failed')
t.end()