Skip to content
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

Merged
merged 2 commits into from
Jul 10, 2017

Conversation

kaylie-alexa
Copy link
Member

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
screen shot 2017-07-09 at 5 16 40 pm

AFTER
screen shot 2017-07-09 at 5 17 43 pm

Eslint behavior is the same as before

screen shot 2017-07-09 at 5 26 30 pm

@@ -380,15 +379,15 @@ export default class PackageLinker {
}
}

determineTopLevelBinLinks(flatTree: HoistManifestTuples): HoistManifestTuples {
determineTopLevelBinLinks(flatTree: HoistManifestTuples): Array<[string, Manifest]> {
Copy link
Member

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?

Copy link
Member Author

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.

@arcanis arcanis merged commit 3c9b51e into yarnpkg:master Jul 10, 2017
@arcanis
Copy link
Member

arcanis commented Jul 10, 2017

I've merged this PR since it would be nice to ship it along with the 0.28.1 :)

arcanis pushed a commit that referenced this pull request Jul 10, 2017
* fix links to only search at root level

* remove outdated commment
Copy link
Member

@BYK BYK left a 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>> {
Copy link
Member

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)

Copy link
Member Author

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);
Copy link
Member

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 :(

@rally25rs
Copy link
Contributor

rally25rs commented Jul 10, 2017

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 determineTopLevelBinLinks() is used to "determine which transient deps should be linked at the top level (/node_modules/.bin)", not to determine the top-level modules.

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...

Copy link
Member Author

@kaylie-alexa kaylie-alexa left a 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>> {
Copy link
Member Author

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);
}
Copy link
Member Author

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]> {
Copy link
Member Author

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.

@kaylie-alexa kaylie-alexa deleted the fix-bin-links branch July 11, 2017 06:25
@BYK
Copy link
Member

BYK commented Jul 11, 2017

sorry to get to the comments after PR closed!

No worries at all :)

deepsweet added a commit to start-runner/webpack that referenced this pull request Jul 22, 2017

Unverified

This user has not yet uploaded their public signing key.
deepsweet added a commit to start-runner/webpack-dev-server that referenced this pull request Jul 22, 2017

Unverified

This user has not yet uploaded their public signing key.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants