Skip to content
This repository has been archived by the owner on Jan 20, 2022. It is now read-only.

Do not conflict on meta-peers that will not be replaced #165

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 29 additions & 13 deletions lib/arborist/build-ideal-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -1339,20 +1339,36 @@ This is a one-time fix-up, please be patient...
// If strict or ours, conflict. Otherwise, keep.
if (isSource) {
// check to see if the current module could go deeper in the tree
const peerSet = getPeerSet(current)
let canReplace = true
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.
for (const edge of p.edgesIn) {
if (peerSet.has(edge.from))
continue

// only respect valid edges, however, since we're likely trying
// to fix the very one that's currently broken!
if (edge.from === target && edge.valid) {
canReplace = false
break OUTER
// only do this check when we're placing peers. when we're placing
// the original in the source, we know that the edge from the source
// is the thing we're trying to place, so its peer set will need to be
// 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.
for (const edge of p.edgesIn) {
if (peerSet.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) {
const rep = dep.parent.children.get(edge.name)
const override = rep && ([...rep.edgesIn].some(e => !e.valid))
if (!rep || !rep.satisfies(edge) || override) {
canReplace = false
break OUTER
}
}
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions lib/arborist/load-actual.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,12 @@ module.exports = cls => class ActualLoader extends cls {
})
if (meta.loadedFromDisk) {
this[_actualTree].meta = meta
meta.add(this[_actualTree])
return this[_loadActualVirtually]({ root })
} else {
const meta = await Shrinkwrap.load({
path: this[_actualTree].path,
})
this[_actualTree].meta = meta
meta.add(this[_actualTree])
return this[_loadActualActually]({ root, ignoreMissing })
}
}
Expand Down
3 changes: 1 addition & 2 deletions lib/arborist/load-virtual.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ module.exports = cls => class VirtualLoader extends cls {
}

async [loadFromShrinkwrap] (s, root) {
root.meta = s
// root is never any of these things, but might be a brand new
// baby Node object that never had its dep flags calculated.
root.extraneous = false
Expand All @@ -80,7 +79,7 @@ module.exports = cls => class VirtualLoader extends cls {
root.devOptional = false
root.peer = false
this[checkRootEdges](s, root)
s.add(root)
root.meta = s
this.virtualTree = root
const {links, nodes} = this[resolveNodes](s, root)
await this[resolveLinks](links, nodes)
Expand Down
27 changes: 16 additions & 11 deletions lib/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const _global = Symbol.for('global')
const _workspaces = Symbol('_workspaces')
const _explain = Symbol('_explain')
const _explanation = Symbol('_explanation')
const _meta = Symbol('_meta')

const relpath = require('./relpath.js')
const consistentResolve = require('./consistent-resolve.js')
Expand Down Expand Up @@ -175,13 +176,13 @@ class Node {
this.edgesIn = new Set()
this.edgesOut = new Map()

// only relevant for the root and top nodes
this.meta = meta

// have to set the internal package ref before assigning the parent,
// because this.package is read when adding to inventory
this[_package] = pkg

// only relevant for the root and top nodes
this.meta = meta

// Note: this is _slightly_ less efficient for the initial tree
// building than it could be, but in exchange, it's a much simpler
// algorithm.
Expand Down Expand Up @@ -226,6 +227,16 @@ class Node {
this[_loadDeps]()
}

get meta () {
return this[_meta]
}

set meta (meta) {
this[_meta] = meta
if (meta)
meta.add(this)
}

get global () {
return this.root[_global]
}
Expand Down Expand Up @@ -358,19 +369,13 @@ class Node {
if (edge)
why.dependents.push(edge.explain(seen))
else {
// if we have an edge from the root, just show that, and stop there
// no need to go deeper, because it doesn't provide much more value.
// ignore invalid edges, since those aren't satisfied by this thing,
// and are not keeping it held in this spot anyway.
const edges = []
for (const edge of this.edgesIn) {
if (!edge.valid && !edge.from.isRoot)
continue

if (edge.from.isRoot) {
edges.length = 0
edges.push(edge)
break
}

edges.push(edge)
}
for (const edge of edges)
Expand Down
Loading