Skip to content

Commit 65880ca

Browse files
authored
fix: remove unsafe remove of install folder (#372)
* fix: remove unsafe remove of install folder * test: update to use folderUtils * perf: skip `existsSync` check
1 parent 54e9510 commit 65880ca

File tree

4 files changed

+27
-23
lines changed

4 files changed

+27
-23
lines changed

sources/Engine.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {SupportedPackageManagers, SupportedPackageManagerSet} from './types';
1818
export type PreparedPackageManagerInfo = Awaited<ReturnType<Engine[`ensurePackageManager`]>>;
1919

2020
export function getLastKnownGoodFile(flag = `r`) {
21-
return fs.promises.open(path.join(folderUtils.getInstallFolder(), `lastKnownGood.json`), flag);
21+
return fs.promises.open(path.join(folderUtils.getCorepackHomeFolder(), `lastKnownGood.json`), flag);
2222
}
2323

2424
export async function getJSONFileContent(fh: FileHandle) {

sources/corepackUtils.ts

+6-12
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,9 @@ export async function installVersion(installTarget: string, locator: Locator, {s
109109
const {version, build} = locatorReference;
110110

111111
const installFolder = path.join(installTarget, locator.name, version);
112-
const corepackFile = path.join(installFolder, `.corepack`);
113112

114-
// Older versions of Corepack didn't generate the `.corepack` file; in
115-
// that case we just download the package manager anew.
116-
if (fs.existsSync(corepackFile)) {
113+
try {
114+
const corepackFile = path.join(installFolder, `.corepack`);
117115
const corepackContent = await fs.promises.readFile(corepackFile, `utf8`);
118116
const corepackData = JSON.parse(corepackContent);
119117

@@ -123,6 +121,10 @@ export async function installVersion(installTarget: string, locator: Locator, {s
123121
hash: corepackData.hash as string,
124122
location: installFolder,
125123
};
124+
} catch (err) {
125+
if ((err as nodeUtils.NodeError).code !== `ENOENT`) {
126+
throw err;
127+
}
126128
}
127129

128130
const defaultNpmRegistryURL = spec.url.replace(`{}`, version);
@@ -172,14 +174,6 @@ export async function installVersion(installTarget: string, locator: Locator, {s
172174
hash: serializedHash,
173175
}));
174176

175-
// The target folder may exist if a previous version of Corepack installed
176-
// it but didn't create the `.corepack` file. In this case we need to
177-
// remove it first.
178-
await fs.promises.rm(installFolder, {
179-
recursive: true,
180-
force: true,
181-
});
182-
183177
await fs.promises.mkdir(path.dirname(installFolder), {recursive: true});
184178
try {
185179
await fs.promises.rename(tmpFolder, installFolder);

sources/folderUtils.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import process from 'process';
66

77
import type {NodeError} from './nodeUtils';
88

9-
export function getInstallFolder() {
9+
/**
10+
* If the install folder structure changes then increment this number.
11+
*/
12+
const INSTALL_FOLDER_VERSION = 1;
13+
14+
export function getCorepackHomeFolder() {
1015
return (
1116
process.env.COREPACK_HOME ??
1217
join(
@@ -18,6 +23,13 @@ export function getInstallFolder() {
1823
);
1924
}
2025

26+
export function getInstallFolder() {
27+
return join(
28+
getCorepackHomeFolder(),
29+
`v${INSTALL_FOLDER_VERSION}`,
30+
);
31+
}
32+
2133
export function getTemporaryFolder(target: string = tmpdir()) {
2234
mkdirSync(target, {recursive: true});
2335

tests/main.test.ts

+7-9
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@ import {Filename, ppath, xfs, npath, PortablePath} from '@yarnpkg/fslib';
33
import process from 'node:process';
44

55
import config from '../config.json';
6+
import * as folderUtils from '../sources/folderUtils';
67

78
import {runCli} from './_runCli';
89

9-
let corepackHome!: PortablePath;
1010

1111
beforeEach(async () => {
12-
corepackHome = await xfs.mktempPromise();
13-
14-
process.env.COREPACK_HOME = npath.fromPortablePath(corepackHome);
12+
process.env.COREPACK_HOME = npath.fromPortablePath(await xfs.mktempPromise());
1513
process.env.COREPACK_DEFAULT_TO_LATEST = `0`;
1614
});
1715

@@ -101,7 +99,7 @@ for (const [name, version] of testedPackageManagers) {
10199
}
102100

103101
it(`should update the Known Good Release only when the major matches`, async () => {
104-
await xfs.writeJsonPromise(ppath.join(corepackHome, `lastKnownGood.json`), {
102+
await xfs.writeJsonPromise(ppath.join(npath.toPortablePath(folderUtils.getCorepackHomeFolder()), `lastKnownGood.json`), {
105103
yarn: `1.0.0`,
106104
});
107105

@@ -645,7 +643,7 @@ it(`should not override the package manager exit code`, async () => {
645643
packageManager: `yarn@2.2.2`,
646644
});
647645

648-
const yarnFolder = ppath.join(corepackHome, `yarn/2.2.2`);
646+
const yarnFolder = ppath.join(npath.toPortablePath(folderUtils.getInstallFolder()), `yarn/2.2.2`);
649647
await xfs.mkdirPromise(yarnFolder, {recursive: true});
650648
await xfs.writeJsonPromise(ppath.join(yarnFolder, `.corepack`), {});
651649

@@ -670,7 +668,7 @@ it(`should not preserve the process.exitCode when a package manager throws`, asy
670668
packageManager: `yarn@2.2.2`,
671669
});
672670

673-
const yarnFolder = ppath.join(corepackHome, `yarn/2.2.2`);
671+
const yarnFolder = ppath.join(npath.toPortablePath(folderUtils.getInstallFolder()), `yarn/2.2.2`);
674672
await xfs.mkdirPromise(yarnFolder, {recursive: true});
675673
await xfs.writeJsonPromise(ppath.join(yarnFolder, `.corepack`), {});
676674

@@ -693,7 +691,7 @@ it(`should not set the exit code after successfully launching the package manage
693691
packageManager: `yarn@2.2.2`,
694692
});
695693

696-
const yarnFolder = ppath.join(corepackHome, `yarn/2.2.2`);
694+
const yarnFolder = ppath.join(npath.toPortablePath(folderUtils.getInstallFolder()), `yarn/2.2.2`);
697695
await xfs.mkdirPromise(yarnFolder, {recursive: true});
698696
await xfs.writeJsonPromise(ppath.join(yarnFolder, `.corepack`), {});
699697

@@ -719,7 +717,7 @@ it(`should support package managers in ESM format`, async () => {
719717
packageManager: `yarn@2.2.2`,
720718
});
721719

722-
const yarnFolder = ppath.join(corepackHome, `yarn/2.2.2`);
720+
const yarnFolder = ppath.join(npath.toPortablePath(folderUtils.getInstallFolder()), `yarn/2.2.2`);
723721
await xfs.mkdirPromise(yarnFolder, {recursive: true});
724722
await xfs.writeJsonPromise(ppath.join(yarnFolder, `.corepack`), {});
725723

0 commit comments

Comments
 (0)