| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 | 'use strict'const BB = require('bluebird')const andAddParentToErrors = require('./and-add-parent-to-errors.js')const failedDependency = require('./deps.js').failedDependencyconst 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')actions.build = require('./action/build.js')actions.preinstall = require('./action/preinstall.js')actions.install = require('./action/install.js')actions.postinstall = require('./action/postinstall.js')actions.prepare = require('./action/prepare.js')actions.finalize = require('./action/finalize.js')actions.remove = require('./action/remove.js')actions.unbuild = require('./action/unbuild.js')actions.move = require('./action/move.js')actions['global-install'] = require('./action/global-install.js')actions['global-link'] = require('./action/global-link.js')actions['refresh-package-json'] = require('./action/refresh-package-json.js')// FIXME: We wrap actions like three ways to sunday here.// Rewrite this to only work one way.Object.keys(actions).forEach(function (actionName) {  var action = actions[actionName]  actions[actionName] = (staging, pkg, log) => {    validate('SOO', [staging, pkg, log])    // refuse to run actions for failed packages    if (pkg.failed) return BB.resolve()    if (action.rollback) {      if (!pkg.rollback) pkg.rollback = []      pkg.rollback.unshift(action.rollback)    }    if (action.commit) {      if (!pkg.commit) pkg.commit = []      pkg.commit.push(action.commit)    }    let actionP    if (pkg.knownInstallable) {      actionP = runAction(action, staging, pkg, log)    } else {      actionP = isInstallable(null, pkg.package).then(() => {        pkg.knownInstallable = true        return runAction(action, staging, pkg, log)      })    }    return actionP.then(() => {      log.finish()    }, (err) => {      return BB.fromNode((cb) => {        andAddParentToErrors(pkg.parent, cb)(err)      }).catch((err) => {        return handleOptionalDepErrors(pkg, err)      })    })  }  actions[actionName].init = action.init || (() => BB.resolve())  actions[actionName].teardown = action.teardown || (() => BB.resolve())})exports.actions = actionsfunction 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) {  if (pkg.failed) return  pkg.failed = true  pkg.requires.forEach((req) => {    var requiredBy = req.requiredBy.filter((reqReqBy) => !reqReqBy.failed)    if (requiredBy.length === 0 && !req.userRequired) {      markAsFailed(req)    }  })}function handleOptionalDepErrors (pkg, err) {  markAsFailed(pkg)  var anyFatal = failedDependency(pkg)  if (anyFatal) {    throw err  } else {    reportOptionalFailure(pkg, null, err)  }}exports.doOne = doOnefunction doOne (cmd, staging, pkg, log, next) {  validate('SSOOF', arguments)  const prepped = prepareAction([cmd, pkg], staging, log)  return withInit(actions[cmd], () => {    return execAction(prepped)  }).nodeify(next)}exports.doParallel = doParallelfunction 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 + ' ' + acts.length)  time(log)  if (!acts.length) { return next() }  return withInit(actions[type], () => {    return BB.map(acts, execAction, {      concurrency: npm.limit.action    })  }).nodeify((err) => {    log.finish()    timeEnd(log)    next(err)  })}exports.doSerial = doSerialfunction doSerial (type, staging, actionsToRun, log, next) {  validate('SSAOF', arguments)  log.silly('doSerial', '%s %d', type, actionsToRun.length)  runSerial(type, staging, actionsToRun, log, next)}exports.doReverseSerial = doReverseSerialfunction doReverseSerial (type, staging, actionsToRun, log, next) {  validate('SSAOF', arguments)  log.silly('doReverseSerial', '%s %d', type, actionsToRun.length)  runSerial(type, staging, [].concat(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)  if (!acts.length) { return next() }  return withInit(actions[type], () => {    return BB.each(acts, execAction)  }).nodeify((err) => {    log.finish()    timeEnd(log)    next(err)  })}function time (log) {  process.emit('time', 'action:' + log.name)}function timeEnd (log) {  process.emit('timeEnd', 'action:' + log.name)}function withInit (action, body) {  return BB.using(    action.init().disposer(() => action.teardown()),    body  )}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))}
 |