diff options
Diffstat (limited to 'deps/npm/lib/install/action')
-rw-r--r-- | deps/npm/lib/install/action/extract.js | 163 | ||||
-rw-r--r-- | deps/npm/lib/install/action/fetch.js | 31 | ||||
-rw-r--r-- | deps/npm/lib/install/action/finalize.js | 131 | ||||
-rw-r--r-- | deps/npm/lib/install/action/global-install.js | 2 | ||||
-rw-r--r-- | deps/npm/lib/install/action/refresh-package-json.js | 38 | ||||
-rw-r--r-- | deps/npm/lib/install/action/update-linked.js | 16 |
6 files changed, 190 insertions, 191 deletions
diff --git a/deps/npm/lib/install/action/extract.js b/deps/npm/lib/install/action/extract.js index fd9562c184..7839177850 100644 --- a/deps/npm/lib/install/action/extract.js +++ b/deps/npm/lib/install/action/extract.js @@ -1,67 +1,56 @@ 'use strict' -var path = require('path') -var iferr = require('iferr') -var asyncMap = require('slide').asyncMap -var fs = require('graceful-fs') -var mkdirp = require('mkdirp') -var move = require('../../utils/move.js') -var gentlyRm = require('../../utils/gently-rm.js') -var updatePackageJson = require('../update-package-json') -var npm = require('../../npm.js') -var moduleName = require('../../utils/module-name.js') -var packageId = require('../../utils/package-id.js') -var cache = require('../../cache.js') -var moduleStagingPath = require('../module-staging-path.js') -var readPackageJson = require('read-package-json') -module.exports = function (staging, pkg, log, next) { - log.silly('extract', packageId(pkg)) - var up = npm.config.get('unsafe-perm') - var user = up ? null : npm.config.get('user') - var group = up ? null : npm.config.get('group') - var extractTo = moduleStagingPath(staging, pkg) - cache.unpack(pkg.package.name, pkg.package.version, extractTo, null, null, user, group, - andUpdatePackageJson(pkg, staging, extractTo, - andStageBundledChildren(pkg, staging, extractTo, log, - andRemoveExtraneousBundles(extractTo, next)))) -} - -function andUpdatePackageJson (pkg, staging, extractTo, next) { - return iferr(next, function () { - readPackageJson(path.join(extractTo, 'package.json'), false, function (err, metadata) { - if (!err) { - // Copy _ keys (internal to npm) and any missing keys from the possibly incomplete - // registry metadata over to the full package metadata read off of disk. - Object.keys(pkg.package).forEach(function (key) { - if (key[0] === '_' || !(key in metadata)) metadata[key] = pkg.package[key] - }) - metadata.name = pkg.package.name // things go wrong if these don't match - pkg.package = metadata - } - updatePackageJson(pkg, extractTo, next) - }) - }) -} +const BB = require('bluebird') -function andStageBundledChildren (pkg, staging, extractTo, log, next) { - return iferr(next, function () { - if (!pkg.package.bundleDependencies) return next() +const fs = BB.promisifyAll(require('graceful-fs')) +const gentlyRm = BB.promisify(require('../../utils/gently-rm.js')) +const log = require('npmlog') +const mkdirp = BB.promisify(require('mkdirp')) +const moduleName = require('../../utils/module-name.js') +const moduleStagingPath = require('../module-staging-path.js') +const move = BB.promisify(require('../../utils/move.js')) +const npa = require('npm-package-arg') +const npm = require('../../npm.js') +const packageId = require('../../utils/package-id.js') +const pacote = require('pacote') +const pacoteOpts = require('../../config/pacote') +const path = require('path') - asyncMap(pkg.children, andStageBundledModule(pkg, staging, extractTo), next) +module.exports = extract +function extract (staging, pkg, log) { + log.silly('extract', packageId(pkg)) + const up = npm.config.get('unsafe-perm') + const user = up ? null : npm.config.get('user') + const group = up ? null : npm.config.get('group') + const extractTo = moduleStagingPath(staging, pkg) + const opts = pacoteOpts({ + uid: user, + gid: group, + integrity: pkg.package._integrity }) -} - -function andRemoveExtraneousBundles (extractTo, next) { - return iferr(next, function () { - gentlyRm(path.join(extractTo, 'node_modules'), next) + return pacote.extract( + pkg.package._resolved + ? npa.resolve(pkg.package.name, pkg.package._resolved) + : pkg.package._requested, + extractTo, + opts + ).then(() => { + if (pkg.package.bundleDependencies) { + return readBundled(pkg, staging, extractTo) + } + }).then(() => { + return gentlyRm(path.join(extractTo, 'node_modules')) }) } -function andStageBundledModule (bundler, staging, parentPath) { - return function (child, next) { - if (child.error) return next(child.error) - stageBundledModule(bundler, child, staging, parentPath, next) - } +function readBundled (pkg, staging, extractTo) { + return BB.map(pkg.children, (child) => { + if (child.error) { + throw child.error + } else { + return stageBundledModule(pkg, child, staging, extractTo) + } + }, {concurrency: 10}) } function getTree (pkg) { @@ -70,47 +59,43 @@ function getTree (pkg) { } function warn (pkg, code, msg) { - var tree = getTree(pkg) - var err = new Error(msg) + const tree = getTree(pkg) + const err = new Error(msg) err.code = code tree.warnings.push(err) } -function stageBundledModule (bundler, child, staging, parentPath, next) { - var stageFrom = path.join(parentPath, 'node_modules', child.package.name) - var stageTo = moduleStagingPath(staging, child) - - return asyncMap(child.children, andStageBundledModule(bundler, staging, stageFrom), iferr(next, finishModule)) +function stageBundledModule (bundler, child, staging, parentPath) { + const stageFrom = path.join(parentPath, 'node_modules', child.package.name) + const stageTo = moduleStagingPath(staging, child) - function finishModule () { - // If we were the one's who bundled this module… - if (child.fromBundle === bundler) { - return moveModule() + return BB.map(child.children, (child) => { + if (child.error) { + throw child.error } else { - return checkForReplacement() + return stageBundledModule(bundler, child, staging, stageFrom) } - } - - function moveModule () { - return mkdirp(path.dirname(stageTo), iferr(next, function () { - return move(stageFrom, stageTo, iferr(next, updateMovedPackageJson)) - })) - } + }).then(() => { + return finishModule(bundler, child, stageTo, stageFrom) + }) +} - function checkForReplacement () { - return fs.stat(stageFrom, function (notExists, exists) { - if (exists) { - warn(bundler, 'EBUNDLEOVERRIDE', 'In ' + packageId(bundler) + - ' replacing bundled version of ' + moduleName(child) + - ' with ' + packageId(child)) - return gentlyRm(stageFrom, next) - } else { - return next() - } +function finishModule (bundler, child, stageTo, stageFrom) { + // If we were the one's who bundled this module… + if (child.fromBundle === bundler) { + return mkdirp(path.dirname(stageTo)).then(() => { + return move(stageFrom, stageTo) }) - } - - function updateMovedPackageJson () { - updatePackageJson(child, stageTo, next) + } else { + return fs.statAsync(stageFrom).then(() => { + const bundlerId = packageId(bundler) + if (!getTree(bundler).warnings.some((w) => { + return w.code === 'EBUNDLEOVERRIDE' + })) { + warn(bundler, 'EBUNDLEOVERRIDE', `${bundlerId} had bundled packages that do not match the required version(s). They have been replaced with non-bundled versions.`) + } + log.verbose('bundle', `EBUNDLEOVERRIDE: Replacing ${bundlerId}'s bundled version of ${moduleName(child)} with ${packageId(child)}.`) + return gentlyRm(stageFrom) + }, () => {}) } } diff --git a/deps/npm/lib/install/action/fetch.js b/deps/npm/lib/install/action/fetch.js index 0e9146a0d5..474e00b05c 100644 --- a/deps/npm/lib/install/action/fetch.js +++ b/deps/npm/lib/install/action/fetch.js @@ -1,29 +1,12 @@ 'use strict' -// var cache = require('../../cache.js') -// var packageId = require('../../utils/package-id.js') -// var moduleName = require('../../utils/module-name.js') -module.exports = function (staging, pkg, log, next) { - next() -/* -// FIXME: Unnecessary as long as we have to have the tarball to resolve all deps, which -// is progressively seeming to be likely for the indefinite future. -// ALSO fails for local deps specified with relative URLs outside of the top level. +const packageId = require('../../utils/package-id.js') +const pacote = require('pacote') +const pacoteOpts = require('../../config/pacote') - var name = moduleName(pkg) - var version - switch (pkg.package._requested.type) { - case 'version': - case 'range': - version = pkg.package.version - break - case 'hosted': - name = name + '@' + pkg.package._requested.spec - break - default: - name = pkg.package._requested.raw - } +module.exports = fetch +function fetch (staging, pkg, log, next) { log.silly('fetch', packageId(pkg)) - cache.add(name, version, pkg.parent.path, false, next) -*/ + const opts = pacoteOpts({integrity: pkg.package._integrity}) + pacote.prefetch(pkg.package._requested, opts).then(() => next(), next) } diff --git a/deps/npm/lib/install/action/finalize.js b/deps/npm/lib/install/action/finalize.js index 03a71f4cc0..1e86475710 100644 --- a/deps/npm/lib/install/action/finalize.js +++ b/deps/npm/lib/install/action/finalize.js @@ -1,85 +1,94 @@ 'use strict' -var path = require('path') -var rimraf = require('rimraf') -var fs = require('graceful-fs') -var mkdirp = require('mkdirp') -var asyncMap = require('slide').asyncMap -var move = require('../../utils/move.js') -var gentlyRm = require('../../utils/gently-rm') -var moduleStagingPath = require('../module-staging-path.js') +const path = require('path') +const fs = require('graceful-fs') +const Bluebird = require('bluebird') +const rimraf = Bluebird.promisify(require('rimraf')) +const mkdirp = Bluebird.promisify(require('mkdirp')) +const lstat = Bluebird.promisify(fs.lstat) +const readdir = Bluebird.promisify(fs.readdir) +const symlink = Bluebird.promisify(fs.symlink) +const gentlyRm = require('../../utils/gently-rm') +const moduleStagingPath = require('../module-staging-path.js') +const move = require('move-concurrently') +const moveOpts = {fs: fs, Promise: Bluebird, maxConcurrency: 4} +const getRequested = require('../get-requested.js') -module.exports = function (staging, pkg, log, next) { - log.silly('finalize', pkg.path) +module.exports = function (staging, pkg, log) { + log.silly('finalize', pkg.realpath) - var extractedTo = moduleStagingPath(staging, pkg) + const extractedTo = moduleStagingPath(staging, pkg) - var delpath = path.join(path.dirname(pkg.path), '.' + path.basename(pkg.path) + '.DELETE') + const delpath = path.join(path.dirname(pkg.realpath), '.' + path.basename(pkg.realpath) + '.DELETE') + let movedDestAway = false - mkdirp(path.resolve(pkg.path, '..'), whenParentExists) - - function whenParentExists (mkdirEr) { - if (mkdirEr) return next(mkdirEr) - // We stat first, because we can't rely on ENOTEMPTY from Windows. - // Windows, by contrast, gives the generic EPERM of a folder already exists. - fs.lstat(pkg.path, destStatted) - } - - function destStatted (doesNotExist) { - if (doesNotExist) { - move(extractedTo, pkg.path, whenMoved) - } else { - moveAway() - } - } - - function whenMoved (moveEr) { - if (!moveEr) return next() - if (moveEr.code !== 'ENOTEMPTY' && moveEr.code !== 'EEXIST') return next(moveEr) - moveAway() + const requested = pkg.package._requested || getRequested(pkg) + if (requested.type === 'directory') { + return makeParentPath(pkg.path) + .then(() => symlink(pkg.realpath, pkg.path, 'junction')) + .catch((ex) => { + return rimraf(pkg.path).then(() => symlink(pkg.realpath, pkg.path, 'junction')) + }) + } else { + return makeParentPath(pkg.realpath) + .then(moveStagingToDestination) + .then(restoreOldNodeModules) + .catch((err) => { + if (movedDestAway) { + return rimraf(pkg.realpath).then(moveOldDestinationBack).then(() => { + throw err + }) + } else { + throw err + } + }) + .then(() => rimraf(delpath)) } - function moveAway () { - move(pkg.path, delpath, whenOldMovedAway) + function makeParentPath (dir) { + return mkdirp(path.dirname(dir)) } - function whenOldMovedAway (moveEr) { - if (moveEr) return next(moveEr) - move(extractedTo, pkg.path, whenConflictMoved) + function moveStagingToDestination () { + return destinationIsClear() + .then(actuallyMoveStaging) + .catch(() => moveOldDestinationAway().then(actuallyMoveStaging)) } - function whenConflictMoved (moveEr) { - // if we got an error we'll try to put back the original module back, - // succeed or fail though we want the original error that caused this - if (moveEr) return move(delpath, pkg.path, function () { next(moveEr) }) - fs.readdir(path.join(delpath, 'node_modules'), makeTarget) + function destinationIsClear () { + return lstat(pkg.realpath).then(() => { + throw new Error('destination exists') + }, () => {}) } - function makeTarget (readdirEr, files) { - if (readdirEr) return cleanup() - if (!files.length) return cleanup() - mkdirp(path.join(pkg.path, 'node_modules'), function (mkdirEr) { moveModules(mkdirEr, files) }) + function actuallyMoveStaging () { + return move(extractedTo, pkg.realpath, moveOpts) } - function moveModules (mkdirEr, files) { - if (mkdirEr) return next(mkdirEr) - asyncMap(files, function (file, done) { - var from = path.join(delpath, 'node_modules', file) - var to = path.join(pkg.path, 'node_modules', file) - move(from, to, done) - }, cleanup) + function moveOldDestinationAway () { + return rimraf(delpath).then(() => { + return move(pkg.realpath, delpath, moveOpts) + }).then(() => { movedDestAway = true }) } - function cleanup (moveEr) { - if (moveEr) return next(moveEr) - rimraf(delpath, afterCleanup) + function moveOldDestinationBack () { + return move(delpath, pkg.realpath, moveOpts).then(() => { movedDestAway = false }) } - function afterCleanup (rimrafEr) { - if (rimrafEr) log.warn('finalize', rimrafEr) - next() + function restoreOldNodeModules () { + if (!movedDestAway) return + return readdir(path.join(delpath, 'node_modules')).catch(() => []).then((modules) => { + if (!modules.length) return + return mkdirp(path.join(pkg.realpath, 'node_modules')).then(() => Bluebird.map(modules, (file) => { + const from = path.join(delpath, 'node_modules', file) + const to = path.join(pkg.realpath, 'node_modules', file) + return move(from, to, moveOpts) + })) + }) } } module.exports.rollback = function (top, staging, pkg, next) { - gentlyRm(pkg.path, false, top, next) + const requested = pkg.package._requested || getRequested(pkg) + if (requested.type === 'directory') return next() + gentlyRm(pkg.realpath, false, top, next) } diff --git a/deps/npm/lib/install/action/global-install.js b/deps/npm/lib/install/action/global-install.js index e4fd8d11d1..bdc121b693 100644 --- a/deps/npm/lib/install/action/global-install.js +++ b/deps/npm/lib/install/action/global-install.js @@ -8,7 +8,7 @@ module.exports = function (staging, pkg, log, next) { log.silly('global-install', packageId(pkg)) var globalRoot = path.resolve(npm.globalDir, '..') npm.config.set('global', true) - var install = new Installer(globalRoot, false, [pkg.package.name + '@' + pkg.package._requested.spec]) + var install = new Installer(globalRoot, false, [pkg.package.name + '@' + pkg.package._requested.fetchSpec]) install.link = false install.run(function () { npm.config.set('global', false) diff --git a/deps/npm/lib/install/action/refresh-package-json.js b/deps/npm/lib/install/action/refresh-package-json.js new file mode 100644 index 0000000000..337be0caf2 --- /dev/null +++ b/deps/npm/lib/install/action/refresh-package-json.js @@ -0,0 +1,38 @@ +'use strict' +const path = require('path') +const Bluebird = require('bluebird') +const readJson = Bluebird.promisify(require('read-package-json')) +const updatePackageJson = Bluebird.promisify(require('../update-package-json')) +const getRequested = require('../get-requested.js') + +module.exports = function (staging, pkg, log) { + log.silly('refresh-package-json', pkg.realpath) + + return readJson(path.join(pkg.path, 'package.json'), false).then((metadata) => { + Object.keys(pkg.package).forEach(function (key) { + if (key !== '_injectedFromShrinkwrap' && !isEmpty(pkg.package[key])) { + metadata[key] = pkg.package[key] + if (key === '_resolved' && metadata[key] == null && pkg.package._injectedFromShrinkwrap) { + metadata[key] = pkg.package._injectedFromShrinkwrap.resolved + } + } + }) + // These two sneak in and it's awful + delete metadata.readme + delete metadata.readmeFilename + + pkg.package = metadata + }).catch(() => 'ignore').then(() => { + const requested = pkg.package._requested || getRequested(pkg) + if (requested.type !== 'directory') { + return updatePackageJson(pkg, pkg.path) + } + }) +} + +function isEmpty (value) { + if (value == null) return true + if (Array.isArray(value)) return !value.length + if (typeof value === 'object') return !Object.keys(value).length + return false +} diff --git a/deps/npm/lib/install/action/update-linked.js b/deps/npm/lib/install/action/update-linked.js deleted file mode 100644 index 0babe10fdf..0000000000 --- a/deps/npm/lib/install/action/update-linked.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' -var path = require('path') - -function getTop (pkg) { - if (pkg.target && pkg.target.parent) return getTop(pkg.target.parent) - if (pkg.parent) return getTop(pkg.parent) - return pkg.path -} - -module.exports = function (staging, pkg, log, next) { - if (pkg.package.version !== pkg.oldPkg.package.version) { - log.warn('update-linked', path.relative(getTop(pkg), pkg.path), 'needs updating to', pkg.package.version, - 'from', pkg.oldPkg.package.version, "but we can't, as it's a symlink") - } - next() -} |