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

Use alternate method of generating global bin shims #6959

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

ArcanoxDragon
Copy link
Contributor

Summary

PR #6954 is a band-aid to a deeper problem with generating global bin shims. Currently, Yarn essentially makes a "shim shim" on Windows due to older versions of Node not supporting symbolic links. This worked fine with the sh and cmd shims, but the new @zkochan/cmd-shim@3.0.0 PowerShell shims are written a bit differently and broke when a "shim of a shim" was created for one.

The old method of Yarn involved traversing Yarn's "Data/global/node_modules/.bin" directory after a global install operation, and for each shim file that was found, cmd-shim was called to create a "shim shim" in Yarn's "bin" folder. This had an unfortunate side effect of creating shim, shim.cmd, and shim.ps1 for each global shim on Windows, meaning one would end up with every permutation of extensions, such as shim.ps1.ps1, and shim.ps1 would actually contain the extensionless bash shim. Previous versions of Yarn worked around this by copying shim.cmd.cmd to shim.cmd but this was a band-aid at best.

The new method implemented by this PR fixes both #6902 and #6958 by changing the way global shims are generated. Instead of creating shims in <yarn prefix>/bin which point to <yarn prefix>/Data/global/node_modules/.bin, Yarn will now parse the global lockfile after every global operation and find the top-level binaries that would be added to <yarn prefix>/Data/global/node_modules/.bin and create a new top-level shim in <yarn prefix>/bin pointing directly to the actual binary path in the providing package's node_modules folder.

I have tested this on Windows 10 using the version of PowerShell included with Windows, and the issue originally documented in #6902 is fixed by the changes made in this PR.

Test plan

A test was added to __tests__/commands/global.js to ensure the proper binaries are created on Windows. The existing global tests should cover regression testing. I have tested this PR locally and successfully used a global binary installed with my local compiled version of Yarn without issue.

@buildsize
Copy link

buildsize bot commented Jan 24, 2019

File name Previous Size New Size Change
yarn-[version].noarch.rpm 1.11 MB 1.11 MB 447 bytes (0%)
yarn-[version].js 4.47 MB 4.48 MB 1.57 KB (0%)
yarn-legacy-[version].js 4.67 MB 4.67 MB 1.76 KB (0%)
yarn-v[version].tar.gz 1.12 MB 1.12 MB -987 bytes (0%)
yarn_[version]all.deb 816.37 KB 816.69 KB 328 bytes (0%)

@@ -159,18 +160,38 @@ async function initUpdateBins(config: Config, reporter: Reporter, flags: Object)
}
}

// add new bins
for (const src of afterBins) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be fixed simply but filtering afterBins here to make sure we don't iterate over .ps1 and .cmd files?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would still be creating shims of shims. It would fix the .ps1.cmd/.cmd.ps1/etc issue, but it would not fix the problem of there being shims pointing to shims pointing to binaries. cmd-shim does not work correctly when such a condition occurs, at least not with PowerShell.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Longer explanation:

The cmd-shim package looks at the shebang of the program it's targeting to figure out what to write into the shim. This works fine for bash and cmd, because for bash it will always be either node or sh and for cmd it will always be either node.exe or cmd.exe. PowerShell breaks because the shebang on the PowerShell shim ends up referencing pwsh.exe, which is the binary for PowerShell Core, even when PowerShell Core is not installed. When a shim is created to a PowerShell shim, it automatically points to pwsh from the shebang, which causes problems if PowerShell Core isn't installed on the system (the version of PS that comes with Windows is powershell.exe, not pwsh.exe, and PowerShell Core is a separate installation).

I suppose it might be worth it to file an issue with cmd-shim to write the correct shebang to PowerShell shims, but I also would have to argue that it's still best to have one layer of shims if possible instead of shims-pointing-to-shims.

@MLoughry
Copy link

Is there any traction on this?

@ArcanoxDragon
Copy link
Contributor Author

Rebased to fix conflicts due to my other PR; should be a clean merge now for if this is approved at some point

@Daniel15
Copy link
Member

Seems reasonable to me... @arcanis what do you think?

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