summaryrefslogtreecommitdiff
path: root/deps/npm/lib/install/inflate-shrinkwrap.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib/install/inflate-shrinkwrap.js')
-rw-r--r--deps/npm/lib/install/inflate-shrinkwrap.js244
1 files changed, 166 insertions, 78 deletions
diff --git a/deps/npm/lib/install/inflate-shrinkwrap.js b/deps/npm/lib/install/inflate-shrinkwrap.js
index aca4204930..9878b0f19a 100644
--- a/deps/npm/lib/install/inflate-shrinkwrap.js
+++ b/deps/npm/lib/install/inflate-shrinkwrap.js
@@ -1,105 +1,193 @@
'use strict'
-var asyncMap = require('slide').asyncMap
-var validate = require('aproba')
-var iferr = require('iferr')
-var realizeShrinkwrapSpecifier = require('./realize-shrinkwrap-specifier.js')
-var isRegistrySpecifier = require('./is-registry-specifier.js')
-var fetchPackageMetadata = require('../fetch-package-metadata.js')
-var annotateMetadata = require('../fetch-package-metadata.js').annotateMetadata
-var addShrinkwrap = require('../fetch-package-metadata.js').addShrinkwrap
-var addBundled = require('../fetch-package-metadata.js').addBundled
-var inflateBundled = require('./inflate-bundled.js')
-var npm = require('../npm.js')
-var createChild = require('./node.js').create
-var moduleName = require('../utils/module-name.js')
-var childPath = require('../utils/child-path.js')
+
+const BB = require('bluebird')
+
+const addBundled = BB.promisify(require('../fetch-package-metadata.js').addBundled)
+const childPath = require('../utils/child-path.js')
+const createChild = require('./node.js').create
+const fetchPackageMetadata = BB.promisify(require('../fetch-package-metadata.js'))
+const inflateBundled = require('./inflate-bundled.js')
+const moduleName = require('../utils/module-name.js')
+const normalizePackageData = require('normalize-package-data')
+const npm = require('../npm.js')
+const realizeShrinkwrapSpecifier = require('./realize-shrinkwrap-specifier.js')
+const validate = require('aproba')
+const path = require('path')
module.exports = function (tree, swdeps, finishInflating) {
if (!npm.config.get('shrinkwrap')) return finishInflating()
tree.loaded = true
- return inflateShrinkwrap(tree.path, tree, swdeps, finishInflating)
+ return inflateShrinkwrap(tree.path, tree, swdeps).then(
+ () => finishInflating(),
+ finishInflating
+ )
}
-function inflateShrinkwrap (topPath, tree, swdeps, finishInflating) {
- validate('SOOF', arguments)
- var onDisk = {}
- tree.children.forEach(function (child) { onDisk[moduleName(child)] = child })
- var dev = npm.config.get('dev') || (!/^prod(uction)?$/.test(npm.config.get('only')) && !npm.config.get('production')) || /^dev(elopment)?$/.test(npm.config.get('only'))
- var prod = !/^dev(elopment)?$/.test(npm.config.get('only'))
-
- // If the shrinkwrap has no dev dependencies in it then we'll leave the one's
- // already on disk. If it DOES have dev dependencies then ONLY those in the
- // shrinkwrap will be included.
- var swHasDev = Object.keys(swdeps).some(function (name) { return swdeps[name].dev })
- tree.children = swHasDev ? [] : tree.children.filter(function (child) {
- return tree.package.devDependencies[moduleName(child)]
+function inflateShrinkwrap (topPath, tree, swdeps) {
+ validate('SOO', arguments)
+ const onDisk = {}
+ tree.children.forEach((child) => {
+ onDisk[moduleName(child)] = child
})
+ const dev = npm.config.get('dev') || (!/^prod(uction)?$/.test(npm.config.get('only')) && !npm.config.get('production')) || /^dev(elopment)?$/.test(npm.config.get('only'))
+ const prod = !/^dev(elopment)?$/.test(npm.config.get('only'))
- return asyncMap(Object.keys(swdeps), doRealizeAndInflate, finishInflating)
+ tree.children = []
- function doRealizeAndInflate (name, next) {
- return realizeShrinkwrapSpecifier(name, swdeps[name], topPath, iferr(next, andInflate(name, next)))
- }
+ return BB.each(Object.keys(swdeps), (name) => {
+ const sw = swdeps[name]
+ if (
+ (!prod && !sw.dev) ||
+ (!dev && sw.dev)
+ ) { return null }
+ const dependencies = sw.dependencies || {}
+ const requested = realizeShrinkwrapSpecifier(name, sw, topPath)
+ return inflatableChild(
+ onDisk[name], name, topPath, tree, sw, requested
+ ).then((child) => {
+ return inflateShrinkwrap(topPath, child, dependencies)
+ })
+ })
+}
- function andInflate (name, next) {
- return function (requested) {
- var sw = swdeps[name]
- var dependencies = sw.dependencies || {}
- if ((!prod && !sw.dev) || (!dev && sw.dev)) return next()
- var child = onDisk[name]
- if (childIsEquivalent(sw, requested, child)) {
- if (!child.fromShrinkwrap) child.fromShrinkwrap = requested.raw
- if (sw.dev) child.shrinkwrapDev = true
- tree.children.push(child)
- annotateMetadata(child.package, requested, requested.raw, topPath)
- return inflateShrinkwrap(topPath, child, dependencies || {}, next)
- } else {
- var from = sw.from || requested.raw
- var optional = sw.optional
- return fetchPackageMetadata(requested, topPath, iferr(next, andAddShrinkwrap(from, optional, dependencies, next)))
- }
- }
+function normalizePackageDataNoErrors (pkg) {
+ try {
+ normalizePackageData(pkg)
+ } catch (ex) {
+ // don't care
}
+}
- function andAddShrinkwrap (from, optional, dependencies, next) {
- return function (pkg) {
- pkg._from = from
- pkg._optional = optional
- addShrinkwrap(pkg, iferr(next, andAddBundled(pkg, dependencies, next)))
- }
+function inflatableChild (onDiskChild, name, topPath, tree, sw, requested) {
+ validate('OSSOOO|ZSSOOO', arguments)
+ if (onDiskChild && childIsEquivalent(sw, requested, onDiskChild)) {
+ // The version on disk matches the shrinkwrap entry.
+ if (!onDiskChild.fromShrinkwrap) onDiskChild.fromShrinkwrap = true
+ if (sw.dev) onDiskChild.shrinkwrapDev = true
+ onDiskChild.package._requested = requested
+ onDiskChild.package._spec = requested.rawSpec
+ onDiskChild.package._where = topPath
+ onDiskChild.fromBundle = sw.bundled ? tree.fromBundle || tree : null
+ if (!onDiskChild.package._args) onDiskChild.package._args = []
+ onDiskChild.package._args.push([String(requested), topPath])
+ // non-npm registries can and will return unnormalized data, plus
+ // even the npm registry may have package data normalized with older
+ // normalization rules. This ensures we get package data in a consistent,
+ // stable format.
+ normalizePackageDataNoErrors(onDiskChild.package)
+ tree.children.push(onDiskChild)
+ return BB.resolve(onDiskChild)
+ } else if (sw.version && sw.integrity) {
+ // The shrinkwrap entry has an integrity field. We can fake a pkg to get
+ // the installer to do a content-address fetch from the cache, if possible.
+ return BB.resolve(makeFakeChild(name, topPath, tree, sw, requested))
+ } else {
+ // It's not on disk, and we can't just look it up by address -- do a full
+ // fpm/inflate bundle pass. For registry deps, this will go straight to the
+ // tarball URL, as if it were a remote tarball dep.
+ return fetchChild(topPath, tree, sw, requested)
}
+}
- function andAddBundled (pkg, dependencies, next) {
- return function () {
- return addBundled(pkg, iferr(next, andAddChild(pkg, dependencies, next)))
+function makeFakeChild (name, topPath, tree, sw, requested) {
+ const from = sw.from || requested.raw
+ const pkg = {
+ name: name,
+ version: sw.version,
+ _resolved: adaptResolved(requested, sw.resolved),
+ _requested: requested,
+ _optional: sw.optional,
+ _integrity: sw.integrity,
+ _from: from,
+ _spec: requested.rawSpec,
+ _where: topPath,
+ _args: [[requested.toString(), topPath]],
+ _injectedFromShrinkwrap: sw
+ }
+ let bundleAdded = BB.resolve()
+ if (Object.keys(sw.dependencies || {}).some((d) => {
+ return sw.dependencies[d].bundled
+ })) {
+ pkg.bundleDependencies = []
+ bundleAdded = addBundled(pkg)
+ }
+ return bundleAdded.then(() => {
+ const child = createChild({
+ package: pkg,
+ loaded: true,
+ parent: tree,
+ children: pkg._bundled || [],
+ fromShrinkwrap: true,
+ fromBundle: sw.bundled ? tree.fromBundle || tree : null,
+ path: childPath(tree.path, pkg),
+ realpath: childPath(tree.realpath, pkg),
+ location: tree.location + '/' + pkg.name,
+ isInLink: tree.isLink
+ })
+ tree.children.push(child)
+ if (pkg._bundled) {
+ delete pkg._bundled
+ inflateBundled(child, child, child.children)
}
+ return child
+ })
+}
+
+function adaptResolved (requested, resolved) {
+ const registry = requested.scope
+ ? npm.config.get(`${requested.scope}:registry`) || npm.config.get('registry')
+ : npm.config.get('registry')
+ if (!requested.registry || (resolved && resolved.indexOf(registry) === 0)) {
+ // Nothing to worry about here. Pass it through.
+ return resolved
+ } else {
+ // We could fast-path for registry.npmjs.org here, but if we do, it
+ // would end up getting written back to the `resolved` field. By always
+ // returning `null` for other registries, `pacote.extract()` will take
+ // care of any required metadata fetches internally, without altering
+ // the tree we're going to write out to shrinkwrap/lockfile.
+ return null
}
+}
- function andAddChild (pkg, dependencies, next) {
- return function () {
- var child = createChild({
- package: pkg,
- loaded: true,
- parent: tree,
- fromShrinkwrap: pkg._from,
- path: childPath(tree.path, pkg),
- realpath: childPath(tree.realpath, pkg),
- children: pkg._bundled || []
- })
- tree.children.push(child)
- if (pkg._bundled) {
- delete pkg._bundled
- inflateBundled(child, child, child.children)
- }
- inflateShrinkwrap(topPath, child, dependencies || {}, next)
+function fetchChild (topPath, tree, sw, requested) {
+ const from = sw.from || requested.raw
+ const optional = sw.optional
+ return fetchPackageMetadata(requested, topPath).then((pkg) => {
+ pkg._from = from
+ pkg._optional = optional
+ return addBundled(pkg).then(() => pkg)
+ }).then((pkg) => {
+ var isLink = pkg._requested.type === 'directory'
+ const child = createChild({
+ package: pkg,
+ loaded: true,
+ parent: tree,
+ fromShrinkwrap: requested,
+ path: childPath(tree.path, pkg),
+ realpath: isLink ? requested.fetchSpec : childPath(tree.realpath, pkg),
+ children: pkg._bundled || [],
+ location: tree.location + '/' + pkg.name,
+ isLink: isLink,
+ isInLink: tree.isLink
+ })
+ tree.children.push(child)
+ if (pkg._bundled) {
+ delete pkg._bundled
+ inflateBundled(child, child, child.children)
}
- }
+ return child
+ })
}
function childIsEquivalent (sw, requested, child) {
if (!child) return false
if (child.fromShrinkwrap) return true
+ if (sw.integrity && child.package._integrity === sw.integrity) return true
+ if (child.isLink && requested.type === 'directory') return path.relative(child.realpath, requested.fetchSpec) === ''
+
if (sw.resolved) return child.package._resolved === sw.resolved
- if (!isRegistrySpecifier(requested) && sw.from) return child.package._from === sw.from
+ if (!requested.registry && sw.from) return child.package._from === sw.from
+ if (!requested.registry && child.package._resolved) return sw.version === child.package._resolved
return child.package.version === sw.version
}