Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib/install/mutate-into-logical-tree.js')
-rw-r--r--deps/npm/lib/install/mutate-into-logical-tree.js71
1 files changed, 46 insertions, 25 deletions
diff --git a/deps/npm/lib/install/mutate-into-logical-tree.js b/deps/npm/lib/install/mutate-into-logical-tree.js
index 833aa94c940..b2059da9060 100644
--- a/deps/npm/lib/install/mutate-into-logical-tree.js
+++ b/deps/npm/lib/install/mutate-into-logical-tree.js
@@ -8,6 +8,24 @@ var validateAllPeerDeps = require('./deps.js').validateAllPeerDeps
var packageId = require('../utils/package-id.js')
var moduleName = require('../utils/module-name.js')
+// Return true if tree is a part of a cycle that:
+// A) Never connects to the top of the tree
+// B) Has not not had a point in the cycle arbitraryly declared its top
+// yet.
+function isDisconnectedCycle (tree, seen) {
+ if (!seen) seen = {}
+ if (tree.isTop || tree.cycleTop || tree.requiredBy.length === 0) {
+ return false
+ } else if (seen[tree.path]) {
+ return true
+ } else {
+ seen[tree.path] = true
+ return tree.requiredBy.every(function (node) {
+ return isDisconnectedCycle(node, Object.create(seen))
+ })
+ }
+}
+
var mutateIntoLogicalTree = module.exports = function (tree) {
validate('O', arguments)
@@ -18,35 +36,29 @@ var mutateIntoLogicalTree = module.exports = function (tree) {
var flat = flattenTree(tree)
- function getNode (flatname) {
- return flatname.substr(0, 5) === '#DEV:'
- ? flat[flatname.substr(5)]
- : flat[flatname]
- }
-
Object.keys(flat).sort().forEach(function (flatname) {
var node = flat[flatname]
- var requiredBy = node.package._requiredBy || []
- var requiredByNames = requiredBy.filter(function (parentFlatname) {
- var parentNode = getNode(parentFlatname)
- if (!parentNode) return false
- return parentNode.package.dependencies[moduleName(node)] ||
- (parentNode.package.devDependencies && parentNode.package.devDependencies[moduleName(node)])
- })
- requiredBy = requiredByNames.map(getNode)
-
- node.requiredBy = requiredBy
-
- if (!requiredBy.length) return
+ if (!node.requiredBy.length) return
- if (node.parent) node.parent.children = without(node.parent.children, node)
+ if (node.parent) {
+ // If a node is a cycle that never reaches the root of the logical
+ // tree then we'll leave it attached to the root, or else it
+ // would go missing. Further we'll note that this is the node in the
+ // cycle that we picked arbitrarily to be the one attached to the root.
+ // others will fall
+ if (isDisconnectedCycle(node)) {
+ node.cycleTop = true
+ // Nor do we want to disconnect non-cyclical extraneous modules from the tree.
+ } else if (node.requiredBy.length) {
+ // regular deps though, we do, as we're moving them into the capable
+ // hands of the modules that require them.
+ node.parent.children = without(node.parent.children, node)
+ }
+ }
- requiredBy.forEach(function (parentNode) {
+ node.requiredBy.forEach(function (parentNode) {
parentNode.children = union(parentNode.children, [node])
})
- if (node.package._requiredBy.some(function (nodename) { return nodename[0] === '#' })) {
- tree.children = union(tree.children, [node])
- }
})
return tree
}
@@ -70,18 +82,27 @@ function translateTree_ (tree, seen) {
tree.children.forEach(function (child) {
pkg.dependencies[moduleName(child)] = translateTree_(child, seen)
})
- Object.keys(tree.missingDeps).forEach(function (name) {
+
+ function markMissing (name, requiredBy) {
if (pkg.dependencies[name]) {
+ if (pkg.dependencies[name].missing) return
pkg.dependencies[name].invalid = true
pkg.dependencies[name].realName = name
pkg.dependencies[name].extraneous = false
} else {
pkg.dependencies[name] = {
- requiredBy: tree.missingDeps[name],
+ requiredBy: requiredBy,
missing: true,
optional: !!pkg.optionalDependencies[name]
}
}
+ }
+
+ Object.keys(tree.missingDeps).forEach(function (name) {
+ markMissing(name, tree.missingDeps[name])
+ })
+ Object.keys(tree.missingDevDeps).forEach(function (name) {
+ markMissing(name, tree.missingDevDeps[name])
})
var checkForMissingPeers = (tree.parent ? [] : [tree]).concat(tree.children)
checkForMissingPeers.filter(function (child) {