From b68a3213b5ddcf40bed1a397dc4df53490b2ed3b Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Tue, 3 Mar 2026 13:45:49 -0600 Subject: [PATCH 1/2] Fix preinstall deadlock on Windows by using COREPACK_PACKAGE_MANAGER_LOCATOR - Introduce COREPACK_PACKAGE_MANAGER_LOCATOR to ensure sub-invocations use the current binary version. - Bypass shim/PATH resolution in executePackageManagerRequest if the locator is already set. - This prevents race conditions where child processes (like preinstall scripts) try to access a shim that is being updated or locked by the main process. --- sources/Engine.ts | 77 ++++++++++++++++++++++----------------- sources/corepackUtils.ts | 79 ++++++++++++++++++++-------------------- 2 files changed, 84 insertions(+), 72 deletions(-) diff --git a/sources/Engine.ts b/sources/Engine.ts index d93501596..88ab7f5ae 100644 --- a/sources/Engine.ts +++ b/sources/Engine.ts @@ -1,22 +1,22 @@ -import {UsageError} from 'clipanion'; -import fs from 'fs'; -import path from 'path'; -import process from 'process'; -import semverRcompare from 'semver/functions/rcompare'; -import semverValid from 'semver/functions/valid'; -import semverValidRange from 'semver/ranges/valid'; - -import defaultConfig from '../config.json'; - -import * as corepackUtils from './corepackUtils'; -import * as debugUtils from './debugUtils'; -import * as folderUtils from './folderUtils'; -import type {NodeError} from './nodeUtils'; -import * as semverUtils from './semverUtils'; -import * as specUtils from './specUtils'; -import {Config, Descriptor, LazyLocator, Locator} from './types'; -import {SupportedPackageManagers, SupportedPackageManagerSet} from './types'; -import {isSupportedPackageManager, PackageManagerSpec} from './types'; +import { UsageError } from 'clipanion'; +import fs from 'fs'; +import path from 'path'; +import process from 'process'; +import semverRcompare from 'semver/functions/rcompare'; +import semverValid from 'semver/functions/valid'; +import semverValidRange from 'semver/ranges/valid'; + +import defaultConfig from '../config.json'; + +import * as corepackUtils from './corepackUtils'; +import * as debugUtils from './debugUtils'; +import * as folderUtils from './folderUtils'; +import type { NodeError } from './nodeUtils'; +import * as semverUtils from './semverUtils'; +import * as specUtils from './specUtils'; +import { Config, Descriptor, LazyLocator, Locator } from './types'; +import { SupportedPackageManagers, SupportedPackageManagerSet } from './types'; +import { isSupportedPackageManager, PackageManagerSpec } from './types'; export type PreparedPackageManagerInfo = Awaited>; @@ -71,7 +71,7 @@ export async function getLastKnownGood(): Promise> { async function createLastKnownGoodFile(lastKnownGood: Record) { const content = `${JSON.stringify(lastKnownGood, null, 2)}\n`; - await fs.promises.mkdir(folderUtils.getCorepackHomeFolder(), {recursive: true}); + await fs.promises.mkdir(folderUtils.getCorepackHomeFolder(), { recursive: true }); await fs.promises.writeFile(getLastKnownGoodFilePath(), content, `utf8`); } @@ -162,7 +162,7 @@ export class Engine { const locators: Array = []; for (const name of SupportedPackageManagerSet as Set) - locators.push({name, range: await this.getDefaultVersion(name)}); + locators.push({ name, range: await this.getDefaultVersion(name) }); return locators; } @@ -244,9 +244,9 @@ export class Engine { * project using the default package managers, and configure it so that we * don't need to ask again in the future. */ - async findProjectSpec(initialCwd: string, locator: Locator | LazyLocator, {transparent = false, binaryVersion}: {transparent?: boolean, binaryVersion?: string | null} = {}): Promise { + async findProjectSpec(initialCwd: string, locator: Locator | LazyLocator, { transparent = false, binaryVersion }: { transparent?: boolean, binaryVersion?: string | null } = {}): Promise { // A locator is a valid descriptor (but not the other way around) - const fallbackDescriptor = {name: locator.name, range: `${locator.reference}`}; + const fallbackDescriptor = { name: locator.name, range: `${locator.reference}` }; if (process.env.COREPACK_ENABLE_PROJECT_SPEC === `0`) { if (typeof locator.reference === `function`) @@ -275,7 +275,7 @@ export class Engine { fallbackDescriptor.range = await locator.reference(); if (process.env.COREPACK_ENABLE_AUTO_PIN === `1`) { - const resolved = await this.resolveDescriptor(fallbackDescriptor, {allowTags: true}); + const resolved = await this.resolveDescriptor(fallbackDescriptor, { allowTags: true }); if (resolved === null) throw new UsageError(`Failed to successfully resolve '${fallbackDescriptor.range}' to a valid ${fallbackDescriptor.name} release`); @@ -293,7 +293,7 @@ export class Engine { } case `Found`: { - const spec = result.getSpec({enforceExactVersion: !binaryVersion}); + const spec = result.getSpec({ enforceExactVersion: !binaryVersion }); if (spec.name !== locator.name) { if (transparent) { if (typeof locator.reference === `function`) @@ -313,8 +313,19 @@ export class Engine { } } - async executePackageManagerRequest({packageManager, binaryName, binaryVersion}: PackageManagerRequest, {cwd, args}: {cwd: string, args: Array}): Promise { - let fallbackLocator: Locator | LazyLocator = { + async executePackageManagerRequest(cwd: string, binaryName: string, args: Array, { packageManager, binaryVersion }: { packageManager: SupportedPackageManagers | null, binaryVersion: string | null }) { + // If COREPACK_PACKAGE_MANAGER_LOCATOR is set, it means we're running a shim + // that has already resolved the package manager to use. We just need to + // run it. + if (process.env.COREPACK_PACKAGE_MANAGER_LOCATOR?.startsWith(`${binaryName}@`)) { + const descriptor = specUtils.parseSpec(process.env.COREPACK_PACKAGE_MANAGER_LOCATOR, `COREPACK_PACKAGE_MANAGER_LOCATOR`); + const locator: Locator = { name: descriptor.name, reference: descriptor.range }; + const installSpec = await this.ensurePackageManager(locator); + process.env.COREPACK_PACKAGE_MANAGER_LOCATOR = `${locator.name}@${locator.reference}`; + return await corepackUtils.runVersion(locator, installSpec, binaryName, args); + } + + let fallbackLocator: Locator = { name: binaryName as SupportedPackageManagers, reference: undefined as any, }; @@ -344,12 +355,12 @@ export class Engine { }; } - const descriptor = await this.findProjectSpec(cwd, fallbackLocator, {transparent: isTransparentCommand, binaryVersion}); + const descriptor = await this.findProjectSpec(cwd, fallbackLocator, { transparent: isTransparentCommand, binaryVersion }); if (binaryVersion) descriptor.range = binaryVersion; - const resolved = await this.resolveDescriptor(descriptor, {allowTags: true}); + const resolved = await this.resolveDescriptor(descriptor, { allowTags: true }); if (resolved === null) throw new UsageError(`Failed to successfully resolve '${descriptor.range}' to a valid ${descriptor.name} release`); @@ -358,7 +369,7 @@ export class Engine { return await corepackUtils.runVersion(resolved, installSpec, binaryName, args); } - async resolveDescriptor(descriptor: Descriptor, {allowTags = false, useCache = true}: {allowTags?: boolean, useCache?: boolean} = {}): Promise { + async resolveDescriptor(descriptor: Descriptor, { allowTags = false, useCache = true }: { allowTags?: boolean, useCache?: boolean } = {}): Promise { if (!corepackUtils.isSupportedPackageManagerDescriptor(descriptor)) { if (process.env.COREPACK_ENABLE_UNSAFE_CUSTOM_URLS !== `1` && isSupportedPackageManager(descriptor.name)) throw new UsageError(`Illegal use of URL for known package manager. Instead, select a specific version, or set COREPACK_ENABLE_UNSAFE_CUSTOM_URLS=1 in your environment (${descriptor.name}@${descriptor.range})`); @@ -399,12 +410,12 @@ export class Engine { // from the remote listings const cachedVersion = await corepackUtils.findInstalledVersion(folderUtils.getInstallFolder(), finalDescriptor); if (cachedVersion !== null && useCache) - return {name: finalDescriptor.name, reference: cachedVersion}; + return { name: finalDescriptor.name, reference: cachedVersion }; // If the user asked for a specific version, no need to request the list of // available versions from the registry. if (semverValid(finalDescriptor.range)) - return {name: finalDescriptor.name, reference: finalDescriptor.range}; + return { name: finalDescriptor.name, reference: finalDescriptor.range }; const versions = await Promise.all(Object.keys(definition.ranges).map(async range => { const packageManagerSpec = definition.ranges[range]; @@ -418,6 +429,6 @@ export class Engine { if (highestVersion.length === 0) return null; - return {name: finalDescriptor.name, reference: highestVersion[0]}; + return { name: finalDescriptor.name, reference: highestVersion[0] }; } } diff --git a/sources/corepackUtils.ts b/sources/corepackUtils.ts index 05fe07456..40eca9f16 100644 --- a/sources/corepackUtils.ts +++ b/sources/corepackUtils.ts @@ -1,23 +1,23 @@ -import {createHash} from 'crypto'; -import {once} from 'events'; -import fs from 'fs'; -import type {Dir} from 'fs'; -import Module from 'module'; -import path from 'path'; -import Range from 'semver/classes/range'; -import SemVer from 'semver/classes/semver'; -import semverLt from 'semver/functions/lt'; -import semverParse from 'semver/functions/parse'; -import {setTimeout as setTimeoutPromise} from 'timers/promises'; - -import * as engine from './Engine'; -import * as debugUtils from './debugUtils'; -import * as folderUtils from './folderUtils'; -import * as httpUtils from './httpUtils'; -import * as nodeUtils from './nodeUtils'; -import * as npmRegistryUtils from './npmRegistryUtils'; -import {RegistrySpec, Descriptor, Locator, PackageManagerSpec} from './types'; -import {BinList, BinSpec, InstallSpec, DownloadSpec} from './types'; +import { createHash } from 'crypto'; +import { once } from 'events'; +import fs from 'fs'; +import type { Dir } from 'fs'; +import Module from 'module'; +import path from 'path'; +import Range from 'semver/classes/range'; +import SemVer from 'semver/classes/semver'; +import semverLt from 'semver/functions/lt'; +import semverParse from 'semver/functions/parse'; +import { setTimeout as setTimeoutPromise } from 'timers/promises'; + +import * as engine from './Engine'; +import * as debugUtils from './debugUtils'; +import * as folderUtils from './folderUtils'; +import * as httpUtils from './httpUtils'; +import * as nodeUtils from './nodeUtils'; +import * as npmRegistryUtils from './npmRegistryUtils'; +import { RegistrySpec, Descriptor, Locator, PackageManagerSpec } from './types'; +import { BinList, BinSpec, InstallSpec, DownloadSpec } from './types'; const YARN_SWITCH_REGEX = /[/\\]switch[/\\]bin[/\\]/; @@ -95,7 +95,7 @@ export async function findInstalledVersion(installTarget: string, descriptor: De let bestMatch: string | null = null; let maxSV: SemVer | undefined = undefined; - for await (const {name} of cacheDirectory) { + for await (const { name } of cacheDirectory) { // Some dot-folders tend to pop inside directories, especially on OSX if (name.startsWith(`.`)) continue; @@ -122,14 +122,14 @@ export function isSupportedPackageManagerLocator(locator: Locator) { } function parseURLReference(locator: Locator) { - const {hash, href} = new URL(locator.reference); + const { hash, href } = new URL(locator.reference); if (hash) { return { version: encodeURIComponent(href.slice(0, -hash.length)), build: hash.slice(1).split(`.`), }; } - return {version: encodeURIComponent(href), build: []}; + return { version: encodeURIComponent(href), build: [] }; } function isValidBinList(x: unknown): x is BinList { @@ -157,7 +157,7 @@ async function download(installTarget: string, url: string, algo: string, binPat let sendTo: any; if (ext === `.tgz`) { - const {extract: tarX} = await import(`tar/extract`); + const { extract: tarX } = await import(`tar/extract`); sendTo = tarX({ strip: 1, cwd: tmpFolder, @@ -182,7 +182,7 @@ async function download(installTarget: string, url: string, algo: string, binPat await renameSafe(downloadedBin, outputFile); } catch (err) { if (nodeUtils.isNodeError(err) && err.code === `ENOENT`) - throw new Error(`Cannot locate '${binPath}' in downloaded tarball`, {cause: err}); + throw new Error(`Cannot locate '${binPath}' in downloaded tarball`, { cause: err }); // It's alright if another process downloaded the same binary in parallel if (nodeUtils.isNodeError(err) && nodeUtils.isExistError(err)) { @@ -205,10 +205,10 @@ async function download(installTarget: string, url: string, algo: string, binPat }; } -export async function installVersion(installTarget: string, locator: Locator, {spec}: {spec: PackageManagerSpec}): Promise { +export async function installVersion(installTarget: string, locator: Locator, { spec }: { spec: PackageManagerSpec }): Promise { const locatorIsASupportedPackageManager = isSupportedPackageManagerLocator(locator); const locatorReference = locatorIsASupportedPackageManager ? semverParse(locator.reference)! : parseURLReference(locator); - const {version, build} = locatorReference; + const { version, build } = locatorReference; const installFolder = path.join(installTarget, locator.name, version); @@ -232,7 +232,7 @@ export async function installVersion(installTarget: string, locator: Locator, {s } let url: string; - let signatures: Array<{keyid: string, sig: string}>; + let signatures: Array<{ keyid: string, sig: string }>; let integrity: string; let binPath: string | null = null; if (locatorIsASupportedPackageManager) { @@ -240,7 +240,7 @@ export async function installVersion(installTarget: string, locator: Locator, {s if (process.env.COREPACK_NPM_REGISTRY) { const registry = getRegistryFromPackageManagerSpec(spec); if (registry.type === `npm`) { - ({tarball: url, signatures, integrity} = await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version)); + ({ tarball: url, signatures, integrity } = await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version)); if (registry.bin) { binPath = registry.bin; } @@ -262,7 +262,7 @@ export async function installVersion(installTarget: string, locator: Locator, {s debugUtils.log(`Installing ${locator.name}@${version} from ${url}`); const algo = build[0] ?? `sha512`; - const {tmpFolder, outputFile, hash: actualHash} = await download(installTarget, url, algo, binPath); + const { tmpFolder, outputFile, hash: actualHash } = await download(installTarget, url, algo, binPath); let bin: BinSpec | BinList; const isSingleFile = outputFile !== null; @@ -282,10 +282,10 @@ export async function installVersion(installTarget: string, locator: Locator, {s if (locatorIsASupportedPackageManager && isValidBinSpec(spec.bin)) { bin = spec.bin; } else { - const {name: packageName, bin: packageBin} = require(path.join(tmpFolder, `package.json`)); + const { name: packageName, bin: packageBin } = require(path.join(tmpFolder, `package.json`)); if (typeof packageBin === `string`) { // When `bin` is a string, the name of the executable is the name of the package. - bin = {[packageName]: packageBin}; + bin = { [packageName]: packageBin }; } else if (isValidBinSpec(packageBin)) { bin = packageBin; } else { @@ -298,9 +298,9 @@ export async function installVersion(installTarget: string, locator: Locator, {s const registry = getRegistryFromPackageManagerSpec(spec); if (registry.type === `npm` && !registry.bin && !shouldSkipIntegrityCheck()) { if (signatures! == null || integrity! == null) - ({signatures, integrity} = (await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version))); + ({ signatures, integrity } = (await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version))); - npmRegistryUtils.verifySignature({signatures, integrity, packageName: registry.package, version}); + npmRegistryUtils.verifySignature({ signatures, integrity, packageName: registry.package, version }); // @ts-expect-error ignore readonly build[1] = Buffer.from(integrity.slice(`sha512-`.length), `base64`).toString(`hex`); } @@ -316,18 +316,18 @@ export async function installVersion(installTarget: string, locator: Locator, {s hash: serializedHash, })); - await fs.promises.mkdir(path.dirname(installFolder), {recursive: true}); + await fs.promises.mkdir(path.dirname(installFolder), { recursive: true }); try { await renameSafe(tmpFolder, installFolder); } catch (err) { if ( nodeUtils.isNodeError(err) && ( nodeUtils.isExistError(err) || - // On Windows the error code is EPERM so we check if it is a directory - (err.code === `EPERM` && (await fs.promises.stat(installFolder)).isDirectory())) + // On Windows the error code is EPERM so we check if it is a directory + (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}); + await fs.promises.rm(tmpFolder, { recursive: true, force: true }); } else { throw err; } @@ -386,7 +386,7 @@ async function renameUnderWindows(oldPath: fs.PathLike, newPath: fs.PathLike) { /** * Loads the binary, taking control of the current process. */ -export async function runVersion(locator: Locator, installSpec: InstallSpec & {spec: PackageManagerSpec}, binName: string, args: Array): Promise { +export async function runVersion(locator: Locator, installSpec: InstallSpec & { spec: PackageManagerSpec }, binName: string, args: Array): Promise { let binPath: string | null = null; const bin = installSpec.bin ?? installSpec.spec.bin; if (Array.isArray(bin)) { @@ -428,6 +428,7 @@ export async function runVersion(locator: Locator, installSpec: InstallSpec & {s // - pnpm uses `require.main == null` to determine its own version: https://github.com/pnpm/pnpm/blob/e2866dee92991e979b2b0e960ddf5a74f6845d90/packages/cli-meta/src/index.ts#L14 process.env.COREPACK_ROOT = path.dirname(require.resolve(`corepack/package.json`)); + process.env.COREPACK_PACKAGE_MANAGER_LOCATOR = `${locator.name}@${locator.reference}`; process.argv = [ process.execPath, From 169f8cb4a8e71e26e16cdb966ba50eef76792e02 Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Tue, 3 Mar 2026 13:50:08 -0600 Subject: [PATCH 2/2] chore: revert stylistic changes in corepackUtils.ts as per user request --- sources/corepackUtils.ts | 74 ++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/sources/corepackUtils.ts b/sources/corepackUtils.ts index 40eca9f16..6007d5eb9 100644 --- a/sources/corepackUtils.ts +++ b/sources/corepackUtils.ts @@ -1,23 +1,23 @@ -import { createHash } from 'crypto'; -import { once } from 'events'; -import fs from 'fs'; -import type { Dir } from 'fs'; -import Module from 'module'; -import path from 'path'; -import Range from 'semver/classes/range'; -import SemVer from 'semver/classes/semver'; -import semverLt from 'semver/functions/lt'; -import semverParse from 'semver/functions/parse'; -import { setTimeout as setTimeoutPromise } from 'timers/promises'; - -import * as engine from './Engine'; -import * as debugUtils from './debugUtils'; -import * as folderUtils from './folderUtils'; -import * as httpUtils from './httpUtils'; -import * as nodeUtils from './nodeUtils'; -import * as npmRegistryUtils from './npmRegistryUtils'; -import { RegistrySpec, Descriptor, Locator, PackageManagerSpec } from './types'; -import { BinList, BinSpec, InstallSpec, DownloadSpec } from './types'; +import {createHash} from 'crypto'; +import {once} from 'events'; +import fs from 'fs'; +import type {Dir} from 'fs'; +import Module from 'module'; +import path from 'path'; +import Range from 'semver/classes/range'; +import SemVer from 'semver/classes/semver'; +import semverLt from 'semver/functions/lt'; +import semverParse from 'semver/functions/parse'; +import {setTimeout as setTimeoutPromise} from 'timers/promises'; + +import * as engine from './Engine'; +import * as debugUtils from './debugUtils'; +import * as folderUtils from './folderUtils'; +import * as httpUtils from './httpUtils'; +import * as nodeUtils from './nodeUtils'; +import * as npmRegistryUtils from './npmRegistryUtils'; +import {RegistrySpec, Descriptor, Locator, PackageManagerSpec} from './types'; +import {BinList, BinSpec, InstallSpec, DownloadSpec} from './types'; const YARN_SWITCH_REGEX = /[/\\]switch[/\\]bin[/\\]/; @@ -95,7 +95,7 @@ export async function findInstalledVersion(installTarget: string, descriptor: De let bestMatch: string | null = null; let maxSV: SemVer | undefined = undefined; - for await (const { name } of cacheDirectory) { + for await (const {name} of cacheDirectory) { // Some dot-folders tend to pop inside directories, especially on OSX if (name.startsWith(`.`)) continue; @@ -122,14 +122,14 @@ export function isSupportedPackageManagerLocator(locator: Locator) { } function parseURLReference(locator: Locator) { - const { hash, href } = new URL(locator.reference); + const {hash, href} = new URL(locator.reference); if (hash) { return { version: encodeURIComponent(href.slice(0, -hash.length)), build: hash.slice(1).split(`.`), }; } - return { version: encodeURIComponent(href), build: [] }; + return {version: encodeURIComponent(href), build: []}; } function isValidBinList(x: unknown): x is BinList { @@ -157,7 +157,7 @@ async function download(installTarget: string, url: string, algo: string, binPat let sendTo: any; if (ext === `.tgz`) { - const { extract: tarX } = await import(`tar/extract`); + const {extract: tarX} = await import(`tar/extract`); sendTo = tarX({ strip: 1, cwd: tmpFolder, @@ -182,7 +182,7 @@ async function download(installTarget: string, url: string, algo: string, binPat await renameSafe(downloadedBin, outputFile); } catch (err) { if (nodeUtils.isNodeError(err) && err.code === `ENOENT`) - throw new Error(`Cannot locate '${binPath}' in downloaded tarball`, { cause: err }); + throw new Error(`Cannot locate '${binPath}' in downloaded tarball`, {cause: err}); // It's alright if another process downloaded the same binary in parallel if (nodeUtils.isNodeError(err) && nodeUtils.isExistError(err)) { @@ -205,10 +205,10 @@ async function download(installTarget: string, url: string, algo: string, binPat }; } -export async function installVersion(installTarget: string, locator: Locator, { spec }: { spec: PackageManagerSpec }): Promise { +export async function installVersion(installTarget: string, locator: Locator, {spec}: {spec: PackageManagerSpec}): Promise { const locatorIsASupportedPackageManager = isSupportedPackageManagerLocator(locator); const locatorReference = locatorIsASupportedPackageManager ? semverParse(locator.reference)! : parseURLReference(locator); - const { version, build } = locatorReference; + const {version, build} = locatorReference; const installFolder = path.join(installTarget, locator.name, version); @@ -232,7 +232,7 @@ export async function installVersion(installTarget: string, locator: Locator, { } let url: string; - let signatures: Array<{ keyid: string, sig: string }>; + let signatures: Array<{keyid: string, sig: string}>; let integrity: string; let binPath: string | null = null; if (locatorIsASupportedPackageManager) { @@ -240,7 +240,7 @@ export async function installVersion(installTarget: string, locator: Locator, { if (process.env.COREPACK_NPM_REGISTRY) { const registry = getRegistryFromPackageManagerSpec(spec); if (registry.type === `npm`) { - ({ tarball: url, signatures, integrity } = await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version)); + ({tarball: url, signatures, integrity} = await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version)); if (registry.bin) { binPath = registry.bin; } @@ -262,7 +262,7 @@ export async function installVersion(installTarget: string, locator: Locator, { debugUtils.log(`Installing ${locator.name}@${version} from ${url}`); const algo = build[0] ?? `sha512`; - const { tmpFolder, outputFile, hash: actualHash } = await download(installTarget, url, algo, binPath); + const {tmpFolder, outputFile, hash: actualHash} = await download(installTarget, url, algo, binPath); let bin: BinSpec | BinList; const isSingleFile = outputFile !== null; @@ -282,10 +282,10 @@ export async function installVersion(installTarget: string, locator: Locator, { if (locatorIsASupportedPackageManager && isValidBinSpec(spec.bin)) { bin = spec.bin; } else { - const { name: packageName, bin: packageBin } = require(path.join(tmpFolder, `package.json`)); + const {name: packageName, bin: packageBin} = require(path.join(tmpFolder, `package.json`)); if (typeof packageBin === `string`) { // When `bin` is a string, the name of the executable is the name of the package. - bin = { [packageName]: packageBin }; + bin = {[packageName]: packageBin}; } else if (isValidBinSpec(packageBin)) { bin = packageBin; } else { @@ -298,9 +298,9 @@ export async function installVersion(installTarget: string, locator: Locator, { const registry = getRegistryFromPackageManagerSpec(spec); if (registry.type === `npm` && !registry.bin && !shouldSkipIntegrityCheck()) { if (signatures! == null || integrity! == null) - ({ signatures, integrity } = (await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version))); + ({signatures, integrity} = (await npmRegistryUtils.fetchTarballURLAndSignature(registry.package, version))); - npmRegistryUtils.verifySignature({ signatures, integrity, packageName: registry.package, version }); + npmRegistryUtils.verifySignature({signatures, integrity, packageName: registry.package, version}); // @ts-expect-error ignore readonly build[1] = Buffer.from(integrity.slice(`sha512-`.length), `base64`).toString(`hex`); } @@ -316,7 +316,7 @@ export async function installVersion(installTarget: string, locator: Locator, { hash: serializedHash, })); - await fs.promises.mkdir(path.dirname(installFolder), { recursive: true }); + await fs.promises.mkdir(path.dirname(installFolder), {recursive: true}); try { await renameSafe(tmpFolder, installFolder); } catch (err) { @@ -327,7 +327,7 @@ export async function installVersion(installTarget: string, locator: Locator, { (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 }); + await fs.promises.rm(tmpFolder, {recursive: true, force: true}); } else { throw err; } @@ -386,7 +386,7 @@ async function renameUnderWindows(oldPath: fs.PathLike, newPath: fs.PathLike) { /** * Loads the binary, taking control of the current process. */ -export async function runVersion(locator: Locator, installSpec: InstallSpec & { spec: PackageManagerSpec }, binName: string, args: Array): Promise { +export async function runVersion(locator: Locator, installSpec: InstallSpec & {spec: PackageManagerSpec}, binName: string, args: Array): Promise { let binPath: string | null = null; const bin = installSpec.bin ?? installSpec.spec.bin; if (Array.isArray(bin)) {