diff --git a/.yarn/versions/6c7747db.yml b/.yarn/versions/6c7747db.yml new file mode 100644 index 000000000000..fa0f6cc83354 --- /dev/null +++ b/.yarn/versions/6c7747db.yml @@ -0,0 +1,34 @@ +releases: + "@yarnpkg/cli": major + "@yarnpkg/core": major + "@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-nm" + - "@yarnpkg/plugin-npm" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-pnpm" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/doctor" + - "@yarnpkg/extensions" + - "@yarnpkg/nm" + - "@yarnpkg/pnpify" + - "@yarnpkg/sdks" diff --git a/.yarnrc.yml b/.yarnrc.yml index 752b965bf1ff..f2bb15d1f523 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1,22 +1,18 @@ changesetIgnorePatterns: - - ".github/**" - - ".yarn/cache/**" + - .github/** + - .yarn/cache/** - "**/*.test.{js,ts}" - - "packages/*/tests/**" - - "packages/plugin-compat/extra/**" - - "packages/gatsby/**" + - packages/*/tests/** + - packages/plugin-compat/extra/** + - packages/gatsby/** -enableGlobalCache: false +compressionLevel: mixed -pnpEnableEsmLoader: true +enableGlobalCache: false immutablePatterns: - .pnp.* -supportedArchitectures: - os: [darwin, linux, win32] - cpu: [x64, arm64] - initScope: yarnpkg npmPublishAccess: public @@ -73,8 +69,19 @@ packageExtensions: typedoc-plugin-yarn: optional: true +pnpEnableEsmLoader: true + preferInteractive: true +supportedArchitectures: + cpu: + - x64 + - arm64 + os: + - darwin + - linux + - win32 + telemetryUserId: yarnpkg/berry yarnPath: scripts/run-yarn.js diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/commands/__snapshots__/add.test.ts.snap b/packages/acceptance-tests/pkg-tests-specs/sources/commands/__snapshots__/add.test.ts.snap deleted file mode 100644 index 7efbfa7d307d..000000000000 --- a/packages/acceptance-tests/pkg-tests-specs/sources/commands/__snapshots__/add.test.ts.snap +++ /dev/null @@ -1,39 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Commands add it should clean the cache when cache lives inside the project 1`] = ` -{ - "code": 0, - "stderr": "", - "stdout": "➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Resolution step -➤ YN0085: │ + no-deps@npm:2.0.0 -➤ YN0085: │ - no-deps@npm:1.0.0 -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0013: │ A package was added to the cache, and one was removed. -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0000: └ Completed -➤ YN0000: · Done -", -} -`; - -exports[`Commands add it should not clean the cache when cache lives inside the project but global cache is set 1`] = ` -{ - "code": 0, - "stderr": "", - "stdout": "➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Resolution step -➤ YN0085: │ + no-deps@npm:2.0.0 -➤ YN0085: │ - no-deps@npm:1.0.0 -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0013: │ A package was added to the cache (+ 0.68 KiB). -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0000: └ Completed -➤ YN0000: · Done -", -} -`; diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/commands/__snapshots__/install.test.js.snap b/packages/acceptance-tests/pkg-tests-specs/sources/commands/__snapshots__/install.test.js.snap deleted file mode 100644 index 858fe53a1df5..000000000000 --- a/packages/acceptance-tests/pkg-tests-specs/sources/commands/__snapshots__/install.test.js.snap +++ /dev/null @@ -1,112 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Commands install displays validation issues of nested workspaces 1`] = ` -{ - "code": 0, - "stderr": "", - "stdout": "➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Project validation -➤ YN0057: │ package-a-ddd35d: String bin field, but no attached package name -➤ YN0000: └ Completed -➤ YN0000: ┌ Resolution step -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0000: └ Completed -➤ YN0000: · Done with warnings -", -} -`; - -exports[`Commands install it should fetch only required packages when using \`--mode=update-lockfile\` 1`] = ` -{ - "code": 0, - "stderr": "", - "stdout": "➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Resolution step -➤ YN0085: │ + no-deps@npm:2.0.0 -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0013: │ A package was added to the cache (+ 0.68 KiB). -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0073: │ Skipped due to mode=update-lockfile -➤ YN0000: └ Completed -➤ YN0000: · Done with warnings -", -} -`; - -exports[`Commands install it should print the logs to the standard output when using --inline-builds 1`] = ` -"➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Resolution step -➤ YN0085: │ + no-deps-scripted@npm:1.0.0 -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0013: │ A package was added to the cache (+ 2.07 KiB). -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0007: │ no-deps-scripted@npm:1.0.0 must be built because it never has been before or the last one failed -➤ YN0000: │ no-deps-scripted@npm:1.0.0 STDOUT preinstall out -➤ YN0000: │ no-deps-scripted@npm:1.0.0 STDERR preinstall err -➤ YN0000: │ no-deps-scripted@npm:1.0.0 STDOUT install out -➤ YN0000: │ no-deps-scripted@npm:1.0.0 STDERR install err -➤ YN0000: │ no-deps-scripted@npm:1.0.0 STDOUT postinstall out -➤ YN0000: │ no-deps-scripted@npm:1.0.0 STDERR postinstall err -➤ YN0000: └ Completed -➤ YN0000: · Done -" -`; - -exports[`Commands install it should skip build scripts when using --mode=skip-build 1`] = ` -"➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Resolution step -➤ YN0085: │ + no-deps-scripted@npm:1.0.0 -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0013: │ A package was added to the cache (+ 2.07 KiB). -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0000: └ Completed -➤ YN0000: · Done -" -`; - -exports[`Commands install reports warning if published binary field is a path but no package name is set 1`] = ` -{ - "code": 0, - "stderr": "", - "stdout": "➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Project validation -➤ YN0057: │ root-workspace-0b6124: String bin field, but no attached package name -➤ YN0000: └ Completed -➤ YN0000: ┌ Resolution step -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0000: └ Completed -➤ YN0000: · Done with warnings -", -} -`; - -exports[`Commands install should not build virtual workspaces 1`] = ` -{ - "code": 0, - "stderr": "", - "stdout": "➤ YN0000: · Yarn 0.0.0 -➤ YN0000: ┌ Resolution step -➤ YN0085: │ + no-deps@npm:2.0.0 -➤ YN0000: └ Completed -➤ YN0000: ┌ Fetch step -➤ YN0013: │ A package was added to the cache (+ 0.68 KiB). -➤ YN0000: └ Completed -➤ YN0000: ┌ Link step -➤ YN0007: │ foo@workspace:workspace must be built because it never has been before or the last one failed -➤ YN0000: └ Completed -➤ YN0000: · Done -", -} -`; diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/commands/add.test.ts b/packages/acceptance-tests/pkg-tests-specs/sources/commands/add.test.ts index 87e9a45e2d33..445503515f8d 100644 --- a/packages/acceptance-tests/pkg-tests-specs/sources/commands/add.test.ts +++ b/packages/acceptance-tests/pkg-tests-specs/sources/commands/add.test.ts @@ -1,9 +1,6 @@ import {Filename, PortablePath, ppath, xfs} from '@yarnpkg/fslib'; - -const { - tests: {getPackageDirectoryPath}, -} = require(`pkg-tests-core`); -const {parseSyml} = require(`@yarnpkg/parsers`); +import {parseSyml} from '@yarnpkg/parsers'; +import {tests} from 'pkg-tests-core'; describe(`Commands`, () => { describe(`add`, () => { @@ -104,7 +101,7 @@ describe(`Commands`, () => { test( `it should add a new regular dependency to the current project (unnamed path)`, makeTemporaryEnv({}, async ({path, run, source}) => { - const packagePath = await getPackageDirectoryPath(`no-deps`, `1.0.0`); + const packagePath = await tests.getPackageDirectoryPath(`no-deps`, `1.0.0`); await run(`add`, packagePath); @@ -570,9 +567,7 @@ describe(`Commands`, () => { expect(preUpgradeCache.find(entry => entry.includes(`no-deps-npm-1.0.0`))).toBeDefined(); - const {code, stdout, stderr} = await run(`add`, `no-deps@2.0.0`); - - await expect({code, stdout, stderr}).toMatchSnapshot(); + await run(`add`, `no-deps@2.0.0`); const postUpgradeCache = await xfs.readdirPromise(`${path}/.yarn/cache` as PortablePath); @@ -589,15 +584,14 @@ describe(`Commands`, () => { YARN_ENABLE_GLOBAL_CACHE: `true`, YARN_GLOBAL_FOLDER: `${path}/global`, }; + await run(`install`, {env}); const preUpgradeCache = await xfs.readdirPromise(`${path}/global/cache` as PortablePath); expect(preUpgradeCache.find(entry => entry.includes(`no-deps-npm-1.0.0`))).toBeDefined(); - const {code, stdout, stderr} = await run(`add`, `no-deps@2.0.0`, {env}); - - await expect({code, stdout, stderr}).toMatchSnapshot(); + await run(`add`, `no-deps@2.0.0`, {env}); const postUpgradeCache = await xfs.readdirPromise(`${path}/global/cache` as PortablePath); diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/commands/install.test.js b/packages/acceptance-tests/pkg-tests-specs/sources/commands/install.test.ts similarity index 84% rename from packages/acceptance-tests/pkg-tests-specs/sources/commands/install.test.js rename to packages/acceptance-tests/pkg-tests-specs/sources/commands/install.test.ts index d6e2b91c0332..36fb175c4fa4 100644 --- a/packages/acceptance-tests/pkg-tests-specs/sources/commands/install.test.js +++ b/packages/acceptance-tests/pkg-tests-specs/sources/commands/install.test.ts @@ -1,8 +1,5 @@ import {Filename, xfs, ppath, npath} from '@yarnpkg/fslib'; - -const { - fs: {writeJson, writeFile}, -} = require(`pkg-tests-core`); +import {tests} from 'pkg-tests-core'; describe(`Commands`, () => { describe(`install`, () => { @@ -15,7 +12,8 @@ describe(`Commands`, () => { }, async ({path, run, source}) => { const {stdout} = await run(`install`, `--inline-builds`); - await expect(stdout).toMatchSnapshot(); + expect(stdout).toContain(`no-deps-scripted@npm:1.0.0 must be built because it never has been before`); + expect(stdout).toContain(`STDOUT preinstall out`); }), ); @@ -28,7 +26,8 @@ describe(`Commands`, () => { }, async ({path, run, source}) => { const {stdout} = await run(`install`, `--inline-builds`, `--mode=skip-build`); - await expect(stdout).toMatchSnapshot(); + expect(stdout).not.toContain(`no-deps-scripted@npm:1.0.0 must be built because it never has been before`); + expect(stdout).not.toContain(`STDOUT preinstall out`); }), ); @@ -231,7 +230,7 @@ describe(`Commands`, () => { }, async ({path, run, source}) => { await run(`install`); - await xfs.removePromise(`${path}/.yarn/cache`); + await xfs.removePromise(ppath.join(path, `.yarn/cache`)); await run(`install`, `--immutable`); }), @@ -254,7 +253,7 @@ describe(`Commands`, () => { }, }, async ({path, run, source}) => { // Ensure the cache directory exists - await xfs.mkdirPromise(`${path}/.yarn/cache`, {recursive: true}); + await xfs.mkdirPromise(ppath.join(path, `.yarn/cache`), {recursive: true}); await expect(run(`install`, `--immutable-cache`)).rejects.toThrow(/YN0056/); }), ); @@ -269,8 +268,8 @@ describe(`Commands`, () => { await run(`install`); // Empty, rather than remove the cache - await xfs.removePromise(`${path}/.yarn/cache`); - await xfs.mkdirPromise(`${path}/.yarn/cache`, {recursive: true}); + await xfs.removePromise(ppath.join(path, `.yarn/cache`)); + await xfs.mkdirPromise(ppath.join(path, `.yarn/cache`), {recursive: true}); await expect(run(`install`, `--immutable-cache`)).rejects.toThrow(/YN0056/); }), @@ -285,9 +284,9 @@ describe(`Commands`, () => { }, async ({path, run, source}) => { await run(`install`); - await xfs.writeFilePromise(`${path}/package.json`, JSON.stringify({ + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), { dependencies: {}, - }, null, 2)); + }); await expect(run(`install`, `--immutable-cache`)).rejects.toThrow(/YN0056/); }), @@ -300,8 +299,8 @@ describe(`Commands`, () => { [`no-deps`]: `1.0.0`, }, }, async ({path, run, source}) => { - let archiveName1; - let archiveName2; + let archiveName1: Filename; + let archiveName2: Filename; // First we need to detect the name that the true cache archive would have { @@ -315,7 +314,7 @@ describe(`Commands`, () => { archiveName1 = zipFiles1[0]; } - await xfs.writeJsonPromise(ppath.join(path, `package.json`), { + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), { dependencies: { [`no-deps`]: `2.0.0`, }, @@ -325,7 +324,7 @@ describe(`Commands`, () => { { await run(`install`); - const allFiles2 = await xfs.readdirPromise(`${path}/.yarn/cache`); + const allFiles2 = await xfs.readdirPromise(ppath.join(path, `.yarn/cache`)); const zipFiles2 = allFiles2.filter(file => file.endsWith(`.zip`)); // Just a sanity check, since this test is quite complex @@ -334,9 +333,9 @@ describe(`Commands`, () => { } // We need to replace the hash in the cache filename, otherwise the cache just won't find the archive - archiveName1 = archiveName1.replace(/[^-]+$/, archiveName2.match(/[^-]+$/)[0]); + archiveName1 = archiveName1.replace(/[^-]+$/, archiveName2.match(/[^-]+$/)![0]) as Filename; - await xfs.writeJsonPromise(ppath.join(path, `package.json`), { + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), { dependencies: { [`no-deps`]: `1.0.0`, }, @@ -344,13 +343,13 @@ describe(`Commands`, () => { // Then we disguise 2.0.0 as 1.0.0. The stored checksum will stay the same. { - const lockfile = await xfs.readFilePromise(`${path}/yarn.lock`, `utf8`); + const lockfile = await xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`); // Moves from "2.0.0" to "1.0.0" - await xfs.writeFilePromise(`${path}/yarn.lock`, lockfile.replace(/2\.0\.0/g, `1.0.0`)); + await xfs.writeFilePromise(ppath.join(path, Filename.lockfile), lockfile.replace(/2\.0\.0/g, `1.0.0`)); // Don't forget to rename the archive to match the name the real 1.0.0 would have - await xfs.movePromise(`${path}/.yarn/cache/${archiveName2}`, `${path}/.yarn/cache/${archiveName1}`); + await xfs.movePromise(ppath.join(path, `.yarn/cache`, archiveName2), ppath.join(path, `.yarn/cache`, archiveName1)); } // Just checking that the test is properly written: it should pass, because the lockfile checksum will match the tarballs @@ -368,7 +367,9 @@ describe(`Commands`, () => { bin: `./bin/cli.js`, }, async ({path, run, source}) => { - await expect(run(`install`)).resolves.toMatchSnapshot(); + const {stdout} = await run(`install`); + + expect(stdout).toContain(`root-workspace-0b6124: String bin field, but no attached package name`); }, ), ); @@ -380,14 +381,20 @@ describe(`Commands`, () => { workspaces: [`packages`], }, async ({path, run, source}) => { - await writeJson(`${path}/packages/package.json`, { + await xfs.mkdirPromise(ppath.join(path, `packages`), {recursive: true}); + await xfs.mkdirPromise(ppath.join(path, `packages/package-a`), {recursive: true}); + + await xfs.writeJsonPromise(ppath.join(path, `packages`, Filename.manifest), { workspaces: [`package-a`], }); - await writeJson(`${path}/packages/package-a/package.json`, { + + await xfs.writeJsonPromise(ppath.join(path, `packages/package-a`, Filename.manifest), { bin: `./bin/cli.js`, }); - await expect(run(`install`)).resolves.toMatchSnapshot(); + await expect(run(`install`)).resolves.toMatchObject({ + stdout: expect.stringContaining(`package-a-ddd35d: String bin field, but no attached package name`), + }); }, ), ); @@ -403,8 +410,9 @@ describe(`Commands`, () => { }, }, async ({path, run, source}) => { - await xfs.mkdirPromise(`${path}/workspace`); - await xfs.writeJsonPromise(`${path}/workspace/package.json`, { + await xfs.mkdirPromise(ppath.join(path, `workspace`)); + + await xfs.writeJsonPromise(ppath.join(path, `workspace`, Filename.manifest), { name: `foo`, scripts: { postinstall: `echo "foo"`, @@ -414,7 +422,10 @@ describe(`Commands`, () => { }, }); - await expect(run(`install`)).resolves.toMatchSnapshot(); + const {stdout} = await run(`install`); + + expect(stdout).toContain(`foo@workspace:workspace must be built`); + expect(stdout).not.toMatch(/foo@virtual:.* must be built/); }, ), ); @@ -658,7 +669,10 @@ describe(`Commands`, () => { [`no-deps-scripted`]: `1.0.0`, }, }, async ({path, run, source}) => { - await writeFile(`${path}/.yarnrc.yml`, `enableScripts: false`); + await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { + enableScripts: false, + }); + const {stdout} = await run(`install`, `--inline-builds`); expect(stdout).toMatch(/YN0004/g); }), @@ -676,7 +690,10 @@ describe(`Commands`, () => { }, }, }, async ({path, run, source}) => { - await writeFile(`${path}/.yarnrc.yml`, `enableScripts: false`); + await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { + enableScripts: false, + }); + const {stdout} = await run(`install`, `--inline-builds`); expect(stdout).toMatch(/YN0005/g); expect(stdout).not.toMatch(/YN0004/g); @@ -686,12 +703,13 @@ describe(`Commands`, () => { test( `it should throw a proper error if not find any locator`, makeTemporaryEnv({}, async ({path, run, source}) => { - await xfs.mkdirPromise(`${path}/non-workspace`); - await xfs.writeJsonPromise(`${path}/non-workspace/package.json`, { + await xfs.mkdirPromise(ppath.join(path, `non-workspace`)); + + await xfs.writeJsonPromise(ppath.join(path, `non-workspace`, Filename.manifest), { name: `non-workspace`, }); - await expect(run(`install`, {cwd: `${path}/non-workspace`})).rejects.toMatchObject({ + await expect(run(`install`, {cwd: ppath.join(path, `non-workspace`)})).rejects.toMatchObject({ code: 1, stdout: expect.stringMatching(/The nearest package directory \(.+\) doesn't seem to be part of the project declared in .+\./g), }); @@ -706,25 +724,28 @@ describe(`Commands`, () => { [`no-deps`]: `1.0.0`, }, }, async ({path, run, source}) => { - await run(`install`, `--mode=update-lockfile`); - - const cacheBefore = await xfs.readdirPromise(`${path}/.yarn/cache`); - expect(cacheBefore.find(entry => entry.includes(`one-fixed-dep-npm-1.0.0`))).toBeDefined(); - expect(cacheBefore.find(entry => entry.includes(`no-deps-npm-1.0.0`))).toBeDefined(); + await run(`install`); - await xfs.writeJsonPromise(`${path}/package.json`, { + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), { dependencies: { [`one-fixed-dep`]: `1.0.0`, [`no-deps`]: `2.0.0`, }, }); - await xfs.removePromise(`${path}/.yarn/cache`); - await xfs.mkdirPromise(`${path}/.yarn/cache`, {recursive: true}); - const {code, stdout, stderr} = await run(`install`, `--mode=update-lockfile`); - await expect({code, stdout, stderr}).toMatchSnapshot(); + await xfs.removePromise(ppath.join(path, `.yarn/cache`)); + await xfs.mkdirPromise(ppath.join(path, `.yarn/cache`), {recursive: true}); - const cacheAfter = await xfs.readdirPromise(`${path}/.yarn/cache`); + await expect(tests.startRegistryRecording(async () => { + await run(`install`, `--mode=update-lockfile`); + })).resolves.toEqual([{ + type: `packageTarball`, + scope: undefined, + localName: `no-deps`, + version: `2.0.0`, + }]); + + const cacheAfter = await xfs.readdirPromise(ppath.join(path, `.yarn/cache`)); expect(cacheAfter.find(entry => entry.includes(`one-fixed-dep-npm-1.0.0`))).toBeUndefined(); expect(cacheAfter.find(entry => entry.includes(`no-deps-npm-1.0.0`))).toBeUndefined(); expect(cacheAfter.find(entry => entry.includes(`no-deps-npm-2.0.0`))).toBeDefined(); @@ -738,7 +759,9 @@ describe(`Commands`, () => { [`no-deps`]: `1.0.0`, }, }, async ({path, run}) => { - await xfs.writeFilePromise(`${path}/${Filename.rc}`, `enableImmutableInstalls: true`); + await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { + enableImmutableInstalls: true, + }); const {stdout} = await run(`install`, `--mode=update-lockfile`); expect(stdout).not.toMatch(/YN0028/g); diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/commands/stage.test.js b/packages/acceptance-tests/pkg-tests-specs/sources/commands/stage.test.js index 54f9324d82b1..cb66171239bf 100644 --- a/packages/acceptance-tests/pkg-tests-specs/sources/commands/stage.test.js +++ b/packages/acceptance-tests/pkg-tests-specs/sources/commands/stage.test.js @@ -51,7 +51,7 @@ describe(`Commands`, () => { `${npath.fromPortablePath(`${path}/.yarn/global/metadata/npm/b98544/localhost/no-deps.json`)}\n`, `${npath.fromPortablePath(`${path}/.yarn/global/cache/no-deps-npm-1.0.0-cf533b267a-0.zip`)}\n`, `${npath.fromPortablePath(`${path}/.yarn/cache/.gitignore`)}\n`, - `${npath.fromPortablePath(`${path}/.yarn/cache/no-deps-npm-1.0.0-cf533b267a-e0e60294c2.zip`)}\n`, + `${npath.fromPortablePath(`${path}/.yarn/cache/no-deps-npm-1.0.0-cf533b267a-af041f19ff.zip`)}\n`, `${npath.fromPortablePath(`${path}/package.json`)}\n`, `${npath.fromPortablePath(`${path}/yarn.lock`)}\n`, ].join(``), diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/mergeConflictResolution.test.js.snap b/packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/mergeConflictResolution.test.ts.snap similarity index 97% rename from packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/mergeConflictResolution.test.js.snap rename to packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/mergeConflictResolution.test.ts.snap index aff3a79635b7..b11113c4f3c1 100644 --- a/packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/mergeConflictResolution.test.js.snap +++ b/packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/mergeConflictResolution.test.ts.snap @@ -5,7 +5,7 @@ exports[`Features Merge Conflict Resolution it should properly fix merge conflic # Manual changes might be lost - proceed with caution! __metadata: - version: 7 + version: X cacheKey: 0 "no-deps@npm:*": @@ -41,7 +41,7 @@ exports[`Features Merge Conflict Resolution it should properly fix merge conflic ➤ YN0000: ┌ Resolution step ➤ YN0000: └ Completed ➤ YN0000: ┌ Fetch step -➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.68 KiB). +➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.78 KiB). ➤ YN0000: └ Completed ➤ YN0000: ┌ Link step ➤ YN0000: └ Completed @@ -55,7 +55,7 @@ exports[`Features Merge Conflict Resolution it should properly fix merge conflic # Manual changes might be lost - proceed with caution! __metadata: - version: 7 + version: X cacheKey: 0 <<<<<<< HEAD @@ -105,7 +105,7 @@ exports[`Features Merge Conflict Resolution it should support fixing cherry-pick # Manual changes might be lost - proceed with caution! __metadata: - version: 7 + version: X cacheKey: 0 "no-deps@npm:*": @@ -141,7 +141,7 @@ exports[`Features Merge Conflict Resolution it should support fixing cherry-pick ➤ YN0000: ┌ Resolution step ➤ YN0000: └ Completed ➤ YN0000: ┌ Fetch step -➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.68 KiB). +➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.78 KiB). ➤ YN0000: └ Completed ➤ YN0000: ┌ Link step ➤ YN0000: └ Completed @@ -155,7 +155,7 @@ exports[`Features Merge Conflict Resolution it should support fixing rebase conf # Manual changes might be lost - proceed with caution! __metadata: - version: 7 + version: X cacheKey: 0 "no-deps@npm:*": @@ -191,7 +191,7 @@ exports[`Features Merge Conflict Resolution it should support fixing rebase conf ➤ YN0000: ┌ Resolution step ➤ YN0000: └ Completed ➤ YN0000: ┌ Fetch step -➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.68 KiB). +➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.78 KiB). ➤ YN0000: └ Completed ➤ YN0000: ┌ Link step ➤ YN0000: └ Completed @@ -205,7 +205,7 @@ exports[`Features Merge Conflict Resolution it shouldn't re-fetch the lockfile m # Manual changes might be lost - proceed with caution! __metadata: - version: 7 + version: X cacheKey: 0 "no-deps@npm:*": @@ -241,7 +241,7 @@ exports[`Features Merge Conflict Resolution it shouldn't re-fetch the lockfile m ➤ YN0000: ┌ Resolution step ➤ YN0000: └ Completed ➤ YN0000: ┌ Fetch step -➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.68 KiB). +➤ YN0013: │ No new packages added to the cache, but one was removed (- 0.78 KiB). ➤ YN0000: └ Completed ➤ YN0000: ┌ Link step ➤ YN0000: └ Completed diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/prunedNativeDeps.test.ts.snap b/packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/prunedNativeDeps.test.ts.snap deleted file mode 100644 index 5cb7865ade37..000000000000 --- a/packages/acceptance-tests/pkg-tests-specs/sources/features/__snapshots__/prunedNativeDeps.test.ts.snap +++ /dev/null @@ -1,78 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Features Pruned native deps should resolve all dependencies, regardless of the system 1`] = ` -"# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 7 - cacheKey: 0 - -"native-bar-x64@npm:1.0.0": - version: 1.0.0 - resolution: "native-bar-x64@npm:1.0.0" - conditions: os=bar & cpu=x64 - languageName: node - linkType: hard - -"native-foo-x64@npm:1.0.0": - version: 1.0.0 - resolution: "native-foo-x64@npm:1.0.0" - conditions: os=foo & cpu=x64 - languageName: node - linkType: hard - -"native-foo-x86@npm:1.0.0": - version: 1.0.0 - resolution: "native-foo-x86@npm:1.0.0" - conditions: os=foo & cpu=x86 - languageName: node - linkType: hard - -"native-libc-glibc@npm:1.0.0": - version: 1.0.0 - resolution: "native-libc-glibc@npm:1.0.0" - conditions: libc=glibc - languageName: node - linkType: hard - -"native-libc-musl@npm:1.0.0": - version: 1.0.0 - resolution: "native-libc-musl@npm:1.0.0" - conditions: libc=musl - languageName: node - linkType: hard - -"optional-native@npm:1.0.0": - version: 1.0.0 - resolution: "optional-native@npm:1.0.0" - dependencies: - native-bar-x64: "npm:1.0.0" - native-foo-x64: "npm:1.0.0" - native-foo-x86: "npm:1.0.0" - native-libc-glibc: "npm:1.0.0" - native-libc-musl: "npm:1.0.0" - dependenciesMeta: - native-bar-x64: - optional: true - native-foo-x64: - optional: true - native-foo-x86: - optional: true - native-libc-glibc: - optional: true - native-libc-musl: - optional: true - checksum: d70003d1b9641f671736ac28a17b1b4e7282eecd48937a8e01dbfe21eda97202ad9668476a5a8676393e596c652a063b1979a21eb05d8240963ce7f4a16afafc - languageName: node - linkType: hard - -"root-workspace-0b6124@workspace:.": - version: 0.0.0-use.local - resolution: "root-workspace-0b6124@workspace:." - dependencies: - optional-native: "npm:1.0.0" - languageName: unknown - linkType: soft -" -`; diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/compressionLevel.test.ts b/packages/acceptance-tests/pkg-tests-specs/sources/features/compressionLevel.test.ts index d0bd6b5da72e..c038129157f6 100644 --- a/packages/acceptance-tests/pkg-tests-specs/sources/features/compressionLevel.test.ts +++ b/packages/acceptance-tests/pkg-tests-specs/sources/features/compressionLevel.test.ts @@ -12,7 +12,7 @@ function computeCacheSize(cacheDir: PortablePath): number { describe(`Features`, () => { describe(`Compression Level`, () => { test( - `compression level 6 cache size should be less than default max compression cache size`, + `compressionLevel: 6 should lead to a lower cache size than compressionLevel: 9`, makeTemporaryEnv( { dependencies: { @@ -26,11 +26,19 @@ describe(`Features`, () => { await xfs.writeFilePromise(`${path}/.yarnrc.yml` as PortablePath, ``); const cacheDir = `${path}/.yarn/cache` as PortablePath; + await xfs.writeJsonPromise(`${path}/.yarnrc.yml` as PortablePath, { + compressionLevel: 9, + checksumBehavior: `update`, + }); + await run(`install`); const levelMaxCacheSize = computeCacheSize(cacheDir); - await xfs.writeFilePromise(`${path}/.yarnrc.yml` as PortablePath, `compressionLevel: 6\nchecksumBehavior: update\n`); + await xfs.writeJsonPromise(`${path}/.yarnrc.yml` as PortablePath, { + compressionLevel: 6, + checksumBehavior: `update`, + }); await run(`install`); diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/mergeConflictResolution.test.js b/packages/acceptance-tests/pkg-tests-specs/sources/features/mergeConflictResolution.test.js deleted file mode 100644 index 006415625452..000000000000 --- a/packages/acceptance-tests/pkg-tests-specs/sources/features/mergeConflictResolution.test.js +++ /dev/null @@ -1,229 +0,0 @@ -const {xfs} = require(`@yarnpkg/fslib`); -const { - exec: {execFile, execGitInit}, - fs: {writeFile}, -} = require(`pkg-tests-core`); - -const LOCKFILE_1_0_0 = ` -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - -no-deps@*: - version "1.0.0" - resolved "http://localhost:64572/no-deps/-/no-deps-1.0.0.tgz#8d556c1e3e6c953ea16689c506073d5fa26b957f" - integrity sha1-jVVsHj5slT6hZonFBgc9X6JrlX8= -`; - -const LOCKFILE_2_0_0 = ` -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - -no-deps@*: - version "2.0.0" - resolved "http://localhost:64572/no-deps/-/no-deps-2.0.0.tgz#f3b8f24d76b21b04748e6888672752b872236fa7" - integrity sha1-87jyTXayGwR0jmiIZydSuHIjb6c= -`; - -describe(`Features`, () => { - describe(`Merge Conflict Resolution`, () => { - test( - `it should properly fix merge conflicts`, - makeTemporaryEnv( - {}, - async ({path, run, source}) => { - await execGitInit({cwd: path}); - - await run(`install`); - await xfs.writeJsonPromise(`${path}/package.json`, {dependencies: {[`no-deps`]: `*`}}); - - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); - - await expect(execFile(`git`, [`merge`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); - - let lockfile = await xfs.readFilePromise(`${path}/yarn.lock`, `utf8`); - lockfile = lockfile.replace(/(checksum: ).*/g, `$1`); - - expect(lockfile).toMatchSnapshot(); - await expect(run(`install`)).resolves.toMatchSnapshot(); - }, - ), - ); - - test( - `it should properly fix merge conflicts when old is Yarn 1 and new is Yarn 2`, - makeTemporaryEnv( - {}, - async ({path, run, source}) => { - await execGitInit({cwd: path}); - - await xfs.writeJsonPromise(`${path}/package.json`, {dependencies: {[`no-deps`]: `*`}}); - await writeFile(`${path}/yarn.lock`, LOCKFILE_1_0_0); - - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); - await writeFile(`${path}/yarn.lock`, LOCKFILE_2_0_0); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `yarn2`], {cwd: path}); - await run(`install`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-yarn2`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`merge`, `2.0.0`], {cwd: path}); - - await expect(execFile(`git`, [`merge`, `yarn2`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); - - let lockfile = await xfs.readFilePromise(`${path}/yarn.lock`, `utf8`); - lockfile = lockfile.replace(/(checksum: ).*/g, `$1`); - - expect(lockfile).toMatchSnapshot(); - await expect(run(`install`)).resolves.toMatchSnapshot(); - }, - ), - ); - - test( - `it should support fixing rebase conflicts`, - makeTemporaryEnv( - {}, - async ({path, run, source}) => { - await execGitInit({cwd: path}); - - await run(`install`); - await xfs.writeJsonPromise(`${path}/package.json`, {dependencies: {[`no-deps`]: `*`}}); - - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); - - await expect(execFile(`git`, [`rebase`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); - - let lockfile = await xfs.readFilePromise(`${path}/yarn.lock`, `utf8`); - lockfile = lockfile.replace(/(checksum: ).*/g, `$1`); - lockfile = lockfile.replace(/(>>>>>>>).*(\(commit-1.0.0\))/g, `$1 0000000 $2`); - - expect(lockfile).toMatchSnapshot(); - await expect(run(`install`)).resolves.toMatchSnapshot(); - }, - ), - ); - - test( - `it should support fixing cherry-pick conflicts`, - makeTemporaryEnv( - {}, - async ({path, run, source}) => { - await execGitInit({cwd: path}); - - await run(`install`); - await xfs.writeJsonPromise(`${path}/package.json`, {dependencies: {[`no-deps`]: `*`}}); - - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); - - await expect(execFile(`git`, [`cherry-pick`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); - - let lockfile = await xfs.readFilePromise(`${path}/yarn.lock`, `utf8`); - lockfile = lockfile.replace(/(checksum: ).*/g, `$1`); - lockfile = lockfile.replace(/(>>>>>>>).*(\(commit-)/g, `$1 0000000 $2`); - - expect(lockfile).toMatchSnapshot(); - await expect(run(`install`)).resolves.toMatchSnapshot(); - }, - ), - ); - - test( - `it shouldn't re-fetch the lockfile metadata when performing simple merge conflict resolutions`, - makeTemporaryEnv( - {}, - async ({path, run, source}) => { - await execGitInit({cwd: path}); - - await run(`install`); - await xfs.writeJsonPromise(`${path}/package.json`, {dependencies: {[`no-deps`]: `*`}}); - - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); - await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); - await execFile(`git`, [`add`, `-A`], {cwd: path}); - await execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); - - await execFile(`git`, [`checkout`, `master`], {cwd: path}); - await execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); - - await expect(execFile(`git`, [`merge`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); - - let lockfile = await xfs.readFilePromise(`${path}/yarn.lock`, `utf8`); - lockfile = lockfile.replace(/(checksum: ).*/g, `$1`); - - expect(lockfile).toMatchSnapshot(); - - await expect(run(`install`, { - enableNetwork: false, - })).resolves.toMatchSnapshot(); - }, - ), - ); - }); -}); diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/mergeConflictResolution.test.ts b/packages/acceptance-tests/pkg-tests-specs/sources/features/mergeConflictResolution.test.ts new file mode 100644 index 000000000000..91ef823bee35 --- /dev/null +++ b/packages/acceptance-tests/pkg-tests-specs/sources/features/mergeConflictResolution.test.ts @@ -0,0 +1,226 @@ +import {Filename, ppath, xfs} from '@yarnpkg/fslib'; +import {exec} from 'pkg-tests-core'; + +const LOCKFILE_1_0_0 = ` +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +no-deps@*: + version "1.0.0" + resolved "http://localhost:64572/no-deps/-/no-deps-1.0.0.tgz#8d556c1e3e6c953ea16689c506073d5fa26b957f" + integrity sha1-jVVsHj5slT6hZonFBgc9X6JrlX8= +`; + +const LOCKFILE_2_0_0 = ` +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +no-deps@*: + version "2.0.0" + resolved "http://localhost:64572/no-deps/-/no-deps-2.0.0.tgz#f3b8f24d76b21b04748e6888672752b872236fa7" + integrity sha1-87jyTXayGwR0jmiIZydSuHIjb6c= +`; + +function cleanLockfile(lockfile: string) { + lockfile = lockfile.replace(/(^ {2}version: )[0-9]+$/m, `$1X`); + lockfile = lockfile.replace(/(checksum: ).*/g, `$1`); + lockfile = lockfile.replace(/(>>>>>>>).*(\(commit-[0-9].0.0\))/g, `$1 0000000 $2`); + + return lockfile; +} + +describe(`Features`, () => { + describe(`Merge Conflict Resolution`, () => { + test( + `it should properly fix merge conflicts`, + makeTemporaryEnv( + {}, + async ({path, run, source}) => { + await exec.execGitInit({cwd: path}); + + await run(`install`); + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), {dependencies: {[`no-deps`]: `*`}}); + + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); + + await expect(exec.execFile(`git`, [`merge`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); + + const lockfile = await xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`); + expect(cleanLockfile(lockfile)).toMatchSnapshot(); + + await expect(run(`install`)).resolves.toMatchSnapshot(); + }, + ), + ); + + test( + `it should properly fix merge conflicts when old is Yarn 1 and new is Yarn 2`, + makeTemporaryEnv( + {}, + async ({path, run, source}) => { + await exec.execGitInit({cwd: path}); + + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), {dependencies: {[`no-deps`]: `*`}}); + await xfs.writeFilePromise(ppath.join(path, Filename.lockfile), LOCKFILE_1_0_0); + + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); + await xfs.writeFilePromise(ppath.join(path, Filename.lockfile), LOCKFILE_2_0_0); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `yarn2`], {cwd: path}); + await run(`install`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-yarn2`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`merge`, `2.0.0`], {cwd: path}); + + await expect(exec.execFile(`git`, [`merge`, `yarn2`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); + + const lockfile = await xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`); + expect(cleanLockfile(lockfile)).toMatchSnapshot(); + + await expect(run(`install`)).resolves.toMatchSnapshot(); + }, + ), + ); + + test( + `it should support fixing rebase conflicts`, + makeTemporaryEnv( + {}, + async ({path, run, source}) => { + await exec.execGitInit({cwd: path}); + + await run(`install`); + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), {dependencies: {[`no-deps`]: `*`}}); + + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); + + await expect(exec.execFile(`git`, [`rebase`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); + + const lockfile = await xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`); + expect(cleanLockfile(lockfile)).toMatchSnapshot(); + + await expect(run(`install`)).resolves.toMatchSnapshot(); + }, + ), + ); + + test( + `it should support fixing cherry-pick conflicts`, + makeTemporaryEnv( + {}, + async ({path, run, source}) => { + await exec.execGitInit({cwd: path}); + + await run(`install`); + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), {dependencies: {[`no-deps`]: `*`}}); + + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); + + await expect(exec.execFile(`git`, [`cherry-pick`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); + + const lockfile = await xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`); + expect(cleanLockfile(lockfile)).toMatchSnapshot(); + + await expect(run(`install`)).resolves.toMatchSnapshot(); + }, + ), + ); + + test( + `it shouldn't re-fetch the lockfile metadata when performing simple merge conflict resolutions`, + makeTemporaryEnv( + {}, + async ({path, run, source}) => { + await exec.execGitInit({cwd: path}); + + await run(`install`); + await xfs.writeJsonPromise(ppath.join(path, Filename.manifest), {dependencies: {[`no-deps`]: `*`}}); + + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `my-commit`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `1.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:1.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-1.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`checkout`, `-b`, `2.0.0`], {cwd: path}); + await run(`set`, `resolution`, `no-deps@npm:*`, `npm:2.0.0`); + await exec.execFile(`git`, [`add`, `-A`], {cwd: path}); + await exec.execFile(`git`, [`commit`, `-a`, `-m`, `commit-2.0.0`], {cwd: path}); + + await exec.execFile(`git`, [`checkout`, `master`], {cwd: path}); + await exec.execFile(`git`, [`merge`, `1.0.0`], {cwd: path}); + + await expect(exec.execFile(`git`, [`merge`, `2.0.0`], {cwd: path, env: {LC_ALL: `C`}})).rejects.toThrow(/CONFLICT/); + + const lockfile = await xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`); + expect(cleanLockfile(lockfile)).toMatchSnapshot(); + + await expect(run(`install`, { + enableNetwork: false, + })).resolves.toMatchSnapshot(); + }, + ), + ); + }); +}); diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/features/prunedNativeDeps.test.ts b/packages/acceptance-tests/pkg-tests-specs/sources/features/prunedNativeDeps.test.ts index 2d58af9fa476..99bbcdffb0fe 100644 --- a/packages/acceptance-tests/pkg-tests-specs/sources/features/prunedNativeDeps.test.ts +++ b/packages/acceptance-tests/pkg-tests-specs/sources/features/prunedNativeDeps.test.ts @@ -1,4 +1,5 @@ import {Filename, ppath, xfs} from '@yarnpkg/fslib'; +import {parseSyml} from '@yarnpkg/parsers'; import {tests} from 'pkg-tests-core'; const {RequestType, startRegistryRecording} = tests; @@ -22,7 +23,18 @@ describe(`Features`, () => { await run(`install`); - await expect(xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`)).resolves.toMatchSnapshot(); + const file = parseSyml(await xfs.readFilePromise(ppath.join(path, Filename.lockfile), `utf8`)); + + expect(Object.keys(file)).toEqual([ + `__metadata`, + `native-bar-x64@npm:1.0.0`, + `native-foo-x64@npm:1.0.0`, + `native-foo-x86@npm:1.0.0`, + `native-libc-glibc@npm:1.0.0`, + `native-libc-musl@npm:1.0.0`, + `optional-native@npm:1.0.0`, + `root-workspace-0b6124@workspace:.`, + ]); })); it(`shouldn't fetch packages that it won't need`, makeTemporaryEnv({ diff --git a/packages/gatsby/content/advanced/error-codes.md b/packages/gatsby/content/advanced/error-codes.md index 7b0b807153f4..3ead354b7e8a 100644 --- a/packages/gatsby/content/advanced/error-codes.md +++ b/packages/gatsby/content/advanced/error-codes.md @@ -424,3 +424,9 @@ To use it, simply pass it the `p`-prefixed code provided in the original peer re ``` yarn explain peer-requirements pf649cd ``` + +## YN0087 - `MIGRATION_SUCCESS` + +When migrating from a major version to the next, some default values may change. When that's the case, Yarn will attempt to temporarily keep the old default by pinning their values in your configuration settings. + +To see the exact changes applied when this message appears, check the content of the `.yarnrc.yml` file and any other file that may appear modified in your repository checkout. diff --git a/packages/plugin-essentials/sources/commands/install.ts b/packages/plugin-essentials/sources/commands/install.ts index 9b7e27de93ea..a86bae68f526 100644 --- a/packages/plugin-essentials/sources/commands/install.ts +++ b/packages/plugin-essentials/sources/commands/install.ts @@ -1,10 +1,28 @@ -import {BaseCommand, WorkspaceRequiredError} from '@yarnpkg/cli'; -import {Configuration, Cache, MessageName, Project, ReportError, StreamReport, formatUtils, InstallMode, execUtils, structUtils, LEGACY_PLUGINS} from '@yarnpkg/core'; -import {xfs, ppath, Filename, PortablePath} from '@yarnpkg/fslib'; -import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; -import CI from 'ci-info'; -import {Command, Option, Usage, UsageError} from 'clipanion'; -import * as t from 'typanion'; +import {BaseCommand, WorkspaceRequiredError} from '@yarnpkg/cli'; +import {Configuration, Cache, MessageName, Project, ReportError, StreamReport, formatUtils, InstallMode, execUtils, structUtils, LEGACY_PLUGINS, ConfigurationValueMap} from '@yarnpkg/core'; +import {xfs, ppath, Filename, PortablePath} from '@yarnpkg/fslib'; +import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; +import CI from 'ci-info'; +import {Command, Option, Usage, UsageError} from 'clipanion'; +import * as t from 'typanion'; + +const LOCKFILE_MIGRATION_RULES: Array<{ + selector: (version: number) => boolean; + name: keyof ConfigurationValueMap; + value: any; +}> = [{ + selector: v => v === -1, + name: `nodeLinker`, + value: `node-modules`, +}, { + selector: v => v !== -1 && v < 8, + name: `enableGlobalCache`, + value: false, +}, { + selector: v => v !== -1 && v < 8, + name: `compressionLevel`, + value: `mixed`, +}]; // eslint-disable-next-line arca/no-default-export export default class YarnCommand extends BaseCommand { @@ -264,39 +282,6 @@ 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, @@ -317,6 +302,37 @@ export default class YarnCommand extends BaseCommand { } const {project, workspace} = await Project.find(configuration, this.context.cwd); + + const lockfileLastVersion = project.lockfileLastVersion; + if (lockfileLastVersion !== null) { + const compatReport = await StreamReport.start({ + configuration, + json: this.json, + stdout: this.context.stdout, + includeFooter: false, + }, async report => { + const newSettings: Record = {}; + + for (const rule of LOCKFILE_MIGRATION_RULES) { + if (rule.selector(lockfileLastVersion) && typeof configuration.sources.get(rule.name) === `undefined`) { + configuration.use(``, {[rule.name]: rule.value}, project.cwd, {overwrite: true}); + newSettings[rule.name] = rule.value; + } + } + + if (Object.keys(newSettings).length > 0) { + await Configuration.updateConfiguration(project.cwd, newSettings); + + report.reportInfo(MessageName.MIGRATION_SUCCESS, `Migrated your project to the latest Yarn version 🚀`); + report.reportSeparator(); + } + }); + + if (compatReport.hasErrors()) { + return compatReport.exitCode(); + } + } + const cache = await Cache.find(configuration, {immutable: immutableCache, check: this.checkCache}); if (!workspace) diff --git a/packages/yarnpkg-core/sources/Cache.ts b/packages/yarnpkg-core/sources/Cache.ts index b46e84dd0a52..8042b4af4bc3 100644 --- a/packages/yarnpkg-core/sources/Cache.ts +++ b/packages/yarnpkg-core/sources/Cache.ts @@ -1,6 +1,6 @@ import {FakeFS, LazyFS, NodeFS, PortablePath, Filename, AliasFS} from '@yarnpkg/fslib'; import {ppath, xfs} from '@yarnpkg/fslib'; -import {DEFAULT_COMPRESSION_LEVEL, ZipFS} from '@yarnpkg/libzip'; +import {ZipFS} from '@yarnpkg/libzip'; import {randomBytes} from 'crypto'; import fs from 'fs'; @@ -74,7 +74,7 @@ export class Cache { this.cacheKey = `${cacheKeyOverride}`; } else { const compressionLevel = configuration.get(`compressionLevel`); - const compressionKey = compressionLevel !== DEFAULT_COMPRESSION_LEVEL + const compressionKey = compressionLevel !== `mixed` ? `c${compressionLevel}` : ``; this.cacheKey = [ diff --git a/packages/yarnpkg-core/sources/Configuration.ts b/packages/yarnpkg-core/sources/Configuration.ts index 09009257943d..01d1b202088e 100644 --- a/packages/yarnpkg-core/sources/Configuration.ts +++ b/packages/yarnpkg-core/sources/Configuration.ts @@ -1,5 +1,4 @@ import {Filename, PortablePath, npath, ppath, xfs} from '@yarnpkg/fslib'; -import {DEFAULT_COMPRESSION_LEVEL} from '@yarnpkg/libzip'; import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; import camelcase from 'camelcase'; import {isCI, isPR, GITHUB_ACTIONS} from 'ci-info'; @@ -221,7 +220,7 @@ export const coreDefinitions: {[coreSettingName: string]: SettingsDefinition} = description: `Zip files compression level, from 0 to 9 or mixed (a variant of 9, which stores some files uncompressed, when compression doesn't yield good results)`, type: SettingsType.NUMBER, values: [`mixed`, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], - default: DEFAULT_COMPRESSION_LEVEL, + default: 0, }, virtualFolder: { description: `Folder where the virtual packages (cf doc) will be mapped on the disk (must be named __virtual__)`, diff --git a/packages/yarnpkg-core/sources/MessageName.ts b/packages/yarnpkg-core/sources/MessageName.ts index 33ceddf7e7ae..a8844ab283c9 100644 --- a/packages/yarnpkg-core/sources/MessageName.ts +++ b/packages/yarnpkg-core/sources/MessageName.ts @@ -98,6 +98,7 @@ export enum MessageName { CONSTRAINTS_CHECK_FAILED = 84, UPDATED_RESOLUTION_RECORD = 85, EXPLAIN_PEER_DEPENDENCIES_CTA = 86, + MIGRATION_SUCCESS = 87, } export function stringifyMessageName(name: MessageName | number): string { diff --git a/packages/yarnpkg-core/sources/Project.ts b/packages/yarnpkg-core/sources/Project.ts index 942d51098a29..262dce5707e6 100644 --- a/packages/yarnpkg-core/sources/Project.ts +++ b/packages/yarnpkg-core/sources/Project.ts @@ -44,7 +44,7 @@ import {IdentHash, DescriptorHash, LocatorHash, PackageExtensionStatus} from './ // When upgraded, the lockfile entries have to be resolved again (but the specific // versions are still pinned, no worry). Bump it when you change the fields within // the Package type; no more no less. -const LOCKFILE_VERSION = 7; +const LOCKFILE_VERSION = 8; // Same thing but must be bumped when the members of the Project class changes (we // don't recommend our users to check-in this file, so it's fine to bump it even @@ -232,6 +232,7 @@ export class Project { * If true, the data contained within `originalPackages` are from a different * lockfile version and need to be refreshed. */ + public lockfileLastVersion: number | null = null; public lockfileNeedsRefresh: boolean = false; /** @@ -340,6 +341,7 @@ export class Project { const lockfileVersion = parsed.__metadata.version; const cacheKey = parsed.__metadata.cacheKey; + this.lockfileLastVersion = lockfileVersion; this.lockfileNeedsRefresh = lockfileVersion < LOCKFILE_VERSION; for (const key of Object.keys(parsed)) { @@ -395,6 +397,8 @@ export class Project { this.storedResolutions.set(descriptor.descriptorHash, locator.locatorHash); } } + } else if (content.includes(`yarn lockfile v1`)) { + this.lockfileLastVersion = -1; } } } diff --git a/yarn.lock b/yarn.lock index b3bd0e15cf53..ffa5516f51cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # Manual changes might be lost - proceed with caution! __metadata: - version: 7 + version: 8 cacheKey: 10 "@actions/core@npm:^1.2.6":