Skip to content
Open
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
48 changes: 18 additions & 30 deletions workspaces/arborist/lib/arborist/build-ideal-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ This is a one-time fix-up, please be patient...
tree: pd,
getChildren: pd => pd.children,
visit: pd => {
const { placed, edge, canPlace: cpd } = pd
const { placed, edge, canPlace: cpd, parent } = pd
// if we didn't place anything, nothing to do here
if (!placed) {
return
Expand Down Expand Up @@ -1011,25 +1011,22 @@ This is a one-time fix-up, please be patient...
return
}

// lastly, also check for the missing deps of the node we placed,
// and any holes created by pruning out conflicted peer sets.
// lastly, also check for the missing deps of the node we placed, and any holes created by pruning out conflicted peer sets.
this.#depsQueue.push(placed)
for (const dep of pd.needEvaluation) {
this.#depsSeen.delete(dep)
this.#depsQueue.push(dep)
}

// pre-fetch any problem edges, since we'll need these soon
// if it fails at this point, though, don't worry because it
// may well be an optional dep that has gone missing. it'll
// fail later anyway.
// if it fails at this point, though, don't worry because it may well be an optional dep that has gone missing
// it'll fail later anyway
for (const e of this.#problemEdges(placed)) {
// XXX This is somehow load bearing. This makes tests that print
// the ideal tree of a tree with tarball dependencies fail. This
// can't be changed or removed till we figure out why
// XXX This is somehow load bearing. This makes tests that print the ideal tree of a tree with tarball dependencies fail
// This can't be changed or removed till we figure out why
// The test is named "tarball deps with transitive tarball deps"
promises.push(() =>
this.#fetchManifest(npa.resolve(e.name, e.spec, fromPath(placed, e)))
this.#fetchManifest(npa.resolve(e.name, e.spec, fromPath(placed, e)), parent)
.catch(() => null)
)
}
Expand All @@ -1047,26 +1044,18 @@ This is a one-time fix-up, please be patient...
return this.#buildDepStep()
}

// loads a node from an edge, and then loads its peer deps (and their
// peer deps, on down the line) into a virtual root parent.
// loads a node from an edge, and then loads its peer deps (and their peer deps, on down the line) into a virtual root parent.
async #nodeFromEdge (edge, parent_, secondEdge, required) {
// create a virtual root node with the same deps as the node that
// is requesting this one, so that we can get all the peer deps in
// a context where they're likely to be resolvable.
// Note that the virtual root will also have virtual copies of the
// targets of any child Links, so that they resolve appropriately.
// create a virtual root node with the same deps as the node that is requesting this one, so that we can get all the peer deps in a context where they're likely to be resolvable.
// Note that the virtual root will also have virtual copies of the targets of any child Links, so that they resolve appropriately.
const parent = parent_ || this.#virtualRoot(edge.from)

const spec = npa.resolve(edge.name, edge.spec, edge.from.path)
const first = await this.#nodeFromSpec(edge.name, spec, parent, edge)

// we might have a case where the parent has a peer dependency on
// `foo@*` which resolves to v2, but another dep in the set has a
// peerDependency on `foo@1`. In that case, if we force it to be v2,
// we're unnecessarily triggering an ERESOLVE.
// If we have a second edge to worry about, and it's not satisfied
// by the first node, try a second and see if that satisfies the
// original edge here.
// we might have a case where the parent has a peer dependency on `foo@*` which resolves to v2, but another dep in the set has a peerDependency on `foo@1`.
// In that case, if we force it to be v2, we're unnecessarily triggering an ERESOLVE.
// If we have a second edge to worry about, and it's not satisfied by the first node, try a second and see if that satisfies the original edge here.
const spec2 = secondEdge && npa.resolve(
edge.name,
secondEdge.spec,
Expand Down Expand Up @@ -1210,11 +1199,12 @@ This is a one-time fix-up, please be patient...
return problems
}

async #fetchManifest (spec) {
async #fetchManifest (spec, parent) {
const options = {
...this.options,
avoid: this.#avoidRange(spec.name),
fullMetadata: true,
_isRoot: parent?.isProjectRoot || parent?.isWorkspace,
}
// get the intended spec and stored metadata from yarn.lock file,
// if available and valid.
Expand All @@ -1231,10 +1221,8 @@ This is a one-time fix-up, please be patient...
}

async #nodeFromSpec (name, spec, parent, edge) {
// pacote will slap integrity on its options, so we have to clone
// the object so it doesn't get mutated.
// Don't bother to load the manifest for link deps, because the target
// might be within another package that doesn't exist yet.
// pacote will slap integrity on its options, so we have to clone the object so it doesn't get mutated.
// Don't bother to load the manifest for link deps, because the target might be within another package that doesn't exist yet.
const { installLinks, legacyPeerDeps } = this
const isWorkspace = this.idealTree.workspaces && this.idealTree.workspaces.has(spec.name)

Expand Down Expand Up @@ -1287,7 +1275,7 @@ This is a one-time fix-up, please be patient...

// spec isn't a directory, and either isn't a workspace or the workspace we have
// doesn't satisfy the edge. try to fetch a manifest and build a node from that.
return this.#fetchManifest(spec)
return this.#fetchManifest(spec, parent)
.then(pkg => new Node({ name, pkg, parent, installLinks, legacyPeerDeps }), error => {
error.requiredBy = edge.from.location || '.'

Expand Down
1 change: 1 addition & 0 deletions workspaces/arborist/lib/arborist/isolated-reifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ module.exports = cls => class IsolatedReifier extends cls {
...this.options,
resolved: node.resolved,
integrity: node.integrity,
// TODO _isRoot
})
const Arborist = this.constructor
const arb = new Arborist({ ...this.options, path: dir })
Expand Down
1 change: 1 addition & 0 deletions workspaces/arborist/lib/arborist/reify.js
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ module.exports = cls => class Reifier extends cls {
...this.options,
resolved: node.resolved,
integrity: node.integrity,
_isRoot: node.parent?.isProjectRoot || node.parent?.isWorkspace,
})
// store nodes don't use Node class so node.package doesn't get updated
if (node.isInStore) {
Expand Down
Loading