diff --git a/.yarn/versions/fd50b4cb.yml b/.yarn/versions/fd50b4cb.yml new file mode 100644 index 000000000000..747a4cb3e741 --- /dev/null +++ b/.yarn/versions/fd50b4cb.yml @@ -0,0 +1,34 @@ +releases: + "@yarnpkg/core": major + "@yarnpkg/plugin-nm": patch + "@yarnpkg/plugin-pnp": patch + "@yarnpkg/plugin-pnpm": patch + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@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-npm" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/cli" + - "@yarnpkg/doctor" + - "@yarnpkg/extensions" + - "@yarnpkg/nm" + - "@yarnpkg/pnpify" + - "@yarnpkg/sdks" diff --git a/CHANGELOG.md b/CHANGELOG.md index 21c7100e2c71..a77d378ea05c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ The following changes only affect people writing Yarn plugins: - The `generateLoader` function in `@yarnpkg/pnp` no longer generates the `$$SETUP_STATE` function, it now needs to be present in the `loader` passed to the function. +- The `getCustomDataKey` function in `Installer` from `@yarnpkg/core` has been moved to `Linker`. + ### Compatibility - The patched filesystem now supports `ftruncate`. diff --git a/packages/plugin-nm/sources/NodeModulesLinker.ts b/packages/plugin-nm/sources/NodeModulesLinker.ts index f46bbd4888f2..83c741fcd7ab 100644 --- a/packages/plugin-nm/sources/NodeModulesLinker.ts +++ b/packages/plugin-nm/sources/NodeModulesLinker.ts @@ -34,6 +34,13 @@ export enum NodeModulesMode { export class NodeModulesLinker implements Linker { private installStateCache: Map> = new Map(); + getCustomDataKey() { + return JSON.stringify({ + name: `NodeModulesLinker`, + version: 2, + }); + } + supportsPackage(pkg: Package, opts: MinimalLinkOptions) { return this.isEnabled(opts); } @@ -119,13 +126,6 @@ class NodeModulesInstaller implements Installer { // Nothing to do } - getCustomDataKey() { - return JSON.stringify({ - name: `NodeModulesInstaller`, - version: 2, - }); - } - private customData: { store: Map; } = { diff --git a/packages/plugin-pnp/sources/PnpLinker.ts b/packages/plugin-pnp/sources/PnpLinker.ts index 40bd524fcdd1..3f14790da215 100644 --- a/packages/plugin-pnp/sources/PnpLinker.ts +++ b/packages/plugin-pnp/sources/PnpLinker.ts @@ -24,6 +24,13 @@ export class PnpLinker implements Linker { private pnpCache: Map = new Map(); + getCustomDataKey() { + return JSON.stringify({ + name: `PnpLinker`, + version: 2, + }); + } + supportsPackage(pkg: Package, opts: MinimalLinkOptions) { return this.isEnabled(opts); } @@ -101,13 +108,6 @@ export class PnpInstaller implements Installer { this.opts = opts; } - getCustomDataKey() { - return JSON.stringify({ - name: `PnpInstaller`, - version: 2, - }); - } - private customData: { store: Map; } = { diff --git a/packages/plugin-pnpm/sources/PnpmLinker.ts b/packages/plugin-pnpm/sources/PnpmLinker.ts index 8f28458eb9cc..3fa7719b4533 100644 --- a/packages/plugin-pnpm/sources/PnpmLinker.ts +++ b/packages/plugin-pnpm/sources/PnpmLinker.ts @@ -9,6 +9,13 @@ export type PnpmCustomData = { }; export class PnpmLinker implements Linker { + getCustomDataKey() { + return JSON.stringify({ + name: `PnpmLinker`, + version: 2, + }); + } + supportsPackage(pkg: Package, opts: MinimalLinkOptions) { return this.isEnabled(opts); } @@ -17,8 +24,8 @@ export class PnpmLinker implements Linker { if (!this.isEnabled(opts)) throw new Error(`Assertion failed: Expected the pnpm linker to be enabled`); - const customDataKey = getCustomDataKey(); - const customData = opts.project.installersCustomData.get(customDataKey) as PnpmCustomData | undefined; + const customDataKey = this.getCustomDataKey(); + const customData = opts.project.linkersCustomData.get(customDataKey) as PnpmCustomData | undefined; if (!customData) throw new UsageError(`The project in ${formatUtils.pretty(opts.project.configuration, `${opts.project.cwd}/package.json`, formatUtils.Type.PATH)} doesn't seem to have been installed - running an install there might help`); @@ -33,8 +40,8 @@ export class PnpmLinker implements Linker { if (!this.isEnabled(opts)) return null; - const customDataKey = getCustomDataKey(); - const customData = opts.project.installersCustomData.get(customDataKey) as any; + const customDataKey = this.getCustomDataKey(); + const customData = opts.project.linkersCustomData.get(customDataKey) as any; if (!customData) throw new UsageError(`The project in ${formatUtils.pretty(opts.project.configuration, `${opts.project.cwd}/package.json`, formatUtils.Type.PATH)} doesn't seem to have been installed - running an install there might help`); @@ -77,10 +84,6 @@ class PnpmInstaller implements Installer { // Nothing to do } - getCustomDataKey() { - return getCustomDataKey(); - } - private customData: PnpmCustomData = { pathByLocator: new Map(), locatorByPath: new Map(), @@ -286,13 +289,6 @@ class PnpmInstaller implements Installer { } } -function getCustomDataKey() { - return JSON.stringify({ - name: `PnpmInstaller`, - version: 2, - }); -} - function getNodeModulesLocation(project: Project) { return ppath.join(project.cwd, Filename.nodeModules); } diff --git a/packages/yarnpkg-core/sources/Installer.ts b/packages/yarnpkg-core/sources/Installer.ts index d73a4a4b74b4..a460b27053fe 100644 --- a/packages/yarnpkg-core/sources/Installer.ts +++ b/packages/yarnpkg-core/sources/Installer.ts @@ -71,18 +71,6 @@ export type InstallPackageExtraApi = { }; export interface Installer { - /** - * Return an arbitrary key. - * - * This key will be used to save and restore the installer's custom data. You - * typically will want to return the installer's name, but you can be fancy - * and send a stringified JSON payload that include the cache version, etc. - * - * TODO (Yarn 4): Move this method into `Linker` so that linkers can use it - * to save some state useful to findPackageLocator (cf PnpmLinker). - */ - getCustomDataKey(): string; - /** * Only called if the installer has a custom data key matching one currently * stored. Will be called with whatever `finalizeInstall` returned in its diff --git a/packages/yarnpkg-core/sources/Linker.ts b/packages/yarnpkg-core/sources/Linker.ts index 704521a99175..bb2a47ebaf2f 100644 --- a/packages/yarnpkg-core/sources/Linker.ts +++ b/packages/yarnpkg-core/sources/Linker.ts @@ -69,6 +69,15 @@ export interface Linker { */ findPackageLocator(location: PortablePath, opts: LinkOptions): Promise; + /** + * Return an arbitrary key. + * + * This key will be used to save and restore the installer's custom data. You + * typically will want to return the installer's name, but you can be fancy + * and send a stringified JSON payload that include the cache version, etc. + */ + getCustomDataKey(): string; + /** * This function must instantiate an Installer object that describes how to * install the packages on the disk. Check the Installer file for more diff --git a/packages/yarnpkg-core/sources/Project.ts b/packages/yarnpkg-core/sources/Project.ts index 6856a1c3cd9b..29d8f7e2c0c5 100644 --- a/packages/yarnpkg-core/sources/Project.ts +++ b/packages/yarnpkg-core/sources/Project.ts @@ -47,7 +47,7 @@ const LOCKFILE_VERSION = 7; // 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 // between patch or minor releases). -const INSTALL_STATE_VERSION = 1; +const INSTALL_STATE_VERSION = 2; const MULTIPLE_KEYS_REGEXP = / *, */g; const TRAILING_SLASH_REGEXP = /\/$/; @@ -138,8 +138,8 @@ export type InstallOptions = { }; const INSTALL_STATE_FIELDS = { - restoreInstallersCustomData: [ - `installersCustomData`, + restoreLinkersCustomData: [ + `linkersCustomData`, ] as const, restoreResolutions: [ @@ -223,10 +223,10 @@ export class Project { public peerRequirements: Map = new Map(); /** - * Contains whatever data the installers (cf `Linker.ts`) want to persist + * Contains whatever data the linkers (cf `Linker.ts`) want to persist * from an install to another. */ - public installersCustomData: Map = new Map(); + public linkersCustomData: Map = new Map(); /** * Those checksums are used to detect whether the relevant files actually @@ -1048,8 +1048,8 @@ export class Project { const installers = new Map(linkers.map(linker => { const installer = linker.makeInstaller(linkerOptions); - const customDataKey = installer.getCustomDataKey(); - const customData = this.installersCustomData.get(customDataKey); + const customDataKey = linker.getCustomDataKey(); + const customData = this.linkersCustomData.get(customDataKey); if (typeof customData !== `undefined`) installer.attachCustomData(customData); @@ -1246,9 +1246,9 @@ export class Project { // Step 3: Inform our linkers that they should have all the info needed - const installersCustomData = new Map(); + const linkersCustomData = new Map(); - for (const installer of installers.values()) { + for (const [linker, installer] of installers) { const finalizeInstallData = await installer.finalizeInstall(); for (const installStatus of finalizeInstallData?.records ?? []) { @@ -1259,11 +1259,11 @@ export class Project { } if (typeof finalizeInstallData?.customData !== `undefined`) { - installersCustomData.set(installer.getCustomDataKey(), finalizeInstallData.customData); + linkersCustomData.set(linker.getCustomDataKey(), finalizeInstallData.customData); } } - this.installersCustomData = installersCustomData; + this.linkersCustomData = linkersCustomData; await miscUtils.allSettledSafe(pendingPromises); @@ -1789,7 +1789,7 @@ export class Project { this.installStateChecksum = newInstallStateChecksum; } - async restoreInstallState({restoreInstallersCustomData = true, restoreResolutions = true, restoreBuildState = true}: RestoreInstallStateOpts = {}) { + async restoreInstallState({restoreLinkersCustomData = true, restoreResolutions = true, restoreBuildState = true}: RestoreInstallStateOpts = {}) { const installStatePath = this.configuration.get(`installStatePath`); let installState: InstallState; @@ -1805,9 +1805,9 @@ export class Project { return; } - if (restoreInstallersCustomData) - if (typeof installState.installersCustomData !== `undefined`) - this.installersCustomData = installState.installersCustomData; + if (restoreLinkersCustomData) + if (typeof installState.linkersCustomData !== `undefined`) + this.linkersCustomData = installState.linkersCustomData; if (restoreBuildState) Object.assign(this, pick(installState, INSTALL_STATE_FIELDS.restoreBuildState));