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.js91
1 files changed, 65 insertions, 26 deletions
diff --git a/deps/npm/lib/install/deps.js b/deps/npm/lib/install/deps.js
index 3f3433535f..c0fe905d4b 100644
--- a/deps/npm/lib/install/deps.js
+++ b/deps/npm/lib/install/deps.js
@@ -183,7 +183,9 @@ function packageRelativePath (tree) {
if (!tree) return ''
var requested = tree.package._requested || {}
var isLocal = requested.type === 'directory' || requested.type === 'file'
- return isLocal ? requested.fetchSpec : tree.path
+ return isLocal ? requested.fetchSpec
+ : (tree.isLink || tree.isInLink) && !preserveSymlinks() ? tree.realpath
+ : tree.path
}
function matchingDep (tree, name) {
@@ -227,14 +229,24 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next)
}
var childName = moduleName(child)
child.saveSpec = computeVersionSpec(tree, child)
- if (saveToDependencies) {
- tree.package[getSaveType(tree, child)][childName] = child.saveSpec
- }
- if (getSaveType(tree, child) === 'optionalDependencies') {
- tree.package.dependencies[childName] = child.saveSpec
- }
child.userRequired = true
- child.save = saveToDependencies
+ child.save = getSaveType(tree, child)
+ const types = ['dependencies', 'devDependencies', 'optionalDependencies']
+ if (child.save) {
+ tree.package[child.save][childName] = child.saveSpec
+ // Astute readers might notice that this exact same code exists in
+ // save.js under a different guise. That code is responsible for deps
+ // being removed from the final written `package.json`. The removal in
+ // this function is specifically to prevent "installed as both X and Y"
+ // warnings when moving an existing dep between different dep fields.
+ //
+ // Or, try it by removing this loop, and do `npm i -P x && npm i -D x`
+ for (let saveType of types) {
+ if (child.save !== saveType) {
+ delete tree.package[saveType][childName]
+ }
+ }
+ }
// 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
@@ -246,9 +258,17 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next)
}, andForEachChild(loadDeps, andFinishTracker(log, next)))
}
+module.exports.computeVersionSpec = computeVersionSpec
function computeVersionSpec (tree, child) {
validate('OO', arguments)
- var requested = child.package._requested
+ var requested
+ if (child.package._requested) {
+ requested = child.package._requested
+ } else if (child.package._from) {
+ requested = npa(child.package._from)
+ } else {
+ requested = npa.resolve(child.package.name, child.package.version)
+ }
if (requested.registry) {
var version = child.package.version
var rangeDescriptor = ''
@@ -275,26 +295,38 @@ function noModuleNameMatches (name) {
// while this implementation does not require async calling, doing so
// gives this a consistent interface with loadDeps et al
-exports.removeDeps = function (args, tree, saveToDependencies, log, next) {
- validate('AOOF', [args, tree, log, next])
- args.forEach(function (pkg) {
+exports.removeDeps = function (args, tree, saveToDependencies, next) {
+ validate('AOSF|AOZF', [args, tree, saveToDependencies, next])
+ for (let pkg of args) {
var pkgName = moduleName(pkg)
var toRemove = tree.children.filter(moduleNameMatches(pkgName))
var pkgToRemove = toRemove[0] || createChild({package: {name: pkgName}})
- 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)
+ var saveType = getSaveType(tree, pkg) || 'dependencies'
+ if (tree.isTop && saveToDependencies) {
+ pkgToRemove.save = saveType
+ }
+ if (tree.package[saveType][pkgName]) {
+ delete tree.package[saveType][pkgName]
+ if (saveType === 'optionalDependencies' && tree.package.dependencies[pkgName]) {
+ delete tree.package.dependencies[pkgName]
}
- pkgToRemove.requiredBy = pkgToRemove.requiredBy.filter((parent) => parent !== tree)
}
- if (pkgToRemove.requiredBy.length === 0) removeObsoleteDep(pkgToRemove)
- })
- log.finish()
+ replaceModuleByPath(tree, 'removedChildren', pkgToRemove)
+ for (let parent of pkgToRemove.requiredBy) {
+ parent.requires = parent.requires.filter((child) => child !== pkgToRemove)
+ }
+ pkgToRemove.requiredBy = pkgToRemove.requiredBy.filter((parent) => parent !== tree)
+ }
+ next()
+}
+exports.removeExtraneous = function (args, tree, next) {
+ for (let pkg of args) {
+ var pkgName = moduleName(pkg)
+ var toRemove = tree.children.filter(moduleNameMatches(pkgName))
+ if (toRemove.length) {
+ removeObsoleteDep(toRemove[0])
+ }
+ }
next()
}
@@ -639,6 +671,13 @@ var findRequirement = exports.findRequirement = function (tree, name, requested,
return findRequirement(tree.parent, name, requested, requestor)
}
+function preserveSymlinks () {
+ if (!('NODE_PRESERVE_SYMLINKS' in process.env)) return false
+ const value = process.env.NODE_PRESERVE_SYMLINKS
+ if (value == null || value === '' || value === 'false' || value === 'no' || value === '0') return false
+ return true
+}
+
// Find the highest level in the tree that we can install this module in.
// If the module isn't installed above us yet, that'd be the very top.
// If it is, then it's the level below where its installed.
@@ -670,7 +709,7 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr
var devDeps = tree.package.devDependencies || {}
if (tree.isTop && devDeps[pkg.name]) {
- var requested = npa.resolve(pkg.name, devDeps[pkg.name], tree.path)
+ var requested = childDependencySpecifier(tree, pkg.name, devDeps[pkg.name])
if (!doesChildVersionMatch({package: pkg}, requested, tree)) {
return null
}
@@ -684,7 +723,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
+ if (!preserveSymlinks() && /^[.][.][\\/]/.test(path.relative(tree.parent.realpath, tree.realpath))) return tree
return (earliestInstallable(requiredBy, tree.parent, pkg) || tree)
}