-
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
fix(linker): Fix yarn removing linked deps during link stage #4757
Conversation
… a linked dependency in package-linker.js Fixes yarn removing linked deps when installing or updating.
This change will increase the build size from 9.94 MB to 9.94 MB, an increase of 935 bytes (0%)
|
This change will decrease the build size from 9.94 MB to 9.94 MB, a decrease of 277 bytes (0%)
|
Note to myself, found a bug, yarn throws when a linked module's destination no longer exists, try catch? Fixed with: f4ed169 |
Provides a helpful warning and removes the offending module.
package.json
Outdated
@@ -1,7 +1,7 @@ | |||
{ | |||
"name": "yarn", | |||
"installationMethod": "unknown", | |||
"version": "1.2.1", | |||
"version": "1.2.2", |
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 unnecessary, the core team will bump the patch version when they are ready to release it
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 will revert this. Thank you.
@@ -304,8 +304,15 @@ export default class PackageLinker { | |||
const stat = await fs.lstat(entryPath); | |||
|
|||
if (stat.isSymbolicLink()) { | |||
const packageName = entry; | |||
linkTargets.set(packageName, await fs.readlink(entryPath)); | |||
try { |
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.
eslint errors on this.
Please run yarn run prettier
to autoformat the code
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.
Will do, and will check with the linter before committing. Thanks.
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.
Done. yarn lint completed.
{}, | ||
'install-dont-overwrite-linked', | ||
async (config): Promise<void> => { | ||
const dependencyPath = path.join(config.cwd, 'node_modules', 'fake-dependency'); |
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 don't understand the test.
i would expect that you would run a link command and then install should not overwrite it?
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 tips.
- You probably want to setup several folders for the test: a linked package.json and the linker package.json
- here is how link command is used in tests https://github.com/yarnpkg/yarn/blob/master/__tests__/commands/link.js#L35
- after linking you can check that link exists
- after that run install command and check that link was not destroyed
https://github.com/yarnpkg/yarn/blob/master/__tests__/commands/install/integration.js#L93
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.
Thank you! Yeah I dont get this test either. I copied it from the other one that checks if scoped links are maintained, I suspect that one is faulty too.
I'll update both with your suggestions here.
…ith the existing code Added the try catch for possible missing linked module targets to the scoped logic to mirror the regular packages Simplified the fixture for testing that yarn doesn't remove linked deps Moved runLink to helpers to be able to use it on other test suites
I re-wrote the tests with @bestander suggestions and tested them with the old code to make sure they break. Both tests for scoped and regular packages now fail correctly and pass correctly with the new code. |
…ined and not just falsy.
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.
See #3288 (comment) for my explanation of the problem.
I think explaining the reason for the change in the commit log would be great for any future readers. I think this is important since there are no comments in the code (and I'd argue comments are not necessary) but the reason for the change is important.
cwd = path.join(cwd, name.cwd); | ||
// if source wasn't set then assume we were given a complete path | ||
if (typeof source === 'undefined') { | ||
cwd = typeof name !== 'string' ? name.cwd : await fs.makeTempDir(); |
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.
These nested conditionals are a bit confusing. Do you think we can find a cleaner way to do this?
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.
they are, if I take this one off which is unnecessary then flow complains. I will take a look in another PR see if I can can come up with a clearer logic and put more comments.
@@ -1,24 +1,12 @@ | |||
/* @flow */ | |||
|
|||
import {run as buildRun} from './_helpers.js'; | |||
import {run as link} from '../../src/cli/commands/link.js'; | |||
import {runLink} from './_helpers.js'; |
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.
Nice refactor.
@@ -317,7 +322,13 @@ export default class PackageLinker { | |||
|
|||
if (stat2.isSymbolicLink()) { | |||
const packageName = `${scopeName}/${entry2}`; | |||
linkTargets.set(packageName, await fs.readlink(entryPath2)); | |||
try { |
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 repeated code kind of calls for a helper function.
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 was thinking about it. But I didn't want to confuse this too much. There's also a todo comment to merge the link targets logic here with logic in another part of the code. I can take a look after and make another PR.
LGTM. @bestander approve and merge at will! |
Do we have a list for these? |
Great job, @gandazgul! |
It works perfectly, npm has this problem since the beginning of version 3, thank you very much! |
@bestander thank you, happy to help. When do you think this will be released? My team is anxious to upgrade yarn to the latest version. |
…#4757) **Summary** Actual fix: changed fs.readlink to fs.realpath when checking if a symlink is a linked dependency in package-linker.js This fixes yarn removing linked deps when installing or updating. Fixes yarnpkg#3288, fixes yarnpkg#4770, fixes yarnpkg#4635, fixes yarnpkg#4603. Potential fix for yarnpkg#3202. **Test plan** See yarnpkg#3288 (comment) for repro steps. See yarnpkg#3288 (comment) for my explanation of the problem. With a real world test scenario this works, but I'm unable to have it break from a unit test. I added a test in the integration suite but with the bug added back in it still passes because both generated paths are identical. I would like some help with the unit test.
@gandazgul it is due to be released any day soon according to recent release history. |
This PR hasn't fixed this problem entirely. I'm still facing this issue. NodeJS version: I do the |
Summary
Actual fix: changed fs.readlink to fs.realpath when checking if a symlink is a linked dependency in package-linker.js This fixes yarn removing linked deps when installing or updating.
Fixes #3288, fixes #4770, fixes #4635, fixes #4603.
Potential fix for #3202.
Test plan
See #3288 (comment) for repro steps.
See #3288 (comment) for my explanation of the problem.
With a real world test scenario this works, but I'm unable to have it break from a unit test. I added a test in the integration suite but with the bug added back in it still passes because both generated paths are identical. I would like some help with the unit test.