diff --git a/src/detectPackageManager.ts b/src/detectPackageManager.ts index c7bb7559..dfef165b 100644 --- a/src/detectPackageManager.ts +++ b/src/detectPackageManager.ts @@ -4,7 +4,7 @@ import chalk from "chalk" import process from "process" import findWorkspaceRoot from "find-yarn-workspace-root" -export type PackageManager = "yarn" | "npm" | "npm-shrinkwrap" +export type PackageManager = "yarn" | "yarn-berry" | "npm" | "npm-shrinkwrap" function printNoYarnLockfileError() { console.log(` @@ -37,6 +37,19 @@ package-lock.json if you don't need it ) } +function detectYarnVersion(appRootPath: string): "yarn" | "yarn-berry" { + try { + const lockfilePath = join(appRootPath, "yarn.lock") + const lockfileContent = fs.readFileSync(lockfilePath, "utf8") + if (lockfileContent.includes("__metadata:")) { + return "yarn-berry" + } + } catch (e) { + // fall through to default + } + return "yarn" +} + export const detectPackageManager = ( appRootPath: string, overridePackageManager: PackageManager | null, @@ -63,7 +76,7 @@ export const detectPackageManager = ( return shrinkWrapExists ? "npm-shrinkwrap" : "npm" } } else if (yarnLockExists || findWorkspaceRoot()) { - return "yarn" + return detectYarnVersion(appRootPath) } else { printNoLockfilesError() process.exit(1) diff --git a/src/makePatch.ts b/src/makePatch.ts index 7e008eb3..933a02a7 100644 --- a/src/makePatch.ts +++ b/src/makePatch.ts @@ -193,14 +193,21 @@ export function makePatch({ // copy .npmrc/.yarnrc in case packages are hosted in private registry // copy .yarn directory as well to ensure installations work in yarn 2 // tslint:disable-next-line:align - ;[".npmrc", ".yarnrc", ".yarn"].forEach((rcFile) => { + ;[".npmrc", ".yarnrc", ".yarnrc.yml", ".yarn"].forEach((rcFile) => { const rcPath = join(appPath, rcFile) if (existsSync(rcPath)) { copySync(rcPath, join(tmpRepo.name, rcFile), { dereference: true }) } }) - if (packageManager === "yarn") { + if (packageManager.startsWith("yarn")) { + const isBerry = packageManager === "yarn-berry" + const installArgs = isBerry + ? ["install"] + : ["install", "--ignore-engines"] + const installArgsIgnoreScripts = isBerry + ? ["install", "--mode=skip-build"] + : ["install", "--ignore-engines", "--ignore-scripts"] console.info( chalk.grey("•"), `Installing ${packageDetails.name}@${packageVersion} with yarn`, @@ -208,20 +215,16 @@ export function makePatch({ try { // try first without ignoring scripts in case they are required // this works in 99.99% of cases - spawnSafeSync(`yarn`, ["install", "--ignore-engines"], { + spawnSafeSync(`yarn`, installArgs, { cwd: tmpRepoNpmRoot, logStdErrOnError: false, }) } catch (e) { // try again while ignoring scripts in case the script depends on // an implicit context which we haven't reproduced - spawnSafeSync( - `yarn`, - ["install", "--ignore-engines", "--ignore-scripts"], - { - cwd: tmpRepoNpmRoot, - }, - ) + spawnSafeSync(`yarn`, installArgsIgnoreScripts, { + cwd: tmpRepoNpmRoot, + }) } } else { console.info(