Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions sources/corepackUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,24 @@ export async function installVersion(installTarget: string, locator: Locator, {s

const corepackData = JSON.parse(corepackContent);

debugUtils.log(`Reusing ${locator.name}@${locator.reference} found in ${installFolder}`);
// An older Corepack may have recorded bin paths that the package doesn't
// ship (e.g. `bin/pnpm.cjs` for pnpm 12). Reinstall instead of running them.
const recordedBin: unknown = corepackData.bin;
const isStale = isValidBinSpec(recordedBin) &&
Object.values(recordedBin).every(dest => !fs.existsSync(path.join(installFolder, dest)));

if (!isStale) {
debugUtils.log(`Reusing ${locator.name}@${locator.reference} found in ${installFolder}`);

return {
hash: corepackData.hash as string,
location: installFolder,
bin: corepackData.bin,
};
}

return {
hash: corepackData.hash as string,
location: installFolder,
bin: corepackData.bin,
};
debugUtils.log(`Reinstalling ${locator.name}@${locator.reference}: none of its bins exist in ${installFolder}`);
await fs.promises.rm(installFolder, {recursive: true, force: true});
} catch (err) {
if (nodeUtils.isNodeError(err) && err.code !== `ENOENT`) {
throw err;
Expand Down
27 changes: 27 additions & 0 deletions tests/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,33 @@ it(`should handle parallel installs`, async () => {
});
});

it(`should reinstall a cached package manager whose recorded bin is missing`, async () => {
await xfs.mktempPromise(async cwd => {
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
packageManager: `pnpm@6.6.2+sha224.eb5c0acad3b0f40ecdaa2db9aa5a73134ad256e17e22d1419a2ab073`,
});

await expect(runCli(cwd, [`pnpm`, `--version`])).resolves.toMatchObject({
exitCode: 0,
stderr: ``,
stdout: `6.6.2\n`,
});

// Simulate a record written by an older Corepack that pointed to a file the package doesn't ship.
const corepackFile = ppath.join(npath.toPortablePath(folderUtils.getInstallFolder()), `pnpm/6.6.2/.corepack` as PortablePath);
const record = await xfs.readJsonPromise(corepackFile);
await xfs.writeJsonPromise(corepackFile, {...record, bin: {pnpm: `./bin/missing.cjs`, pnpx: `./bin/missing.cjs`}});

await expect(runCli(cwd, [`pnpm`, `--version`])).resolves.toMatchObject({
exitCode: 0,
stderr: ``,
stdout: `6.6.2\n`,
});

await expect(xfs.readJsonPromise(corepackFile)).resolves.toMatchObject({bin: record.bin});
});
});

it(`should not override the package manager exit code`, async () => {
await xfs.mktempPromise(async cwd => {
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
Expand Down