diff --git a/.yarn/versions/4b2a6a48.yml b/.yarn/versions/4b2a6a48.yml new file mode 100644 index 000000000000..bf00c169c56c --- /dev/null +++ b/.yarn/versions/4b2a6a48.yml @@ -0,0 +1,30 @@ +releases: + "@yarnpkg/core": minor + "@yarnpkg/plugin-essentials": major + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-exec" + - "@yarnpkg/plugin-file" + - "@yarnpkg/plugin-git" + - "@yarnpkg/plugin-github" + - "@yarnpkg/plugin-http" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-link" + - "@yarnpkg/plugin-node-modules" + - "@yarnpkg/plugin-npm" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/cli" + - "@yarnpkg/doctor" + - "@yarnpkg/pnpify" diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/v1Migration.test.ts b/packages/acceptance-tests/pkg-tests-specs/sources/features/v1Migration.test.ts new file mode 100644 index 000000000000..ccf4ef4fd45e --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-specs/sources/features/v1Migration.test.ts @@ -0,0 +1,20 @@ +import {Filename, ppath, xfs} from '@yarnpkg/fslib'; + +describe(`Features`, () => { + describe(`V1 Migration`, () => { + test( + `it should enable the node-modules linker when migrating from v1`, + makeTemporaryEnv({ + dependencies: { + [`no-deps`]: `1.0.0`, + }, + }, async ({path, run, source}) => { + await xfs.writeFilePromise(ppath.join(path, Filename.lockfile), `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n# yarn lockfile v1\n\n\n\n`); + + await run(`install`); + + await expect(xfs.existsPromise(ppath.join(path, Filename.nodeModules, `no-deps` as Filename))).resolves.toEqual(true); + }), + ); + }); +}); diff --git a/packages/plugin-essentials/sources/commands/install.ts b/packages/plugin-essentials/sources/commands/install.ts index bf81f00d1c42..15c724035d38 100644 --- a/packages/plugin-essentials/sources/commands/install.ts +++ b/packages/plugin-essentials/sources/commands/install.ts @@ -1,8 +1,7 @@ import {BaseCommand, WorkspaceRequiredError} from '@yarnpkg/cli'; import {Configuration, Cache, MessageName, Project, ReportError, StreamReport, formatUtils} from '@yarnpkg/core'; -import {xfs, ppath} from '@yarnpkg/fslib'; +import {xfs, ppath, Filename} from '@yarnpkg/fslib'; import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; -import {TRAVIS} from 'ci-info'; import {Command, Option, Usage} from 'clipanion'; // eslint-disable-next-line arca/no-default-export @@ -193,13 +192,11 @@ export default class YarnCommand extends BaseCommand { // Note: it's been deprecated because we're now locking more than just the // lockfile - for example the PnP artifacts will also be locked. if (typeof this.frozenLockfile !== `undefined`) { - const exitCode = await reportDeprecation(`The --frozen-lockfile option is deprecated; use --immutable and/or --immutable-cache instead`, { - error: !isGCP && !TRAVIS, + await reportDeprecation(`The --frozen-lockfile option is deprecated; use --immutable and/or --immutable-cache instead`, { + error: false, }); - if (exitCode !== null) { - return exitCode; - } + this.immutable = this.frozenLockfile; } // We also want to prevent them from using --cache-folder @@ -238,6 +235,39 @@ export default class YarnCommand extends BaseCommand { } } + if (configuration.projectCwd !== null && typeof configuration.sources.get(`nodeLinker`) === `undefined`) { + const projectCwd = configuration.projectCwd; + + let content; + try { + content = await xfs.readFilePromise(ppath.join(projectCwd, Filename.lockfile), `utf8`); + } catch {} + + // If migrating from a v1 install, we automatically enable the node-modules linker, + // since that's likely what the author intended to do. + if (content?.includes(`yarn lockfile v1`)) { + const nmReport = await StreamReport.start({ + configuration, + json: this.json, + stdout: this.context.stdout, + includeFooter: false, + }, async report => { + report.reportInfo(MessageName.AUTO_NM_SUCCESS, `Migrating from Yarn 1; automatically enabling the compatibility node-modules linker 👍`); + report.reportSeparator(); + + configuration.use(``, {nodeLinker: `node-modules`}, projectCwd, {overwrite: true}); + + await Configuration.updateConfiguration(projectCwd, { + nodeLinker: `node-modules`, + }); + }); + + if (nmReport.hasErrors()) { + return nmReport.exitCode(); + } + } + } + if (configuration.projectCwd !== null) { const telemetryReport = await StreamReport.start({ configuration, diff --git a/packages/yarnpkg-core/sources/MessageName.ts b/packages/yarnpkg-core/sources/MessageName.ts index e63530c5f780..60ebccde1c68 100644 --- a/packages/yarnpkg-core/sources/MessageName.ts +++ b/packages/yarnpkg-core/sources/MessageName.ts @@ -72,6 +72,7 @@ export enum MessageName { INVALID_CONFIGURATION_VALUE = 67, UNUSED_PACKAGE_EXTENSION = 68, REDUNDANT_PACKAGE_EXTENSION = 69, + AUTO_NM_SUCCESS = 70, } export function stringifyMessageName(name: MessageName | number): string {