summaryrefslogtreecommitdiff
path: root/deps/npm/lib/install/deps.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib/install/deps.js')
-rw-r--r--deps/npm/lib/install/deps.js475
1 files changed, 251 insertions, 224 deletions
diff --git a/deps/npm/lib/install/deps.js b/deps/npm/lib/install/deps.js
index d1feb6cd4b..3f3433535f 100644
--- a/deps/npm/lib/install/deps.js
+++ b/deps/npm/lib/install/deps.js
@@ -1,20 +1,19 @@
'use strict'
+
+const BB = require('bluebird')
+
+var fs = require('fs')
var assert = require('assert')
var path = require('path')
var semver = require('semver')
var asyncMap = require('slide').asyncMap
var chain = require('slide').chain
-var union = require('lodash.union')
var iferr = require('iferr')
var npa = require('npm-package-arg')
var validate = require('aproba')
-var realizePackageSpecifier = require('realize-package-specifier')
-var realizeShrinkwrapSpecifier = require('./realize-shrinkwrap-specifier')
-var asap = require('asap')
var dezalgo = require('dezalgo')
var fetchPackageMetadata = require('../fetch-package-metadata.js')
var andAddParentToErrors = require('./and-add-parent-to-errors.js')
-var addShrinkwrap = require('../fetch-package-metadata.js').addShrinkwrap
var addBundled = require('../fetch-package-metadata.js').addBundled
var readShrinkwrap = require('./read-shrinkwrap.js')
var inflateShrinkwrap = require('./inflate-shrinkwrap.js')
@@ -24,35 +23,17 @@ var npm = require('../npm.js')
var flatNameFromTree = require('./flatten-tree.js').flatNameFromTree
var createChild = require('./node.js').create
var resetMetadata = require('./node.js').reset
-var andIgnoreErrors = require('./and-ignore-errors.js')
var isInstallable = require('./validate-args.js').isInstallable
var packageId = require('../utils/package-id.js')
var moduleName = require('../utils/module-name.js')
var isDevDep = require('./is-dev-dep.js')
var isProdDep = require('./is-prod-dep.js')
var reportOptionalFailure = require('./report-optional-failure.js')
+var getSaveType = require('./save.js').getSaveType
// The export functions in this module mutate a dependency tree, adding
// items to them.
-function isDep (tree, child, cb) {
- var name = moduleName(child)
- var prodVer = isProdDep(tree, name)
- var devVer = isDevDep(tree, name)
-
- childDependencySpecifier(tree, name, prodVer, function (er, prodSpec) {
- if (er) return cb(child.fromShrinkwrap)
- var matches
- if (prodSpec) matches = doesChildVersionMatch(child, prodSpec, tree)
- if (matches) return cb(true, prodSpec)
- if (devVer === prodVer) return cb(child.fromShrinkwrap)
- childDependencySpecifier(tree, name, devVer, function (er, devSpec) {
- if (er) return cb(child.fromShrinkwrap)
- cb(doesChildVersionMatch(child, devSpec, tree) || child.fromShrinkwrap, null, devSpec)
- })
- })
-}
-
var registryTypes = { range: true, version: true }
function doesChildVersionMatch (child, requested, requestor) {
@@ -61,130 +42,121 @@ function doesChildVersionMatch (child, requested, requestor) {
if (child.parent === requestor && child.fromShrinkwrap) return true
// ranges of * ALWAYS count as a match, because when downloading we allow
// prereleases to match * if there are ONLY prereleases
- if (requested.spec === '*') return true
+ if (requested.type === 'range' && requested.fetchSpec === '*') return true
- var childReq = child.package._requested
- if (!childReq) childReq = npa(moduleName(child) + '@' + child.package._from)
- if (childReq) {
- if (childReq.rawSpec === requested.rawSpec) return true
- if (childReq.type === requested.type && childReq.spec === requested.spec) return true
+ if (requested.type === 'directory') {
+ if (!child.isLink) return false
+ return path.relative(child.realpath, requested.fetchSpec) === ''
}
- // If _requested didn't exist OR if it didn't match then we'll try using
- // _from. We pass it through npa to normalize the specifier.
- // This can happen when installing from an `npm-shrinkwrap.json` where `_requested` will
- // be the tarball URL from `resolved` and thus can't match what's in the `package.json`.
- // In those cases _from, will be preserved and we can compare that to ensure that they
- // really came from the same sources.
- // You'll see this scenario happen with at least tags and git dependencies.
+
if (!registryTypes[requested.type]) {
+ var childReq = child.package._requested
+ if (!childReq && child.package._from) {
+ childReq = npa.resolve(moduleName(child), child.package._from.replace(new RegExp('^' + moduleName(child) + '@'), ''))
+ }
+ if (childReq) {
+ if (childReq.rawSpec === requested.rawSpec) return true
+ if (childReq.type === requested.type && childReq.saveSpec === requested.saveSpec) return true
+ if (childReq.type === requested.type && childReq.spec === requested.saveSpec) return true
+ }
+ // If _requested didn't exist OR if it didn't match then we'll try using
+ // _from. We pass it through npa to normalize the specifier.
+ // This can happen when installing from an `npm-shrinkwrap.json` where `_requested` will
+ // be the tarball URL from `resolved` and thus can't match what's in the `package.json`.
+ // In those cases _from, will be preserved and we can compare that to ensure that they
+ // really came from the same sources.
+ // You'll see this scenario happen with at least tags and git dependencies.
if (child.package._from) {
var fromReq = npa(child.package._from)
if (fromReq.rawSpec === requested.rawSpec) return true
- if (fromReq.type === requested.type && fromReq.spec === requested.spec) return true
+ if (fromReq.type === requested.type && fromReq.saveSpec && fromReq.saveSpec === requested.saveSpec) return true
}
return false
}
- return semver.satisfies(child.package.version, requested.spec)
-}
-
-// TODO: Rename to maybe computeMetadata or computeRelationships
-exports.recalculateMetadata = function (tree, log, next) {
- recalculateMetadata(tree, log, {}, next)
+ try {
+ return semver.satisfies(child.package.version, requested.fetchSpec)
+ } catch (e) {
+ return false
+ }
}
-exports._childDependencySpecifier = childDependencySpecifier
-function childDependencySpecifier (tree, name, spec, cb) {
- if (!tree.resolved) tree.resolved = {}
- if (!tree.resolved[name]) tree.resolved[name] = {}
- if (tree.resolved[name][spec]) {
- return asap(function () {
- cb(null, tree.resolved[name][spec])
- })
- }
- realizePackageSpecifier(name + '@' + spec, packageRelativePath(tree), function (er, req) {
- if (er) return cb(er)
- tree.resolved[name][spec] = req
- cb(null, req)
- })
+function childDependencySpecifier (tree, name, spec) {
+ return npa.resolve(name, spec, packageRelativePath(tree))
}
-function recalculateMetadata (tree, log, seen, next) {
- validate('OOOF', arguments)
- if (seen[tree.path]) return next()
+exports.computeMetadata = computeMetadata
+function computeMetadata (tree, seen) {
+ if (!seen) seen = {}
+ if (!tree || seen[tree.path]) return
seen[tree.path] = true
if (tree.parent == null) {
resetMetadata(tree)
tree.isTop = true
}
+ tree.location = flatNameFromTree(tree)
- function markDeps (toMark, done) {
- var name = toMark.name
- var spec = toMark.spec
- var kind = toMark.kind
- childDependencySpecifier(tree, name, spec, function (er, req) {
- if (er || !req.name) return done()
- var child = findRequirement(tree, req.name, req)
- if (child) {
- resolveWithExistingModule(child, tree, log, andIgnoreErrors(done))
- } else if (kind === 'dep') {
- tree.missingDeps[req.name] = req.rawSpec
- done()
- } else if (kind === 'dev') {
- tree.missingDevDeps[req.name] = req.rawSpec
- done()
- } else {
- done()
- }
- })
+ function findChild (name, spec, kind) {
+ try {
+ var req = childDependencySpecifier(tree, name, spec)
+ } catch (err) {
+ return
+ }
+ var child = findRequirement(tree, req.name, req)
+ if (child) {
+ resolveWithExistingModule(child, tree)
+ return true
+ }
+ return
}
- function makeMarkable (deps, kind) {
- if (!deps) return []
- return Object.keys(deps).map(function (depname) { return { name: depname, spec: deps[depname], kind: kind } })
+ const deps = tree.package.dependencies || {}
+ for (let name of Object.keys(deps)) {
+ if (findChild(name, deps[name])) continue
+ tree.missingDeps[name] = deps[name]
+ }
+ if (tree.isTop) {
+ const devDeps = tree.package.devDependencies || {}
+ for (let name of Object.keys(devDeps)) {
+ if (findChild(name, devDeps[name])) continue
+ tree.missingDevDeps[name] = devDeps[name]
+ }
}
- // Ensure dependencies and dev dependencies are marked as required
- var tomark = makeMarkable(tree.package.dependencies, 'dep')
- if (tree.isTop) tomark = union(tomark, makeMarkable(tree.package.devDependencies, 'dev'))
+ tree.children.filter((child) => !child.removed && !child.failed).forEach((child) => computeMetadata(child, seen))
- // Ensure any children ONLY from a shrinkwrap are also included
- var childrenOnlyInShrinkwrap = tree.children.filter(function (child) {
- return child.fromShrinkwrap &&
- !tree.package.dependencies[child.package.name] &&
- !tree.package.devDependencies[child.package.name]
- })
- var tomarkOnlyInShrinkwrap = childrenOnlyInShrinkwrap.map(function (child) {
- var name = child.package.name
- var matched = child.package._spec.match(/^@?[^@]+@(.*)$/)
- var spec = matched ? matched[1] : child.package._spec
- var kind = tree.package.dependencies[name] ? 'dep'
- : tree.package.devDependencies[name] ? 'dev'
- : 'dep'
- return { name: name, spec: spec, kind: kind }
- })
- tomark = union(tomark, tomarkOnlyInShrinkwrap)
+ return tree
+}
- // Don't bother trying to recalc children of failed deps
- tree.children = tree.children.filter(function (child) { return !child.failed })
+function isDep (tree, child) {
+ var name = moduleName(child)
+ var prodVer = isProdDep(tree, name)
+ var devVer = isDevDep(tree, name)
- chain([
- [asyncMap, tomark, markDeps],
- [asyncMap, tree.children, function (child, done) { recalculateMetadata(child, log, seen, done) }]
- ], function () {
- tree.location = flatNameFromTree(tree)
- next(null, tree)
- })
+ try {
+ var prodSpec = childDependencySpecifier(tree, name, prodVer)
+ } catch (err) {
+ return {isDep: true, isProdDep: false, isDevDep: false}
+ }
+ var matches
+ if (prodSpec) matches = doesChildVersionMatch(child, prodSpec, tree)
+ if (matches) return {isDep: true, isProdDep: prodSpec, isDevDep: false}
+ if (devVer === prodVer) return {isDep: child.fromShrinkwrap, isProdDep: false, isDevDep: false}
+ try {
+ var devSpec = childDependencySpecifier(tree, name, devVer)
+ return {isDep: doesChildVersionMatch(child, devSpec, tree) || child.fromShrinkwrap, isProdDep: false, isDevDep: devSpec}
+ } catch (err) {
+ return {isDep: child.fromShrinkwrap, isProdDep: false, isDevDep: false}
+ }
}
-function addRequiredDep (tree, child, cb) {
- isDep(tree, child, function (childIsDep, childIsProdDep, childIsDevDep) {
- if (!childIsDep) return cb(false)
- replaceModuleByPath(child, 'requiredBy', tree)
- replaceModuleByName(tree, 'requires', child)
- if (childIsProdDep && tree.missingDeps) delete tree.missingDeps[moduleName(child)]
- if (childIsDevDep && tree.missingDevDeps) delete tree.missingDevDeps[moduleName(child)]
- cb(true)
- })
+function addRequiredDep (tree, child) {
+ var dep = isDep(tree, child)
+ if (!dep.isDep) return false
+ replaceModuleByPath(child, 'requiredBy', tree)
+ replaceModuleByName(tree, 'requires', child)
+ if (dep.isProdDep && tree.missingDeps) delete tree.missingDeps[moduleName(child)]
+ if (dep.isDevDep && tree.missingDevDeps) delete tree.missingDevDeps[moduleName(child)]
+ return true
}
exports.removeObsoleteDep = removeObsoleteDep
@@ -207,45 +179,38 @@ function removeObsoleteDep (child, log) {
})
}
-function matchingDep (tree, name) {
- if (tree.package.dependencies && tree.package.dependencies[name]) return tree.package.dependencies[name]
- if (tree.package.devDependencies && tree.package.devDependencies[name]) return tree.package.devDependencies[name]
- return
-}
-
function packageRelativePath (tree) {
if (!tree) return ''
var requested = tree.package._requested || {}
- var isLocal = requested.type === 'directory' || requested.type === 'local'
- return isLocal ? requested.spec : tree.path
+ var isLocal = requested.type === 'directory' || requested.type === 'file'
+ return isLocal ? requested.fetchSpec : tree.path
}
-function getShrinkwrap (tree, name) {
- return tree.package._shrinkwrap && tree.package._shrinkwrap.dependencies && tree.package._shrinkwrap.dependencies[name]
+function matchingDep (tree, name) {
+ if (!tree || !tree.package) return
+ if (tree.package.dependencies && tree.package.dependencies[name]) return tree.package.dependencies[name]
+ if (tree.package.devDependencies && tree.package.devDependencies[name]) return tree.package.devDependencies[name]
+ return
}
exports.getAllMetadata = function (args, tree, where, next) {
asyncMap(args, function (arg, done) {
- function fetchMetadataWithVersion () {
- var version = matchingDep(tree, arg)
- var spec = version == null ? arg : arg + '@' + version
- return fetchPackageMetadata(spec, where, done)
- }
- if (tree && arg.lastIndexOf('@') <= 0) {
- var sw = getShrinkwrap(tree, arg)
- if (sw) {
- return realizeShrinkwrapSpecifier(arg, sw, where, function (err, spec) {
- if (err) {
- return fetchMetadataWithVersion()
+ var spec = npa(arg)
+ if (spec.type !== 'file' && spec.type !== 'directory' && (spec.name == null || spec.rawSpec === '')) {
+ return fs.stat(path.join(arg, 'package.json'), (err) => {
+ if (err) {
+ var version = matchingDep(tree, spec.name)
+ if (version) {
+ return fetchPackageMetadata(npa.resolve(spec.name, version), where, done)
} else {
return fetchPackageMetadata(spec, where, done)
}
- })
- } else {
- return fetchMetadataWithVersion()
- }
+ } else {
+ return fetchPackageMetadata(npa('file:' + arg), where, done)
+ }
+ })
} else {
- return fetchPackageMetadata(arg, where, done)
+ return fetchPackageMetadata(spec, where, done)
}
}, next)
}
@@ -261,13 +226,12 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next)
child.isGlobal = true
}
var childName = moduleName(child)
+ child.saveSpec = computeVersionSpec(tree, child)
if (saveToDependencies) {
- tree.package[saveToDependencies][childName] =
- child.package._requested.rawSpec || child.package._requested.spec
+ tree.package[getSaveType(tree, child)][childName] = child.saveSpec
}
- if (saveToDependencies && saveToDependencies !== 'devDependencies') {
- tree.package.dependencies[childName] =
- child.package._requested.rawSpec || child.package._requested.spec
+ if (getSaveType(tree, child) === 'optionalDependencies') {
+ tree.package.dependencies[childName] = child.saveSpec
}
child.userRequired = true
child.save = saveToDependencies
@@ -275,14 +239,32 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next)
// For things the user asked to install, that aren't a dependency (or
// won't be when we're done), flag it as "depending" on the user
// themselves, so we don't remove it as a dep that no longer exists
- addRequiredDep(tree, child, function (childIsDep) {
- if (!childIsDep) child.userRequired = true
- depLoaded(null, child, tracker)
- })
+ var childIsDep = addRequiredDep(tree, child)
+ if (!childIsDep) child.userRequired = true
+ depLoaded(null, child, tracker)
}))
}, andForEachChild(loadDeps, andFinishTracker(log, next)))
}
+function computeVersionSpec (tree, child) {
+ validate('OO', arguments)
+ var requested = child.package._requested
+ if (requested.registry) {
+ var version = child.package.version
+ var rangeDescriptor = ''
+ if (semver.valid(version, true) &&
+ semver.gte(version, '0.1.0', true) &&
+ !npm.config.get('save-exact')) {
+ rangeDescriptor = npm.config.get('save-prefix')
+ }
+ return rangeDescriptor + version
+ } else if (requested.type === 'directory' || requested.type === 'file') {
+ return 'file:' + path.relative(tree.path, requested.fetchSpec)
+ } else {
+ return requested.saveSpec
+ }
+}
+
function moduleNameMatches (name) {
return function (child) { return moduleName(child) === name }
}
@@ -299,11 +281,18 @@ exports.removeDeps = function (args, tree, saveToDependencies, log, next) {
var pkgName = moduleName(pkg)
var toRemove = tree.children.filter(moduleNameMatches(pkgName))
var pkgToRemove = toRemove[0] || createChild({package: {name: pkgName}})
- if (saveToDependencies) {
- replaceModuleByPath(tree, 'removed', pkgToRemove)
- pkgToRemove.save = saveToDependencies
+ if (tree.isTop) {
+ if (saveToDependencies) {
+ pkgToRemove.save = getSaveType(tree, pkg)
+ delete tree.package[pkgToRemove.save][pkgName]
+ if (pkgToRemove.save === 'optionalDependencies') {
+ delete tree.package.dependencies[pkgName]
+ }
+ replaceModuleByPath(tree, 'removed', pkgToRemove)
+ }
+ pkgToRemove.requiredBy = pkgToRemove.requiredBy.filter((parent) => parent !== tree)
}
- removeObsoleteDep(pkgToRemove)
+ if (pkgToRemove.requiredBy.length === 0) removeObsoleteDep(pkgToRemove)
})
log.finish()
next()
@@ -387,6 +376,43 @@ function andHandleOptionalErrors (log, tree, name, done) {
}
}
+exports.prefetchDeps = prefetchDeps
+function prefetchDeps (tree, deps, log, next) {
+ validate('OOOF', arguments)
+ var skipOptional = !npm.config.get('optional')
+ var seen = {}
+ const finished = andFinishTracker(log, next)
+ const fpm = BB.promisify(fetchPackageMetadata)
+ resolveBranchDeps(tree.package, deps).then(
+ () => finished(), finished
+ )
+
+ function resolveBranchDeps (pkg, deps) {
+ return BB.resolve(null).then(() => {
+ var allDependencies = Object.keys(deps).map((dep) => {
+ return npa.resolve(dep, deps[dep])
+ }).filter((dep) => {
+ return dep.registry &&
+ !seen[dep.toString()] &&
+ !findRequirement(tree, dep.name, dep)
+ })
+ if (skipOptional) {
+ var optDeps = pkg.optionalDependencies || {}
+ allDependencies = allDependencies.filter((dep) => !optDeps[dep.name])
+ }
+ return BB.map(allDependencies, (dep) => {
+ seen[dep.toString()] = true
+ return fpm(dep, '', {tracker: log.newItem('fetchMetadata')}).then(
+ (pkg) => {
+ return pkg && pkg.dependencies && resolveBranchDeps(pkg, pkg.dependencies)
+ },
+ () => null
+ )
+ })
+ })
+ }
+}
+
// Load any missing dependencies in the given tree
exports.loadDeps = loadDeps
function loadDeps (tree, log, next) {
@@ -427,15 +453,19 @@ exports.loadDevDeps = function (tree, log, next) {
var loadExtraneous = exports.loadExtraneous = function (tree, log, next) {
var seen = {}
- function loadExtraneous (tree, log, next) {
- validate('OOF', arguments)
- if (seen[tree.path]) return next()
+
+ function loadExtraneous (tree) {
+ if (seen[tree.path]) return
seen[tree.path] = true
- asyncMap(tree.children.filter(function (child) { return !child.loaded }), function (child, done) {
- resolveWithExistingModule(child, tree, log, done)
- }, andForEachChild(loadExtraneous, andFinishTracker(log, next)))
+ for (var child of tree.children) {
+ if (child.loaded) continue
+ resolveWithExistingModule(child, tree)
+ loadExtraneous(child)
+ }
}
- loadExtraneous(tree, log, next)
+ loadExtraneous(tree)
+ log.finish()
+ next()
}
exports.loadExtraneous.andResolveDeps = function (tree, log, next) {
@@ -444,37 +474,38 @@ exports.loadExtraneous.andResolveDeps = function (tree, log, next) {
// resolving the dependencies of extraneous deps.
if (tree.loaded) return loadExtraneous(tree, log, next)
asyncMap(tree.children.filter(function (child) { return !child.loaded }), function (child, done) {
- resolveWithExistingModule(child, tree, log, done)
+ resolveWithExistingModule(child, tree)
+ done(null, child, log)
}, andForEachChild(loadDeps, andFinishTracker(log, next)))
}
function addDependency (name, versionSpec, tree, log, done) {
validate('SSOOF', arguments)
var next = andAddParentToErrors(tree, done)
- childDependencySpecifier(tree, name, versionSpec, iferr(done, function (req) {
- var child = findRequirement(tree, name, req)
- if (child) {
- resolveWithExistingModule(child, tree, log, iferr(next, function (child, log) {
- if (child.package._shrinkwrap === undefined) {
- readShrinkwrap.andInflate(child, function (er) { next(er, child, log) })
- } else {
- next(null, child, log)
- }
- }))
+ try {
+ var req = childDependencySpecifier(tree, name, versionSpec)
+ } catch (err) {
+ return done(err)
+ }
+ var child = findRequirement(tree, name, req)
+ if (child) {
+ resolveWithExistingModule(child, tree)
+ if (child.package._shrinkwrap === undefined) {
+ readShrinkwrap.andInflate(child, function (er) { next(er, child, log) })
} else {
- fetchPackageMetadata(req, packageRelativePath(tree), {tracker: log.newItem('fetchMetadata')}, iferr(next, function (pkg) {
- resolveWithNewModule(pkg, tree, log, next)
- }))
+ next(null, child, log)
}
- }))
+ } else {
+ fetchPackageMetadata(req, packageRelativePath(tree), {tracker: log.newItem('fetchMetadata')}, iferr(next, function (pkg) {
+ resolveWithNewModule(pkg, tree, log, next)
+ }))
+ }
}
-function resolveWithExistingModule (child, tree, log, next) {
- validate('OOOF', arguments)
- addRequiredDep(tree, child, function () {
- if (tree.parent && child.parent !== tree) updatePhantomChildren(tree.parent, child)
- next(null, child, log)
- })
+function resolveWithExistingModule (child, tree) {
+ validate('OO', arguments)
+ addRequiredDep(tree, child)
+ if (tree.parent && child.parent !== tree) updatePhantomChildren(tree.parent, child)
}
var updatePhantomChildren = exports.updatePhantomChildren = function (current, child) {
@@ -521,44 +552,39 @@ function resolveWithNewModule (pkg, tree, log, next) {
log.silly('resolveWithNewModule', packageId(pkg), 'checking installable status')
return isInstallable(pkg, iferr(next, function () {
- if (!pkg._from) {
- pkg._from = pkg._requested.name + '@' + pkg._requested.spec
- }
- addShrinkwrap(pkg, iferr(next, function () {
- addBundled(pkg, iferr(next, function () {
- var parent = earliestInstallable(tree, tree, pkg) || tree
- var child = createChild({
- package: pkg,
- parent: parent,
- path: path.join(parent.path, 'node_modules', pkg.name),
- realpath: path.resolve(parent.realpath, 'node_modules', pkg.name),
- children: pkg._bundled || [],
- isLink: tree.isLink,
- knownInstallable: true
- })
- delete pkg._bundled
- var hasBundled = child.children.length
-
- var replaced = replaceModuleByName(parent, 'children', child)
- if (replaced) removeObsoleteDep(replaced)
- addRequiredDep(tree, child, function () {
- child.location = flatNameFromTree(child)
+ addBundled(pkg, iferr(next, function () {
+ var parent = earliestInstallable(tree, tree, pkg) || tree
+ var isLink = pkg._requested.type === 'directory'
+ var child = createChild({
+ package: pkg,
+ parent: parent,
+ path: path.join(parent.isLink ? parent.realpath : parent.path, 'node_modules', pkg.name),
+ realpath: isLink ? pkg._requested.fetchSpec : path.join(parent.realpath, 'node_modules', pkg.name),
+ children: pkg._bundled || [],
+ isLink: isLink,
+ isInLink: parent.isLink,
+ knownInstallable: true
+ })
+ delete pkg._bundled
+ var hasBundled = child.children.length
- if (tree.parent && parent !== tree) updatePhantomChildren(tree.parent, child)
+ var replaced = replaceModuleByName(parent, 'children', child)
+ if (replaced) removeObsoleteDep(replaced)
+ addRequiredDep(tree, child)
+ child.location = flatNameFromTree(child)
- if (hasBundled) {
- inflateBundled(child, child, child.children)
- }
+ if (tree.parent && parent !== tree) updatePhantomChildren(tree.parent, child)
- if (pkg._shrinkwrap && pkg._shrinkwrap.dependencies) {
- return inflateShrinkwrap(child, pkg._shrinkwrap.dependencies, function (er) {
- next(er, child, log)
- })
- }
+ if (hasBundled) {
+ inflateBundled(child, child, child.children)
+ }
- next(null, child, log)
+ if (pkg._shrinkwrap && pkg._shrinkwrap.dependencies) {
+ return inflateShrinkwrap(child, pkg._shrinkwrap.dependencies, function (er) {
+ next(er, child, log)
})
- }))
+ }
+ next(null, child, log)
}))
}))
}
@@ -567,7 +593,7 @@ var validatePeerDeps = exports.validatePeerDeps = function (tree, onInvalid) {
if (!tree.package.peerDependencies) return
Object.keys(tree.package.peerDependencies).forEach(function (pkgname) {
var version = tree.package.peerDependencies[pkgname]
- var match = findRequirement(tree.parent || tree, pkgname, npa(pkgname + '@' + version))
+ var match = findRequirement(tree.parent || tree, pkgname, npa.resolve(pkgname, version))
if (!match) onInvalid(tree, pkgname, version)
})
}
@@ -590,7 +616,7 @@ var findRequirement = exports.findRequirement = function (tree, name, requested,
validate('OSO', [tree, name, requested])
if (!requestor) requestor = tree
var nameMatch = function (child) {
- return moduleName(child) === name && child.parent && !child.removed
+ return moduleName(child) === name && child.parent && !child.removed && !child.failed
}
var versionMatch = function (child) {
return doesChildVersionMatch(child, requested, requestor)
@@ -618,7 +644,6 @@ var findRequirement = exports.findRequirement = function (tree, name, requested,
// If it is, then it's the level below where its installed.
var earliestInstallable = exports.earliestInstallable = function (requiredBy, tree, pkg) {
validate('OOO', arguments)
-
function undeletedModuleMatches (child) {
return !child.removed && moduleName(child) === pkg.name
}
@@ -645,7 +670,7 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr
var devDeps = tree.package.devDependencies || {}
if (tree.isTop && devDeps[pkg.name]) {
- var requested = npa(pkg.name + '@' + devDeps[pkg.name])
+ var requested = npa.resolve(pkg.name, devDeps[pkg.name], tree.path)
if (!doesChildVersionMatch({package: pkg}, requested, tree)) {
return null
}
@@ -659,5 +684,7 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr
if (npm.config.get('global-style') && tree.parent.isTop) return tree
if (npm.config.get('legacy-bundling')) return tree
+ if (!process.env.NODE_PRESERVE_SYMLINKS && /^[.][.][\\/]/.test(path.relative(tree.parent.realpath, tree.realpath))) return tree
+
return (earliestInstallable(requiredBy, tree.parent, pkg) || tree)
}