From 859d7398b753d22e0e74c3b07ba88c1a566691ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Fri, 10 Nov 2023 17:28:50 +0100 Subject: [PATCH 1/6] Prepares for the 1.22.20 release --- package.json | 1 + scripts/build-webpack.js | 14 ++++++ src/cli/commands/policies.js | 2 +- src/cli/index.js | 94 ++++++++++++++---------------------- src/reporters/lang/en.js | 3 ++ yarn.lock | 2 +- 6 files changed, 56 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index 8f08b2794a..66fb61c589 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "object-path": "^0.11.2", "proper-lockfile": "^2.0.0", "puka": "^1.0.0", + "punycode": "1.4.1", "read": "^1.0.7", "request": "^2.87.0", "request-capture-har": "^1.2.2", diff --git a/scripts/build-webpack.js b/scripts/build-webpack.js index d0b166fa2d..230e79588f 100755 --- a/scripts/build-webpack.js +++ b/scripts/build-webpack.js @@ -7,6 +7,10 @@ const resolve = require('resolve'); const util = require('util'); const fs = require('fs'); +// Otherwise Webpack 4 will be "helpful" and automatically mark the `punycode` package as external, +// despite us wanting to bundle it since it will be removed from future Node.js versions. +delete process.binding("natives").punycode; + const version = require('../package.json').version; const basedir = path.join(__dirname, '../'); const babelRc = JSON.parse(fs.readFileSync(path.join(basedir, '.babelrc'), 'utf8')); @@ -74,6 +78,11 @@ const compiler = webpack({ [`artifacts/yarn-${version}.js`]: path.join(basedir, 'src/cli/index.js'), 'packages/lockfile/index.js': path.join(basedir, 'src/lockfile/index.js'), }, + resolve: { + alias: { + punycode: require.resolve(`punycode/`), + }, + }, module: { rules: [ { @@ -126,6 +135,11 @@ compiler.run((err, stats) => { const compilerLegacy = webpack({ // devtool: 'inline-source-map', entry: path.join(basedir, 'src/cli/index.js'), + resolve: { + alias: { + punycode: require.resolve(`punycode/`), + }, + }, module: { rules: [ { diff --git a/src/cli/commands/policies.js b/src/cli/commands/policies.js index 08766c76e6..49e46f67dc 100644 --- a/src/cli/commands/policies.js +++ b/src/cli/commands/policies.js @@ -157,7 +157,7 @@ const {run, setFlags, examples} = buildSubCommands('policies', { bundleUrl = 'https://nightly.yarnpkg.com/latest.js'; bundleVersion = 'nightly'; } else if (V2_NAMES.includes(range) || isLocalFile(range) || isV2Version(range)) { - const normalizedRange = range === `canary` ? `canary` : `stable`; + const normalizedRange = isV2Version(range) ? range : range === `canary` ? `canary` : `stable`; if (process.env.COREPACK_ROOT) { await child.spawn( diff --git a/src/cli/index.js b/src/cli/index.js index 4348adbb12..6fb78c09e6 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -26,6 +26,8 @@ import handleSignals from '../util/signal-handler.js'; import {boolify, boolifyWithDefault} from '../util/conversion.js'; import {ProcessTermError} from '../errors'; +const chalk = require('chalk'); + process.stdout.prependListener('error', err => { // swallow err only if downstream consumer process closed pipe early if (err.code === 'EPIPE' || err.code === 'ERR_STREAM_DESTROYED') { @@ -263,6 +265,39 @@ export async function main({ reporter.initPeakMemoryCounter(); const config = new Config(reporter); + + const projectRoot = findProjectRoot(commander.cwd); + const cwd = command.shouldRunInCurrentCwd ? commander.cwd : projectRoot; + + if (!process.env.COREPACK_ROOT) { + const rootManifest = await config.readRootManifest(projectRoot); + if (typeof rootManifest.packageManager === `string`) { + if (!rootManifest.packageManager.match(/^yarn@[01]\./)) { + reporter.error( + `This project's package.json defines ${chalk.gray('"packageManager": "yarn@')}${chalk.yellow( + `${rootManifest.packageManager.replace(/^yarn@/, ``).replace(/\+.*/, ``)}`, + )}${chalk.gray(`"`)}. However the current global version of Yarn is ${chalk.yellow(version)}.`, + ); + + process.stderr.write(`\n`); + process.stderr.write( + `Presence of the ${chalk.gray( + `"packageManager"`, + )} field indicates that the project is meant to be used with Corepack, a tool included by default with all modern Node.js distributions.\n`, + ); + + process.stderr.write( + `Corepack must currently be enabled by running ${chalk.magenta( + `corepack enable`, + )} in your terminal. For more information, check out ${chalk.blueBright(`https://yarnpkg.com/corepack`)}.\n`, + ); + + exit(1); + return; + } + } + } + const outputWrapperEnabled = boolifyWithDefault(process.env.YARN_WRAP_OUTPUT, true); const shouldWrapOutput = outputWrapperEnabled && @@ -466,61 +501,6 @@ export async function main({ }); }; - function onUnexpectedError(err: Error) { - function indent(str: string): string { - return '\n ' + str.trim().split('\n').join('\n '); - } - - const log = []; - log.push(`Arguments: ${indent(process.argv.join(' '))}`); - log.push(`PATH: ${indent(process.env.PATH || 'undefined')}`); - log.push(`Yarn version: ${indent(version)}`); - log.push(`Node version: ${indent(process.versions.node)}`); - log.push(`Platform: ${indent(process.platform + ' ' + process.arch)}`); - - log.push(`Trace: ${indent(err.stack)}`); - - // add manifests - for (const registryName of registryNames) { - const possibleLoc = path.join(config.cwd, registries[registryName].filename); - const manifest = fs.existsSync(possibleLoc) ? fs.readFileSync(possibleLoc, 'utf8') : 'No manifest'; - log.push(`${registryName} manifest: ${indent(manifest)}`); - } - - // lockfile - const lockLoc = path.join( - config.lockfileFolder || config.cwd, // lockfileFolder might not be set at this point - constants.LOCKFILE_FILENAME, - ); - const lockfile = fs.existsSync(lockLoc) ? fs.readFileSync(lockLoc, 'utf8') : 'No lockfile'; - log.push(`Lockfile: ${indent(lockfile)}`); - - const errorReportLoc = writeErrorReport(log); - - reporter.error(reporter.lang('unexpectedError', err.message)); - - if (errorReportLoc) { - reporter.info(reporter.lang('bugReport', errorReportLoc)); - } - } - - function writeErrorReport(log): ?string { - const errorReportLoc = config.enableMetaFolder - ? path.join(config.cwd, constants.META_FOLDER, 'yarn-error.log') - : path.join(config.cwd, 'yarn-error.log'); - - try { - fs.writeFileSync(errorReportLoc, log.join('\n\n') + '\n'); - } catch (err) { - reporter.error(reporter.lang('fileWriteError', errorReportLoc, err.message)); - return undefined; - } - - return errorReportLoc; - } - - const cwd = command.shouldRunInCurrentCwd ? commander.cwd : findProjectRoot(commander.cwd); - const folderOptionKeys = ['linkFolder', 'globalFolder', 'preferredCacheFolder', 'cacheFolder', 'modulesFolder']; // Resolve all folder options relative to cwd @@ -559,7 +539,7 @@ export async function main({ focus: commander.focus, otp: commander.otp, }) - .then(() => { + .then(async () => { // lockfile check must happen after config.init sets lockfileFolder if (command.requireLockfile && !fs.existsSync(path.join(config.lockfileFolder, constants.LOCKFILE_FILENAME))) { throw new MessageError(reporter.lang('noRequiredLockfile')); @@ -608,8 +588,6 @@ export async function main({ if (err instanceof MessageError) { reporter.error(err.message); - } else { - onUnexpectedError(err); } if (command.getDocsInfo) { diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index e376e969b3..61e4224a4e 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -2,6 +2,9 @@ /* eslint max-len: 0 */ const messages = { + checkCorepack: + 'This command would have run $0 on a project configured to use $1. Is Corepack installed? If not, follow the instructions at https://yarnpkg.com/corepack.', + upToDate: 'Already up-to-date.', folderInSync: 'Folder in sync.', nothingToInstall: 'Nothing to install.', diff --git a/yarn.lock b/yarn.lock index fe1b1cd3f8..f432c813e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6140,7 +6140,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.4.1: +punycode@1.4.1, punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= From e4f54c08cddf3f4f168fd16788ebffa69cf4bf26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Fri, 10 Nov 2023 17:34:52 +0100 Subject: [PATCH 2/6] Cleanup --- src/cli/index.js | 2 +- src/reporters/lang/en.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cli/index.js b/src/cli/index.js index 6fb78c09e6..84f793680c 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -539,7 +539,7 @@ export async function main({ focus: commander.focus, otp: commander.otp, }) - .then(async () => { + .then(() => { // lockfile check must happen after config.init sets lockfileFolder if (command.requireLockfile && !fs.existsSync(path.join(config.lockfileFolder, constants.LOCKFILE_FILENAME))) { throw new MessageError(reporter.lang('noRequiredLockfile')); diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index 61e4224a4e..e376e969b3 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -2,9 +2,6 @@ /* eslint max-len: 0 */ const messages = { - checkCorepack: - 'This command would have run $0 on a project configured to use $1. Is Corepack installed? If not, follow the instructions at https://yarnpkg.com/corepack.', - upToDate: 'Already up-to-date.', folderInSync: 'Folder in sync.', nothingToInstall: 'Nothing to install.', From d1f7d141062332b8d5a4910810a88a296bb7e789 Mon Sep 17 00:00:00 2001 From: Calvin Huang Date: Thu, 3 Mar 2022 15:50:54 -0800 Subject: [PATCH 3/6] Update child.js --- src/util/child.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/util/child.js b/src/util/child.js index 7356f3ccbb..4e0dab44bc 100644 --- a/src/util/child.js +++ b/src/util/child.js @@ -6,6 +6,7 @@ import BlockingQueue from './blocking-queue.js'; import {ProcessSpawnError, ProcessTermError} from '../errors.js'; import {promisify} from './promise.js'; +const os = require('os'); const child = require('child_process'); const fs = require('fs'); const path = require('path'); @@ -46,8 +47,8 @@ export function forkp(program: string, args: Array, opts?: Object): Prom reject(error); }); - proc.on('close', exitCode => { - resolve(exitCode); + proc.on('close', (exitCode: number, signal: string) => { + resolve(exitCode ?? 128 + os.constants.signals[signal]); }); }); } @@ -63,8 +64,8 @@ export function spawnp(program: string, args: Array, opts?: Object): Pro reject(error); }); - proc.on('close', exitCode => { - resolve(exitCode); + proc.on('close', (exitCode: number, signal: string) => { + resolve(exitCode ?? 128 + os.constants.signals[signal]); }); }); } From 7c6a0a4968845fec7f75eddbc8b833058f4ff52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 13 Nov 2023 10:14:09 +0100 Subject: [PATCH 4/6] Prevents crashes when .yarnrc.yml is empty --- src/rc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rc.js b/src/rc.js index c8f48131c0..7da9708839 100644 --- a/src/rc.js +++ b/src/rc.js @@ -55,7 +55,7 @@ export function getRcConfigForFolder(cwd: string): {[key: string]: string} { function loadRcFile(fileText: string, filePath: string): {[key: string]: string} { let {object: values} = parse(fileText, filePath); - if (filePath.match(/\.yml$/) && typeof values.yarnPath === 'string') { + if (filePath.match(/\.yml$/) && values && typeof values.yarnPath === 'string') { values = {'yarn-path': values.yarnPath}; } From 38e3530b9c18b751ae02f868b5dbe418e3e7ad06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 13 Nov 2023 10:23:21 +0100 Subject: [PATCH 5/6] Couple of tweaks --- src/cli/index.js | 2 +- src/util/child.js | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cli/index.js b/src/cli/index.js index 84f793680c..02ca91b980 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -283,7 +283,7 @@ export async function main({ process.stderr.write( `Presence of the ${chalk.gray( `"packageManager"`, - )} field indicates that the project is meant to be used with Corepack, a tool included by default with all modern Node.js distributions.\n`, + )} field indicates that the project is meant to be used with Corepack, a tool included by default with all official Node.js distributions starting from 16.9 and 14.19.\n`, ); process.stderr.write( diff --git a/src/util/child.js b/src/util/child.js index 4e0dab44bc..3528cae463 100644 --- a/src/util/child.js +++ b/src/util/child.js @@ -48,7 +48,9 @@ export function forkp(program: string, args: Array, opts?: Object): Prom }); proc.on('close', (exitCode: number, signal: string) => { - resolve(exitCode ?? 128 + os.constants.signals[signal]); + const finalExitCode = + typeof exitCode !== `undefined` && exitCode !== null ? exitCode : 128 + os.constants.signals[signal]; + resolve(finalExitCode); }); }); } @@ -65,7 +67,9 @@ export function spawnp(program: string, args: Array, opts?: Object): Pro }); proc.on('close', (exitCode: number, signal: string) => { - resolve(exitCode ?? 128 + os.constants.signals[signal]); + const finalExitCode = + typeof exitCode !== `undefined` && exitCode !== null ? exitCode : 128 + os.constants.signals[signal]; + resolve(finalExitCode); }); }); } From 2fd6bfa231f8479d4fde95002e1f4e3a4cdb4f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 14 Nov 2023 10:19:05 +0100 Subject: [PATCH 6/6] Bumps version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 66fb61c589..7d451026f7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "yarn", "installationMethod": "unknown", - "version": "1.22.19", + "version": "1.22.20", "packageManager": "yarn@1.22.17", "license": "BSD-2-Clause", "preferGlobal": true,