• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2module.exports = update
3
4const url = require('url')
5const log = require('npmlog')
6const Bluebird = require('bluebird')
7const npm = require('./npm.js')
8const Installer = require('./install.js').Installer
9const usage = require('./utils/usage')
10const outdated = Bluebird.promisify(npm.commands.outdated)
11
12update.usage = usage(
13  'update',
14  'npm update [-g] [<pkg>...]'
15)
16
17update.completion = npm.commands.outdated.completion
18
19function update (args, cb) {
20  return update_(args).asCallback(cb)
21}
22
23function update_ (args) {
24  let dryrun = false
25  if (npm.config.get('dry-run')) dryrun = true
26
27  log.verbose('update', 'computing outdated modules to update')
28  return outdated(args, true).then((rawOutdated) => {
29    const outdated = rawOutdated.map(function (ww) {
30      return {
31        dep: ww[0],
32        depname: ww[1],
33        current: ww[2],
34        wanted: ww[3],
35        latest: ww[4],
36        req: ww[5],
37        what: ww[1] + '@' + ww[3]
38      }
39    })
40
41    const wanted = outdated.filter(function (ww) {
42      if (ww.current === ww.wanted && ww.wanted !== ww.latest) {
43        log.verbose(
44          'outdated',
45          'not updating', ww.depname,
46          "because it's currently at the maximum version that matches its specified semver range"
47        )
48      }
49      return ww.current !== ww.wanted
50    })
51    if (wanted.length === 0) return
52
53    log.info('outdated', 'updating', wanted)
54    const toInstall = {}
55
56    wanted.forEach(function (ww) {
57      // use the initial installation method (repo, tar, git) for updating
58      if (url.parse(ww.req).protocol) ww.what = ww.req
59
60      const where = (ww.dep.parent && ww.dep.parent.path) || ww.dep.path
61      const isTransitive = !(ww.dep.requiredBy || []).some((p) => p.isTop)
62      const key = where + ':' + String(isTransitive)
63      if (!toInstall[key]) toInstall[key] = {where: where, opts: {saveOnlyLock: isTransitive}, what: []}
64      if (toInstall[key].what.indexOf(ww.what) === -1) toInstall[key].what.push(ww.what)
65    })
66    return Bluebird.each(Object.keys(toInstall), (key) => {
67      const deps = toInstall[key]
68      const inst = new Installer(deps.where, dryrun, deps.what, deps.opts)
69      return inst.run()
70    })
71  })
72}
73