Created
April 28, 2021 00:12
-
-
Save isaacs/3a1c20f9d6ff9e75356cba5bd9597d5d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/arborist/build-ideal-tree.js b/lib/arborist/build-ideal-tree.js | |
index 49b21ca2..d2ed2b35 100644 | |
--- a/lib/arborist/build-ideal-tree.js | |
+++ b/lib/arborist/build-ideal-tree.js | |
@@ -1631,52 +1631,66 @@ This is a one-time fix-up, please be patient... | |
// placed here as well. the virtualRoot already has the appropriate | |
// overrides applied. | |
if (peerEntryEdge) { | |
- const peerSet = getPeerSet(current) | |
- OUTER: for (const p of peerSet) { | |
- // if any have a non-peer dep from the target, or a peer dep if | |
- // the target is root, then cannot safely replace and dupe deeper. | |
+ const currentPeerSet = getPeerSet(current) | |
+ | |
+ // We are effectively replacing currentPeerSet with newPeerSet | |
+ // If there are any non-peer deps coming into the currentPeerSet, | |
+ // which are currently valid, and are from the target, then that | |
+ // means that we have to ensure that they're not going to be made | |
+ // invalid by putting the newPeerSet in place. | |
+ // If the edge comes from somewhere deeper than the target, then | |
+ // that's fine, because we'll create an invalid edge, detect it, | |
+ // and duplicate the node further into the tree. | |
+ // loop through the currentPeerSet checking for valid edges on | |
+ // the members of the peer set which will be made invalid. | |
+ const targetEdges = new Set() | |
+ for (const p of currentPeerSet) { | |
for (const edge of p.edgesIn) { | |
- if (peerSet.has(edge.from)) | |
+ // edge from within the peerSet, ignore | |
+ if (currentPeerSet.has(edge.from)) | |
continue | |
- | |
- // only respect valid edges, however, since we're likely trying | |
- // to fix the very one that's currently broken! If the virtual | |
- // root's replacement is ok, and doesn't have any invalid edges | |
- // indicating that it was an overridden peer, then ignore the | |
- // conflict and continue. If it WAS an override, then we need | |
- // to get the conflict here so that we can decide whether to | |
- // accept the current dep node, clobber it, or fail the install. | |
- if (edge.from === target && edge.valid) { | |
- // replacement from virtual root | |
- const rep = dep.parent.children.get(edge.name) | |
- // not going to replace it, so make sure it won't cause problems | |
- // if the things we ARE replacing are going to break the edges | |
- // for the thing that has to be here, then it's a conflict. | |
- if (!rep) { | |
- const current = edge.to | |
- for (const repEdge of current.edgesOut.values()) { | |
- const newRepDep = dep.parent.children.get(repEdge.name) | |
- if (repEdge.valid && newRepDep && !newRepDep.satisfies(repEdge)) { | |
- canReplace = false | |
- break OUTER | |
- } | |
- } | |
- continue | |
+ // only care about valid edges from target. | |
+ // edges from elsewhere can dupe if offended, invalid edges | |
+ // are already being fixed or will be later. | |
+ if (edge.from !== target || !edge.valid) | |
+ continue | |
+ targetEdges.add(edge) | |
+ } | |
+ } | |
+ debug.log('targetEdges', dep.name, targetEdges) | |
+ for (const edge of targetEdges) { | |
+ // see if we intend to replace this one anyway | |
+ const rep = dep.parent.children.get(edge.name) | |
+ const current = edge.to | |
+ if (!rep) { | |
+ debug.log('no rep', edge) | |
+ // this isn't one we're replacing. but it WAS included in the | |
+ // peerSet for some reason, so make sure that it's still | |
+ // ok with the replacements in the new peerSet | |
+ for (const curEdge of current.edgesOut.values()) { | |
+ const newRepDep = dep.parent.children.get(curEdge.name) | |
+ if (curEdge.valid && newRepDep && !newRepDep.satisfies(curEdge)) { | |
+ debug.log('not satisfied', curEdge, newRepDep) | |
+ canReplace = false | |
+ break | |
} | |
- | |
- // was said replacement an override already? | |
- const override = [...rep.edgesIn].some(e => !e.valid) | |
- // if we have a rep, and it's ok to put in this location, and | |
- // it's not already part of an override in the peerSet, then | |
- // we can continue with it. | |
- if (rep.satisfies(edge) && !override) | |
- continue | |
- | |
- // Otherwise, we cannot replace. | |
- canReplace = false | |
- break OUTER | |
} | |
+ continue | |
} | |
+ | |
+ debug.log('have replacement', rep) | |
+ | |
+ // was this replacement already an override of some sort? | |
+ const override = [...rep.edgesIn].some(e => !e.valid) | |
+ // if we have a rep, and it's ok to put in this location, and | |
+ // it's not already part of an override in the peerSet, then | |
+ // we can continue with it. | |
+ if (rep.satisfies(edge) && !override) | |
+ continue | |
+ // Otherwise, we cannot replace. | |
+ debug.log('cannot replace', edge, rep) | |
+ canReplace = false | |
+ break | |
} | |
} | |
if (canReplace) { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment