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

[rush] Fix for issue 1349 rush install fails for preferred version #1368

Merged
merged 6 commits into from
Jul 11, 2019

Conversation

apostolisms
Copy link
Contributor

@apostolisms apostolisms commented Jul 10, 2019

This is a fix for issue #1349

private _getValidDependencyVersion(dependencyVersion: string): string {
return semver.valid(dependencyVersion.split('/').pop()!) ?
dependencyVersion.split('/').pop()! :
dependencyVersion.split('_')[0]!;
Copy link
Contributor

Choose a reason for hiding this comment

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

For the else case, do we need to grab the last element on split('/') and then grab the first element on split('_')?

@@ -272,6 +272,12 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile {
return packageDescription;
}

private _getValidDependencyVersion(dependencyVersion: string): string {
return semver.valid(dependencyVersion.split('/').pop()!) ?
dependencyVersion.split('/').pop()! :
Copy link
Member

Choose a reason for hiding this comment

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

Extract dependencyVersion.split('/').pop()! into a variable so that it need not be computed twice?

@@ -272,6 +272,12 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile {
return packageDescription;
}

private _getValidDependencyVersion(dependencyVersion: string): string {
return semver.valid(dependencyVersion.split('/').pop()!) ?
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 think this is what you want. From that issue, it looks like the two formats we need to handle are:

  • /react-loadable/5.5.0/react@16.8.6
  • /react-loadable/5.5.0_react@16.8.6

(both matching react@16.8.6)

The dependencyVersion.split('/').pop() statement will return react@16.8.6, but semver.valid('react@16.8.6') returns null, always falling back to the dependencyVersion.split('_') statement.

I think this is what we want:

Suggested change
return semver.valid(dependencyVersion.split('/').pop()!) ?
if (dependencyVersion.indexOf('_') !== -1) {
// PNPM 3: the format looks like "/react-loadable/5.5.0_react@16.8.6"
return dependencyVersion.split('_').pop()!;
} else {
// PNPM 2: the format looks like "/react-loadable/5.5.0/react@16.8.6"
return dependencyVersion.split('/').pop()!;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@iclanton in PNP 2.x it seems like its coming in as:
/react-loadable/5.5.0 and
/react-loadable/5.5.0/react@16.8.6
and similarly for react-dom. So semver.valid('5.5.0') or semver.valid('16.8.6') passes

In pnpm 3.x it is consistently:
/react-loadable/5.5.0_react@16.8.6
/react-dom/16.8.6_react@16.8.6
and dependencyVersion.split('_')[0] will validate semver.valid('5.5.0')

If we use dependencyVersion.split('_').pop()!; it will fail in pnpm 3.x because it will try to validate react@16.8.6

I think we need to return dependencyVersion.split('_')[0] for pnpm 3.x to pass regardless if we check using dependencyVersion.indexOf('_') !== -1 or semver.valid

Copy link
Member

Choose a reason for hiding this comment

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

I misunderstood what the input to this function was. I thought it was the full path, not just a portion of the version string.

None of the inputs to this function when it runs on WBT contain any slashes. That makes me wonder if the logic introduced in #615 is necessary for anything other than PNPM v1. @halfnibble is probably right that .split('_') should be called after the slashes are split off.

@@ -272,6 +272,12 @@ export class PnpmShrinkwrapFile extends BaseShrinkwrapFile {
return packageDescription;
}

private _getValidDependencyVersion(dependencyVersion: string): string {
return semver.valid(dependencyVersion.split('/').pop()!) ?
Copy link
Member

Choose a reason for hiding this comment

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

I misunderstood what the input to this function was. I thought it was the full path, not just a portion of the version string.

None of the inputs to this function when it runs on WBT contain any slashes. That makes me wonder if the logic introduced in #615 is necessary for anything other than PNPM v1. @halfnibble is probably right that .split('_') should be called after the slashes are split off.

@apostolisms
Copy link
Contributor Author

@iclanton it seems like it. There are no slashes with pnpm 2.x. If it was introduced for pnpm 1.x support maybe we should keep it for backwards compatibility. Also I want to update per @sachinjoseph recommendation before merging.

const validDependencyVersion: string = dependencyVersion.split('/').pop()!;
return semver.valid(validDependencyVersion) ? validDependencyVersion : dependencyVersion.split('_')[0]!;
}

Copy link
Collaborator

@octogonz octogonz Jul 11, 2019

Choose a reason for hiding this comment

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

The original code was being a bit lazy with dependencyVersion.split('/').pop()!. (I like to say "If a function relies on split(), it probably has at least one bug" -- but of course that code predates your PR heheh.)

Now that we're expanding the logic, it might be time to beef up the rigor a bit, since:

  • The input format is no longer trivially simple
  • This input comes from an unvalidated external file, and that file has already betrayed us once

Anyway the next step up is a RegExp, something like this (pseudocode):

class TheClass {
  // Example: /react-loadable/5.5.0
  private static _pnpm2VersionRegExp: RegExp = /\/([^/_@]+)$/;

  // Example: 5.5.0_react@16.8.6
  private static _pnpm3VersionRegExp = /^([^/_@]+)_/;

   private _getValidDependencyVersion(dependencyVersion: string): string {
     let match: RegExpExecArray | null = MyClass._pnpm2VersionRegExp.exec(dependencyVersion);
     if (match) {
       return match[1];
     }
     match = MyClass._pnpm3VersionRegExp.exec(dependencyVersion);
     if (match) {
       return match[1];
     }
     throw new Error(`Invalid version format: "${dependencyVersion}"`)
   }
}

Copy link
Collaborator

@octogonz octogonz Jul 11, 2019

Choose a reason for hiding this comment

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

The semver.valid() thing also seems a bit lax. It's basically saying "If it doesn't look like a version, meh, let's pretend we didn't see it." Ideally we'd want to have a clear idea about what exactly we're ignoring, but I don't want to hold up your PR, since it's an important fix. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@octogonz I think we should merge this in since it is a blocking issue and open a separate PR for optimizing. I don't particularly like my fix either since even dependencyVersion.split('/').pop()! seems to be redundant. With pnpm 2.x it looks like dependency version never comes in as /react-loadable/5.5.0 I think the slashes get stripped out elsewhere?
I don't want to depart too much from the original implementation though before I thoroughly test it with 2.x and 3.x and verify that the cases we need to handle are actually just /react-loadable/5.5.0 and /react-loadable/5.5.0_react@16.8.6 ( / and _)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sounds good 👍

@apostolisms apostolisms merged commit 23ee6d5 into microsoft:master Jul 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants