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

fix(linker): Fix yarn removing linked deps during link stage #4757

Merged
merged 6 commits into from
Oct 26, 2017

Conversation

gandazgul
Copy link
Contributor

@gandazgul gandazgul commented Oct 23, 2017

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.

… a linked dependency in package-linker.js

Fixes yarn removing linked deps when installing or updating.
@buildsize
Copy link

buildsize bot commented Oct 23, 2017

This change will increase the build size from 9.94 MB to 9.94 MB, an increase of 935 bytes (0%)

File name Previous Size New Size Change
yarn-[version].noarch.rpm 859.47 KB 859.44 KB -31 bytes (0%)
yarn-[version].js 3.78 MB 3.78 MB 369 bytes (0%)
yarn-legacy-[version].js 3.83 MB 3.83 MB 586 bytes (0%)
yarn-v[version].tar.gz 865.09 KB 865.17 KB 85 bytes (0%)
yarn_[version]all.deb 654.12 KB 654.05 KB -74 bytes (0%)

@buildsize
Copy link

buildsize bot commented Oct 23, 2017

This change will decrease the build size from 9.94 MB to 9.94 MB, a decrease of 277 bytes (0%)

File name Previous Size New Size Change
yarn-[version].noarch.rpm 859.47 KB 859.34 KB -132 bytes (0%)
yarn-[version].js 3.78 MB 3.78 MB -181 bytes (0%)
yarn-legacy-[version].js 3.83 MB 3.83 MB 36 bytes (0%)
yarn-v[version].tar.gz 865.09 KB 865 KB -86 bytes (0%)
yarn_[version]all.deb 654.12 KB 654.2 KB 86 bytes (0%)

@gandazgul
Copy link
Contributor Author

gandazgul commented Oct 23, 2017

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",
Copy link
Member

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

Copy link
Contributor Author

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

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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

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?

Copy link
Member

Choose a reason for hiding this comment

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

A few tips.

  1. You probably want to setup several folders for the test: a linked package.json and the linker package.json
  2. here is how link command is used in tests https://github.com/yarnpkg/yarn/blob/master/__tests__/commands/link.js#L35
  3. after linking you can check that link exists
  4. 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

Copy link
Contributor Author

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
@gandazgul
Copy link
Contributor Author

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.

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.

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

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?

Copy link
Contributor Author

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

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

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.

Copy link
Contributor Author

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.

@BYK
Copy link
Member

BYK commented Oct 26, 2017

LGTM. @bestander approve and merge at will!

@BYK BYK changed the title Fixed yarn removing linked deps when installing or upgrading fix(linker): Fix yarn removing linked deps during link stage Oct 26, 2017
@BYK
Copy link
Member

BYK commented Oct 26, 2017

Fixes: #3288 and other reported issues relating to linked deps being removed.

Do we have a list for these?

@gandazgul
Copy link
Contributor Author

gandazgul commented Oct 26, 2017

@BYK I found these:

#4770
#4635
#4603

Thanks for approving the PR. :)

@BYK BYK merged commit 9b0e7bb into yarnpkg:master Oct 26, 2017
@bestander
Copy link
Member

Great job, @gandazgul!
Thanks for helping with review, @BYK

@bertho-zero
Copy link
Contributor

It works perfectly, npm has this problem since the beginning of version 3, thank you very much!

@gandazgul
Copy link
Contributor Author

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

joaolucasl pushed a commit to joaolucasl/yarn that referenced this pull request Oct 27, 2017
…#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.
@bestander
Copy link
Member

@gandazgul it is due to be released any day soon according to recent release history.
In the mean time feel free to use nightly builds https://yarnpkg.com/en/docs/nightly

@rdsedmundo
Copy link

This PR hasn't fixed this problem entirely. I'm still facing this issue.

NodeJS version: 10.0.0
Yarn version: 1.6.0

I do the yarn link package and I can confirm it works by executing ls -l node_modules/package and seeing the symlink pointing to the right folder. After I run yarn install though and execute the ls -l node_modules/package command again, the symlink is removed and it does use the package from what is on package.json again (it's a Git URL by the way, don't know if it makes difference).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants