Skip to content

Instantly share code, notes, and snippets.

@isaacs
Created April 28, 2021 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isaacs/3a1c20f9d6ff9e75356cba5bd9597d5d to your computer and use it in GitHub Desktop.
Save isaacs/3a1c20f9d6ff9e75356cba5bd9597d5d to your computer and use it in GitHub Desktop.
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