-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prioritize bin links at the root level #3877
Conversation
@@ -380,15 +379,15 @@ export default class PackageLinker { | |||
} | |||
} | |||
|
|||
determineTopLevelBinLinks(flatTree: HoistManifestTuples): HoistManifestTuples { | |||
determineTopLevelBinLinks(flatTree: HoistManifestTuples): Array<[string, Manifest]> { |
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.
Does using HoistManifestTuples
break something?
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.
No but this function was only used once below, where it just pulled out the Manifest (pkg
), and I thought it'd be better to reduce the size of object being passed from the HoistManifest. If you think we need to keep the previous signature, happy to send a refactor PR.
I've merged this PR since it would be nice to ship it along with the 0.28.1 :) |
* fix links to only search at root level * remove outdated commment
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 amazing, thank you!
@@ -20,6 +21,36 @@ async function linkAt(config, ...relativePath): Promise<string> { | |||
} | |||
} | |||
|
|||
function execCommand(cwd: string, binPath: Array<string>, args: Array<string>): Promise<Array<?string>> { |
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.
I remember seeing a function like this in somewhere else. May be we should start using something like https://yarnpkg.com/en/package/jsinspect to help catch these automatically? (also it would help me be sure instead of saying "I suspect" :D)
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.
Yeah I copied it over from the test file that was testing run
command and tweaked it for my purpose. I think it was out of scope for this diff but the right thing to do is probably have a place to store and dedupe all of these similar functions (you're right--I've definitely seen it being reused in several other test files!) inside some shared test utils folder.
On a separate note, that looks like a cool tool! I think I've seen similar functions under src/ which is probably more important to refactor :)
@@ -106,7 +106,7 @@ test('Produces valid destination paths for scoped modules', () => { | |||
_reference: (({}: any): PackageReference), | |||
}: any): Manifest); | |||
|
|||
const info = new HoistManifest(key, parts, pkg, '', true, false); | |||
const info = new HoistManifest(key, parts, pkg, '', true, true, false); |
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.
We really should convert this method to accept and options object instead of boolean arguments. No idea what's happening here :(
Oh man, this .bin link thing has been such a pain... So the bin linking behavior in <=0.24 was to only link the top-level bins. In 3535 (which went out as part of v0.25) I started linking the transient deps, but didn't want to change too much code and dig myself a hole I couldn't get out of, so based it on the order of the flat-hoiseted tree, which is at least a deterministic ordering. However I also left the old/existing logic in place that had already been linking just the direct dependencies, so that no matter what dep was first in the flat-hoist list, which could be a transient dep, it would get overridden by the direct dep, just like <=v0.24 had linked. 3332 removed that last part, so would certainly result in transient deps being .bin linked instead of direct-deps. I think that might be a naming issue on my part that caused some confusion. The function I hadn't seen 3332 when it got merged, but it probably indicates that <=v0.24 was linking wrong bins too, since the code that got deleted there was the original (before I messed with it) code that did the bin links for the direct dependencies. I hope you're attempt to fix these bin links has better luck than mine... |
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.
sorry to get to the comments after PR closed!
@@ -20,6 +21,36 @@ async function linkAt(config, ...relativePath): Promise<string> { | |||
} | |||
} | |||
|
|||
function execCommand(cwd: string, binPath: Array<string>, args: Array<string>): Promise<Array<?string>> { |
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.
Yeah I copied it over from the test file that was testing run
command and tweaked it for my purpose. I think it was out of scope for this diff but the right thing to do is probably have a place to store and dedupe all of these similar functions (you're right--I've definitely seen it being reused in several other test files!) inside some shared test utils folder.
On a separate note, that looks like a cool tool! I think I've seen similar functions under src/ which is probably more important to refactor :)
// | ||
for (const info of infos) { | ||
this.hoist(info); | ||
} |
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.
fyi, this was unrelated, (so is the for loop below) but the second iteration really didn't seem necessary. lmk if they're need for some reason.
@@ -380,15 +379,15 @@ export default class PackageLinker { | |||
} | |||
} | |||
|
|||
determineTopLevelBinLinks(flatTree: HoistManifestTuples): HoistManifestTuples { | |||
determineTopLevelBinLinks(flatTree: HoistManifestTuples): Array<[string, Manifest]> { |
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.
No but this function was only used once below, where it just pulled out the Manifest (pkg
), and I thought it'd be better to reduce the size of object being passed from the HoistManifest. If you think we need to keep the previous signature, happy to send a refactor PR.
No worries at all :) |
Summary
This is a fix for #3801
It seems like there's some history behind this issue, namely
#3310, which 1) looked through all transient dependencies, 2) linked them to node_modules/.bin, then 3) overrode them with any top level dependencies
#3545, removed the last part from above, which I assume was due to it incorrectly detecting what is actually at top level.
So now, the flat tree from
PackageHoister
gives us a list of all the bin paths that are hoisted to top level, but will include same names if their version ranges don't match, since hoisted has a different meaning from being added as an actual top level dependency. The latest implementation before this PR relied on the whatever order it came from and satisfied the bin link with the first one it found.So solution was to still allow for the override to happen when the package has
isDirectRequired
equal to true.@bestander @rally25rs feel free to jump in with any additional knowledge :)
Test plan
Added tests to actually read versions of the bin links. It passes all the previous test cases with eslint, and passes the new test with uglifyjs bin that fails on master. (Got lucky that we already had uglifyjs tarball in the test fixtures!)
BEFORE

AFTER

Eslint behavior is the same as before