diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go index fff816d88c9ed..897e84712de70 100644 --- a/cli/internal/lockfile/pnpm_lockfile.go +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -439,16 +439,35 @@ func (p *PnpmLockfile) resolveSpecifier(workspacePath turbopath.AnchoredUnixPath return "", false, err } // Verify that the specifier in the importer matches the one given - if !ok || resolution.Specifier != specifier { + if !ok { // Check if the specifier is already a resolved version if _, ok := p.Packages[p.formatKey(name, specifier)]; ok { return specifier, true, nil } return "", false, fmt.Errorf("Unable to find resolved version for %s@%s in %s", name, specifier, workspacePath) } + overrideSpecifier := p.applyOverrides(name, specifier) + if resolution.Specifier != overrideSpecifier { + if _, ok := p.Packages[p.formatKey(name, overrideSpecifier)]; ok { + return overrideSpecifier, true, nil + } + return "", false, nil + } return resolution.Version, true, nil } +// Apply pnpm overrides to specifier, see https://pnpm.io/package_json#pnpmoverrides +// Note this is barebones support and will only supports global overrides +// future work will support semver ranges and selector filtering. +func (p *PnpmLockfile) applyOverrides(name string, specifier string) string { + if len(p.Overrides) > 0 { + if new, ok := p.Overrides[name]; ok { + return new + } + } + return specifier +} + func formatPnpmKey(name string, version string) string { return fmt.Sprintf("/%s/%s", name, version) } diff --git a/cli/internal/lockfile/pnpm_lockfile_test.go b/cli/internal/lockfile/pnpm_lockfile_test.go index deec1a332dd4a..582cf2e11bd41 100644 --- a/cli/internal/lockfile/pnpm_lockfile_test.go +++ b/cli/internal/lockfile/pnpm_lockfile_test.go @@ -289,3 +289,22 @@ func Test_LockfileTopLevelOverride(t *testing.T) { assert.DeepEqual(t, pkg.Key, "/ci-info/3.7.1") assert.DeepEqual(t, pkg.Version, "3.7.1") } + +func Test_PnpmOverride(t *testing.T) { + contents, err := getFixture(t, "pnpm_override.yaml") + if err != nil { + t.Error(err) + } + lockfile, err := DecodePnpmLockfile(contents) + assert.NilError(t, err, "decode lockfile") + + pkg, err := lockfile.ResolvePackage( + turbopath.AnchoredUnixPath("config/hardhat"), + "@nomiclabs/hardhat-ethers", + "npm:hardhat-deploy-ethers@0.3.0-beta.13", + ) + assert.NilError(t, err, "failure to find package") + assert.Assert(t, pkg.Found) + assert.DeepEqual(t, pkg.Key, "/hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy") + assert.DeepEqual(t, pkg.Version, "/hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy") +} diff --git a/cli/internal/lockfile/testdata/pnpm_override.yaml b/cli/internal/lockfile/testdata/pnpm_override.yaml new file mode 100644 index 0000000000000..21021920f574e --- /dev/null +++ b/cli/internal/lockfile/testdata/pnpm_override.yaml @@ -0,0 +1,24 @@ +lockfileVersion: 5.4 + +overrides: + "@nomiclabs/hardhat-ethers": npm:hardhat-deploy-ethers@^0.3.0-beta.13 + +importers: + config/hardhat: + specifiers: + "@nomiclabs/hardhat-ethers": npm:hardhat-deploy-ethers@^0.3.0-beta.13 + dependencies: + "@nomiclabs/hardhat-ethers": /hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy + +packages: + /hardhat-deploy-ethers/0.3.0-beta.13_yab2ug5tvye2kp6e24l5x3z7uy: + resolution: + { + integrity: sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw==, + } + peerDependencies: + ethers: ^5.0.0 + hardhat: ^2.0.0 + dependencies: + ethers: 5.7.2 + hardhat: 2.12.4_typescript@4.9.4