Skip to content
Merged
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: 13 additions & 10 deletions sources/corepackUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export async function findInstalledVersion(installTarget: string, descriptor: De
try {
cacheDirectory = await fs.promises.opendir(installFolder);
} catch (error) {
if ((error as nodeUtils.NodeError).code === `ENOENT`) {
if (nodeUtils.isNodeError(error) && error.code === `ENOENT`) {
return null;
} else {
throw error;
Expand Down Expand Up @@ -181,10 +181,15 @@ async function download(installTarget: string, url: string, algo: string, binPat
try {
await renameSafe(downloadedBin, outputFile);
} catch (err) {
if ((err as nodeUtils.NodeError)?.code === `ENOENT`)
if (nodeUtils.isNodeError(err) && err.code === `ENOENT`)
throw new Error(`Cannot locate '${binPath}' in downloaded tarball`, {cause: err});

throw err;
// It's alright if another process downloaded the same binary in parallel
if (nodeUtils.isNodeError(err) && nodeUtils.isExistError(err)) {
await fs.promises.rm(downloadedBin);
} else {
throw err;
}
}

// Calculate the hash of the bin file
Expand Down Expand Up @@ -221,7 +226,7 @@ export async function installVersion(installTarget: string, locator: Locator, {s
bin: corepackData.bin,
};
} catch (err) {
if ((err as nodeUtils.NodeError)?.code !== `ENOENT`) {
if (nodeUtils.isNodeError(err) && err.code !== `ENOENT`) {
throw err;
}
}
Expand Down Expand Up @@ -316,9 +321,10 @@ export async function installVersion(installTarget: string, locator: Locator, {s
await renameSafe(tmpFolder, installFolder);
} catch (err) {
if (
(err as nodeUtils.NodeError).code === `ENOTEMPTY` ||
nodeUtils.isNodeError(err) && (
nodeUtils.isExistError(err) ||
// On Windows the error code is EPERM so we check if it is a directory
((err as nodeUtils.NodeError).code === `EPERM` && (await fs.promises.stat(installFolder)).isDirectory())
(err.code === `EPERM` && (await fs.promises.stat(installFolder)).isDirectory()))
) {
debugUtils.log(`Another instance of corepack installed ${locator.name}@${locator.reference}`);
await fs.promises.rm(tmpFolder, {recursive: true, force: true});
Expand Down Expand Up @@ -365,10 +371,7 @@ async function renameUnderWindows(oldPath: fs.PathLike, newPath: fs.PathLike) {
break;
} catch (err) {
if (
(
(err as nodeUtils.NodeError).code === `ENOENT` ||
(err as nodeUtils.NodeError).code === `EPERM`
) &&
nodeUtils.isNodeError(err) && (err.code === `ENOENT` || err.code === `EPERM`) &&
i < (retries - 1)
) {
await setTimeoutPromise(100 * 2 ** i);
Expand Down
8 changes: 8 additions & 0 deletions sources/nodeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ export interface NodeError extends Error {
code: string;
}

export function isNodeError(err: any): err is NodeError {
return !!err?.code;
}

export function isExistError(err: NodeError) {
return err.code === `EEXIST` || err.code === `ENOTEMPTY`;
}

function getEndOfLine(content: string) {
const matches = content.match(/\r?\n/g);
if (matches === null)
Expand Down