-
Notifications
You must be signed in to change notification settings - Fork 63
fix running unchanged links lifecycle scripts #290
fix running unchanged links lifecycle scripts #290
Conversation
Previously, the `node.isDescendantOf` method would only check for direct parents of that node, this may cause unexpected side effects on build ideal tree and reify when working with linked dependencies. This change modifies it so that `node.isDescendantOf` now looks at `node.resolveParent` (making sure `fsParents` are included in the lookup) to determine wether that node is a descendant of another. This also made it possible to refactor the logic that checks for an `external` dep in build-ideal-tree to use `node.isDescendantOf` instead of a regex check in the realpath of the link. Relates to: npm#290 Relates to: npm/cli#2900
Previously, the `node.isDescendantOf` method would only check for direct parents of that node, this may cause unexpected side effects on build ideal tree and reify when working with linked dependencies. This change modifies it so that `node.isDescendantOf` now looks at `node.resolveParent` (making sure `fsParents` are included in the lookup) to determine wether that node is a descendant of another. This also made it possible to refactor the logic that checks for an `external` dep in build-ideal-tree to use `node.isDescendantOf` instead of a regex check in the realpath of the link. Relates to: npm/cli#2900
ae6c2af
to
2b35be1
Compare
Users expect workspaces (or regular linked deps) to run their prepare lifecycle script on every reify, since it's often used as some form of compilation step and should run even though that node hasn't changed. Fixes: npm/cli#2900
2b35be1
to
aedbc8c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Fixes a bug, improves the readability in a few places, and incidentally makes deduping more efficient. +1, but should maybe get a review from someone who wasn't pairing on it, probably.
// skip links that only live within node_modules as they are most | ||
// likely managed by packages we installed, we only want to rebuild | ||
// unchanged links we directly manage | ||
if (node.isLink && node.target.fsTop === tree) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could also consider || !this.diff.unchanged.includes(node.target.fsTop)
to capture the "did not change link, but did change link's fsParent" use case. (Separate issue from the one this commit addresses, can come later.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a few clarifying questions, but i think this all makes sense
@@ -914,7 +914,7 @@ This is a one-time fix-up, please be patient... | |||
await Promise.all(promises) | |||
|
|||
for (const { to } of node.edgesOut.values()) { | |||
if (to && to.isLink) | |||
if (to && to.isLink && to.target) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can something be a link and not have a target?
@@ -1421,7 +1421,7 @@ This is a one-time fix-up, please be patient... | |||
// prune anything deeper in the tree that can be replaced by this | |||
if (this.idealTree) { | |||
for (const node of this.idealTree.inventory.query('name', newDep.name)) { | |||
if (node.isDescendantOf(target)) | |||
if (!node.isTop && node.isDescendantOf(target)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this extra check is because it's possible for isDescendantOf
to return true when the node isTop
? when is that the case? i'm wondering if it's worth putting a comment here explaining why both tests are needed, because i would sure assume that a node couldn't be both the descendant of a target and a top node
@@ -1876,7 +1876,8 @@ This is a one-time fix-up, please be patient... | |||
if (link.root !== this.idealTree) | |||
continue | |||
|
|||
const external = /^\.\.(\/|$)/.test(relpath(this.path, link.realpath)) | |||
const tree = this.idealTree.target || this.idealTree | |||
const external = !link.target.isDescendantOf(tree) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is such a better test than the regex on the relative path, i love it
const filter = node => | ||
node.isDescendantOf(this.idealTree) && | ||
node.top.isProjectRoot && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is also much more clear to me than the old code
Users expect workspaces (or regular linked deps) to run their prepare
lifecycle script on every reify, since it's often used as some form of
compilation step and should run even though that node hasn't changed.
References
Fixes: npm/cli#2900