From a23467f29efca46e60da8ae471e447a621970987 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Wed, 17 May 2023 23:18:31 +0300 Subject: [PATCH] feat: include some settings as fields in the lockfile ref #6312 --- __fixtures__/empty/pnpm-lock.yaml | 2 +- __fixtures__/local-pkg/pnpm-lock.yaml | 2 +- __fixtures__/local-scoped-pkg/pnpm-lock.yaml | 2 +- .../pnpm-lock.yaml | 2 +- __fixtures__/pnpm-lock.yaml | 2 +- __fixtures__/tar-pkg/pnpm-lock.yaml | 2 +- .../pnpm-lock.yaml | 6 +- .../pnpm-lock.yaml | 6 +- .../implementation/extendRebuildOptions.ts | 2 + .../inlineSpecifiersLockfileConverters.ts | 4 +- lockfile/lockfile-file/src/read.ts | 6 ++ .../lockfile-file/src/sortLockfileKeys.ts | 11 +-- lockfile/lockfile-types/src/index.ts | 7 ++ packages/constants/src/index.ts | 2 +- .../src/patchCommit.ts | 8 +- .../test/patch.test.ts | 30 +++++--- .../core/src/getPeerDependencyIssues.ts | 2 +- pkg-manager/core/src/install/index.ts | 73 ++++++++++++++++--- pkg-manager/core/src/link/options.ts | 2 + pkg-manager/core/test/install/aliases.ts | 8 ++ .../core/test/install/frozenLockfile.ts | 15 ++++ pkg-manager/core/test/install/local.ts | 12 +++ pkg-manager/core/test/install/overrides.ts | 4 +- .../core/test/install/packageExtensions.ts | 4 +- pkg-manager/core/test/lockfile.ts | 22 +++++- pkg-manager/core/test/uninstall.ts | 4 + pkg-manager/get-context/src/index.ts | 8 ++ pkg-manager/get-context/src/readLockfiles.ts | 8 +- pkg-manager/get-context/test/index.ts | 2 + .../test/__snapshots__/dedupe.ts.snap | 4 +- pnpm/test/monorepo/index.ts | 8 ++ .../storeStatus/extendStoreStatusOptions.ts | 2 + 32 files changed, 220 insertions(+), 52 deletions(-) diff --git a/__fixtures__/empty/pnpm-lock.yaml b/__fixtures__/empty/pnpm-lock.yaml index 7a06cc7962b..ede21390729 100644 --- a/__fixtures__/empty/pnpm-lock.yaml +++ b/__fixtures__/empty/pnpm-lock.yaml @@ -1 +1 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' diff --git a/__fixtures__/local-pkg/pnpm-lock.yaml b/__fixtures__/local-pkg/pnpm-lock.yaml index 7a06cc7962b..ede21390729 100644 --- a/__fixtures__/local-pkg/pnpm-lock.yaml +++ b/__fixtures__/local-pkg/pnpm-lock.yaml @@ -1 +1 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' diff --git a/__fixtures__/local-scoped-pkg/pnpm-lock.yaml b/__fixtures__/local-scoped-pkg/pnpm-lock.yaml index 7a06cc7962b..ede21390729 100644 --- a/__fixtures__/local-scoped-pkg/pnpm-lock.yaml +++ b/__fixtures__/local-scoped-pkg/pnpm-lock.yaml @@ -1 +1 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' diff --git a/__fixtures__/multiple-scripts-error-exit/pnpm-lock.yaml b/__fixtures__/multiple-scripts-error-exit/pnpm-lock.yaml index 7a06cc7962b..ede21390729 100644 --- a/__fixtures__/multiple-scripts-error-exit/pnpm-lock.yaml +++ b/__fixtures__/multiple-scripts-error-exit/pnpm-lock.yaml @@ -1 +1 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' diff --git a/__fixtures__/pnpm-lock.yaml b/__fixtures__/pnpm-lock.yaml index 7a06cc7962b..ede21390729 100644 --- a/__fixtures__/pnpm-lock.yaml +++ b/__fixtures__/pnpm-lock.yaml @@ -1 +1 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' diff --git a/__fixtures__/tar-pkg/pnpm-lock.yaml b/__fixtures__/tar-pkg/pnpm-lock.yaml index 7a06cc7962b..ede21390729 100644 --- a/__fixtures__/tar-pkg/pnpm-lock.yaml +++ b/__fixtures__/tar-pkg/pnpm-lock.yaml @@ -1 +1 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' diff --git a/__fixtures__/workspace-with-lockfile-dupes/pnpm-lock.yaml b/__fixtures__/workspace-with-lockfile-dupes/pnpm-lock.yaml index dd6cb069b9c..9345ce3e786 100644 --- a/__fixtures__/workspace-with-lockfile-dupes/pnpm-lock.yaml +++ b/__fixtures__/workspace-with-lockfile-dupes/pnpm-lock.yaml @@ -1,4 +1,8 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false importers: diff --git a/__fixtures__/workspace-with-lockfile-subdep-dupes/pnpm-lock.yaml b/__fixtures__/workspace-with-lockfile-subdep-dupes/pnpm-lock.yaml index 3276bb9f7b6..4cdfbc30d81 100644 --- a/__fixtures__/workspace-with-lockfile-subdep-dupes/pnpm-lock.yaml +++ b/__fixtures__/workspace-with-lockfile-subdep-dupes/pnpm-lock.yaml @@ -1,4 +1,8 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false importers: diff --git a/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts b/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts index b51af8e9ea3..97472b735a4 100644 --- a/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts +++ b/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts @@ -6,8 +6,10 @@ import { type Registries } from '@pnpm/types' import loadJsonFile from 'load-json-file' export interface StrictRebuildOptions { + autoInstallPeers: boolean cacheDir: string childConcurrency: number + excludeLinksFromLockfile: boolean extraBinPaths: string[] extraEnv: Record lockfileDir: string diff --git a/lockfile/lockfile-file/src/experiments/inlineSpecifiersLockfileConverters.ts b/lockfile/lockfile-file/src/experiments/inlineSpecifiersLockfileConverters.ts index a48fc4ee483..f0b67c921c9 100644 --- a/lockfile/lockfile-file/src/experiments/inlineSpecifiersLockfileConverters.ts +++ b/lockfile/lockfile-file/src/experiments/inlineSpecifiersLockfileConverters.ts @@ -113,7 +113,7 @@ export function revertFromInlineSpecifiersFormat (lockfile: InlineSpecifiersLock let revertedImporters = mapValues(importers, revertProjectSnapshot) let packages = lockfile.packages - if (originalVersion === 6) { + if (originalVersionStr.startsWith('6.')) { revertedImporters = Object.fromEntries( Object.entries(revertedImporters ?? {}) .map(([importerId, pkgSnapshot]: [string, ProjectSnapshot]) => { @@ -150,7 +150,7 @@ export function revertFromInlineSpecifiersFormat (lockfile: InlineSpecifiersLock packages, importers: revertedImporters, } - if (originalVersion === 6 && newLockfile.time) { + if (originalVersionStr.startsWith('6.') && newLockfile.time) { newLockfile.time = Object.fromEntries( Object.entries(newLockfile.time) .map(([depPath, time]) => [convertLockfileV6DepPathToV5DepPath(depPath), time]) diff --git a/lockfile/lockfile-file/src/read.ts b/lockfile/lockfile-file/src/read.ts index d07b7860b51..e2fd4a4ccf9 100644 --- a/lockfile/lockfile-file/src/read.ts +++ b/lockfile/lockfile-file/src/read.ts @@ -136,6 +136,8 @@ export function createLockfileObject ( importerIds: string[], opts: { lockfileVersion: number | string + autoInstallPeers: boolean + excludeLinksFromLockfile: boolean } ) { const importers = importerIds.reduce((acc, importerId) => { @@ -148,6 +150,10 @@ export function createLockfileObject ( return { importers, lockfileVersion: opts.lockfileVersion || LOCKFILE_VERSION, + settings: { + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: opts.excludeLinksFromLockfile, + }, } } diff --git a/lockfile/lockfile-file/src/sortLockfileKeys.ts b/lockfile/lockfile-file/src/sortLockfileKeys.ts index 090efd78a01..4700919ad4e 100644 --- a/lockfile/lockfile-file/src/sortLockfileKeys.ts +++ b/lockfile/lockfile-file/src/sortLockfileKeys.ts @@ -33,12 +33,13 @@ const ORDERED_KEYS = { const ROOT_KEYS_ORDER = { lockfileVersion: 1, + settings: 2, // only and never are conflict options. - neverBuiltDependencies: 2, - onlyBuiltDependencies: 2, - overrides: 3, - packageExtensionsChecksum: 4, - patchedDependencies: 5, + neverBuiltDependencies: 3, + onlyBuiltDependencies: 3, + overrides: 4, + packageExtensionsChecksum: 5, + patchedDependencies: 6, specifiers: 10, dependencies: 11, optionalDependencies: 12, diff --git a/lockfile/lockfile-types/src/index.ts b/lockfile/lockfile-types/src/index.ts index acb12c072eb..8548bab90b2 100644 --- a/lockfile/lockfile-types/src/index.ts +++ b/lockfile/lockfile-types/src/index.ts @@ -2,6 +2,11 @@ import { type DependenciesMeta, type PatchFile } from '@pnpm/types' export type { PatchFile } +export interface LockfileSettings { + autoInstallPeers?: boolean + excludeLinksFromLockfile?: boolean +} + export interface Lockfile { importers: Record lockfileVersion: number | string @@ -12,6 +17,7 @@ export interface Lockfile { overrides?: Record packageExtensionsChecksum?: string patchedDependencies?: Record + settings?: LockfileSettings } export interface ProjectSnapshot { @@ -33,6 +39,7 @@ export interface LockfileV6 { overrides?: Record packageExtensionsChecksum?: string patchedDependencies?: Record + settings?: LockfileSettings } export interface ProjectSnapshotV6 { diff --git a/packages/constants/src/index.ts b/packages/constants/src/index.ts index d0abf24177f..7cb3ee03ee0 100644 --- a/packages/constants/src/index.ts +++ b/packages/constants/src/index.ts @@ -1,6 +1,6 @@ export const WANTED_LOCKFILE = 'pnpm-lock.yaml' export const LOCKFILE_VERSION = 5.4 -export const LOCKFILE_VERSION_V6 = '6.0' +export const LOCKFILE_VERSION_V6 = '6.1' export const ENGINE_NAME = `${process.platform}-${process.arch}-node-${process.version.split('.')[0]}` export const LAYOUT_VERSION = 5 diff --git a/patching/plugin-commands-patching/src/patchCommit.ts b/patching/plugin-commands-patching/src/patchCommit.ts index b9e5b33a348..bfb6bfcabc6 100644 --- a/patching/plugin-commands-patching/src/patchCommit.ts +++ b/patching/plugin-commands-patching/src/patchCommit.ts @@ -74,7 +74,13 @@ export async function handler (opts: install.InstallCommandOptions & Pick { }) describe('patch with custom modules-dir and virtual-store-dir', () => { - const customModulesDirFixture = tempDir() - f.copy('custom-modules-dir', customModulesDirFixture) - const cacheDir = path.resolve(customModulesDirFixture, 'cache') - const storeDir = path.resolve(customModulesDirFixture, 'store') - const defaultPatchOption = { - ...basePatchOption, - cacheDir, - dir: customModulesDirFixture, - storeDir, - modulesDir: 'fake_modules', - virtualStoreDir: 'fake_modules/.fake_store', - } + let defaultPatchOption: patch.PatchCommandOptions + let customModulesDirFixture: string + let cacheDir: string + let storeDir: string + beforeAll(() => { + customModulesDirFixture = tempDir() + f.copy('custom-modules-dir', customModulesDirFixture) + cacheDir = path.resolve(customModulesDirFixture, 'cache') + storeDir = path.resolve(customModulesDirFixture, 'store') + defaultPatchOption = { + ...basePatchOption, + cacheDir, + dir: customModulesDirFixture, + storeDir, + modulesDir: 'fake_modules', + virtualStoreDir: 'fake_modules/.fake_store', + } + }) test('should work with custom modules-dir and virtual-store-dir', async () => { const manifest = fs.readFileSync(path.join(customModulesDirFixture, 'package.json'), 'utf8') diff --git a/pkg-manager/core/src/getPeerDependencyIssues.ts b/pkg-manager/core/src/getPeerDependencyIssues.ts index 963af2059a6..728b5d2c91c 100644 --- a/pkg-manager/core/src/getPeerDependencyIssues.ts +++ b/pkg-manager/core/src/getPeerDependencyIssues.ts @@ -20,7 +20,7 @@ export type ListMissingPeersOptions = Partial | 'useGitBranchLockfile' | 'workspacePackages' > -& Pick +& Pick export async function getPeerDependencyIssues ( projects: ProjectOptions[], diff --git a/pkg-manager/core/src/install/index.ts b/pkg-manager/core/src/install/index.ts index cc05fe5513e..2b51ada00ba 100644 --- a/pkg-manager/core/src/install/index.ts +++ b/pkg-manager/core/src/install/index.ts @@ -84,6 +84,15 @@ import { getAllUniqueSpecs, getPreferredVersionsFromLockfileAndManifests } from import { linkPackages } from './link' import { reportPeerDependencyIssues } from './reportPeerDependencyIssues' +class LockfileConfigMismatchError extends PnpmError { + constructor (outdatedLockfileSettingName: string) { + super('LOCKFILE_CONFIG_MISMATCH', + `Cannot proceed with the frozen installation. The current "${outdatedLockfileSettingName!}" configuration doesn't match the value found in the lockfile`, { + hint: 'Update your lockfile using "pnpm install --no-frozen-lockfile"', + }) + } +} + const BROKEN_LOCKFILE_INTEGRITY_ERRORS = new Set([ 'ERR_PNPM_UNEXPECTED_PKG_CONTENT_IN_STORE', 'ERR_PNPM_TARBALL_INTEGRITY', @@ -317,26 +326,44 @@ export async function mutateModules ( path: path.join(opts.lockfileDir, patchFile.path), }), patchedDependencies) : undefined - let needsFullResolution = !maybeOpts.ignorePackageManifest && - lockfileIsNotUpToDate(ctx.wantedLockfile, { + const frozenLockfile = opts.frozenLockfile || + opts.frozenLockfileIfExists && ctx.existsWantedLockfile + let outdatedLockfileSettings = false + if (!opts.ignorePackageManifest) { + const outdatedLockfileSettingName = getOutdatedLockfileSetting(ctx.wantedLockfile, { + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: opts.excludeLinksFromLockfile, overrides: opts.overrides, neverBuiltDependencies: opts.neverBuiltDependencies, onlyBuiltDependencies: opts.onlyBuiltDependencies, packageExtensionsChecksum, patchedDependencies, - }) || + }) + outdatedLockfileSettings = outdatedLockfileSettingName != null + if (frozenLockfile && outdatedLockfileSettings) { + throw new LockfileConfigMismatchError(outdatedLockfileSettingName!) + } + } + let needsFullResolution = outdatedLockfileSettings || opts.fixLockfile || !ctx.wantedLockfile.lockfileVersion.toString().startsWith('6.') || opts.forceFullResolution if (needsFullResolution) { + ctx.wantedLockfile.settings = { + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: opts.excludeLinksFromLockfile, + } ctx.wantedLockfile.overrides = opts.overrides ctx.wantedLockfile.neverBuiltDependencies = opts.neverBuiltDependencies ctx.wantedLockfile.onlyBuiltDependencies = opts.onlyBuiltDependencies ctx.wantedLockfile.packageExtensionsChecksum = packageExtensionsChecksum ctx.wantedLockfile.patchedDependencies = patchedDependencies + } else if (!frozenLockfile) { + ctx.wantedLockfile.settings = { + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: opts.excludeLinksFromLockfile, + } } - const frozenLockfile = opts.frozenLockfile || - opts.frozenLockfileIfExists && ctx.existsWantedLockfile if ( !ctx.lockfileHadConflicts && !opts.fixLockfile && @@ -645,7 +672,7 @@ async function calcPatchHashes (patches: Record, lockfileDir: st }, patches) } -function lockfileIsNotUpToDate ( +function getOutdatedLockfileSetting ( lockfile: Lockfile, { neverBuiltDependencies, @@ -653,18 +680,40 @@ function lockfileIsNotUpToDate ( overrides, packageExtensionsChecksum, patchedDependencies, + autoInstallPeers, + excludeLinksFromLockfile, }: { neverBuiltDependencies?: string[] onlyBuiltDependencies?: string[] overrides?: Record packageExtensionsChecksum?: string patchedDependencies?: Record - }) { - return !equals(lockfile.overrides ?? {}, overrides ?? {}) || - !equals((lockfile.neverBuiltDependencies ?? []).sort(), (neverBuiltDependencies ?? []).sort()) || - !equals(onlyBuiltDependencies?.sort(), lockfile.onlyBuiltDependencies) || - lockfile.packageExtensionsChecksum !== packageExtensionsChecksum || - !equals(lockfile.patchedDependencies ?? {}, patchedDependencies ?? {}) + autoInstallPeers?: boolean + excludeLinksFromLockfile?: boolean + } +) { + if (!equals(lockfile.overrides ?? {}, overrides ?? {})) { + return 'overrides' + } + if (!equals((lockfile.neverBuiltDependencies ?? []).sort(), (neverBuiltDependencies ?? []).sort())) { + return 'neverBuiltDependencies' + } + if (!equals(onlyBuiltDependencies?.sort(), lockfile.onlyBuiltDependencies)) { + return 'onlyBuiltDependencies' + } + if (lockfile.packageExtensionsChecksum !== packageExtensionsChecksum) { + return 'packageExtensionsChecksum' + } + if (!equals(lockfile.patchedDependencies ?? {}, patchedDependencies ?? {})) { + return 'patchedDependencies' + } + if ((lockfile.settings?.autoInstallPeers != null && lockfile.settings.autoInstallPeers !== autoInstallPeers)) { + return 'settings.autoInstallPeers' + } + if (lockfile.settings?.excludeLinksFromLockfile != null && lockfile.settings.excludeLinksFromLockfile !== excludeLinksFromLockfile) { + return 'settings.excludeLinksFromLockfile' + } + return null } export function createObjectChecksum (obj: unknown) { diff --git a/pkg-manager/core/src/link/options.ts b/pkg-manager/core/src/link/options.ts index 49b60f9abff..6dca21a1401 100644 --- a/pkg-manager/core/src/link/options.ts +++ b/pkg-manager/core/src/link/options.ts @@ -9,7 +9,9 @@ import { import { type ReporterFunction } from '../types' interface StrictLinkOptions { + autoInstallPeers: boolean binsDir: string + excludeLinksFromLockfile: boolean force: boolean forceSharedLockfile: boolean useLockfile: boolean diff --git a/pkg-manager/core/test/install/aliases.ts b/pkg-manager/core/test/install/aliases.ts index 769825b651d..97e4a575b44 100644 --- a/pkg-manager/core/test/install/aliases.ts +++ b/pkg-manager/core/test/install/aliases.ts @@ -13,6 +13,10 @@ test('installing aliased dependency', async () => { expect(typeof project.requireModule('positive')).toBe('function') expect(await project.readLockfile()).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { negative: { specifier: 'npm:is-negative@1.0.0', @@ -70,6 +74,10 @@ test('a dependency has an aliased subdependency', async () => { expect(project.requireModule('@pnpm.e2e/pkg-with-1-aliased-dep')().name).toEqual('@pnpm.e2e/dep-of-pkg-with-1-dep') expect(await project.readLockfile()).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { '@pnpm.e2e/pkg-with-1-aliased-dep': { specifier: '^100.0.0', diff --git a/pkg-manager/core/test/install/frozenLockfile.ts b/pkg-manager/core/test/install/frozenLockfile.ts index eee4fa8ecfd..fccf04c834e 100644 --- a/pkg-manager/core/test/install/frozenLockfile.ts +++ b/pkg-manager/core/test/install/frozenLockfile.ts @@ -287,3 +287,18 @@ test('prefer-frozen-lockfile: should prefer frozen-lockfile when package has lin await projects['p1'].has('p2') await projects['p2'].has('is-negative') }) + +test('frozen-lockfile: installation fails if the value of auto-install-peers changes', async () => { + prepareEmpty() + const manifest = { + dependencies: { + 'is-positive': '^3.0.0', + }, + } + + await install(manifest, await testDefaults({ autoInstallPeers: true })) + + await expect( + install(manifest, await testDefaults({ frozenLockfile: true, autoInstallPeers: false })) + ).rejects.toThrow('Cannot proceed with the frozen installation. The current "settings.autoInstallPeers" configuration doesn\'t match the value found in the lockfile') +}) diff --git a/pkg-manager/core/test/install/local.ts b/pkg-manager/core/test/install/local.ts index ad58dbcded8..7a479a1cb84 100644 --- a/pkg-manager/core/test/install/local.ts +++ b/pkg-manager/core/test/install/local.ts @@ -45,6 +45,10 @@ test('local file', async () => { const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { 'local-pkg': { specifier: expectedSpecs['local-pkg'], @@ -88,6 +92,10 @@ test('local file via link:', async () => { const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { 'local-pkg': { specifier: expectedSpecs['local-pkg'], @@ -116,6 +124,10 @@ test('local file with symlinked node_modules', async () => { const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { 'local-pkg': { specifier: expectedSpecs['local-pkg'], diff --git a/pkg-manager/core/test/install/overrides.ts b/pkg-manager/core/test/install/overrides.ts index 8b6f20a5668..be87323743c 100644 --- a/pkg-manager/core/test/install/overrides.ts +++ b/pkg-manager/core/test/install/overrides.ts @@ -94,8 +94,8 @@ test('versions are replaced with versions specified through overrides option', a rootDir: process.cwd(), }, await testDefaults({ frozenLockfile: true, overrides })) ).rejects.toThrow( - new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE', - 'Cannot perform a frozen installation because the version of the lockfile is incompatible with this version of pnpm' + new PnpmError('LOCKFILE_CONFIG_MISMATCH', + 'Cannot proceed with the frozen installation. The current "overrides" configuration doesn\'t match the value found in the lockfile' ) ) }) diff --git a/pkg-manager/core/test/install/packageExtensions.ts b/pkg-manager/core/test/install/packageExtensions.ts index b336e8600a6..ddd58872c39 100644 --- a/pkg-manager/core/test/install/packageExtensions.ts +++ b/pkg-manager/core/test/install/packageExtensions.ts @@ -88,8 +88,8 @@ test('manifests are extended with fields specified by packageExtensions', async rootDir: process.cwd(), }, await testDefaults({ frozenLockfile: true, packageExtensions })) ).rejects.toThrow( - new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE', - 'Cannot perform a frozen installation because the version of the lockfile is incompatible with this version of pnpm' + new PnpmError('LOCKFILE_CONFIG_MISMATCH', + 'Cannot proceed with the frozen installation. The current "packageExtensionsChecksum" configuration doesn\'t match the value found in the lockfile' ) ) }) diff --git a/pkg-manager/core/test/lockfile.ts b/pkg-manager/core/test/lockfile.ts index ccff3bfcfd9..103b0b48f0f 100644 --- a/pkg-manager/core/test/lockfile.ts +++ b/pkg-manager/core/test/lockfile.ts @@ -475,6 +475,10 @@ test('scoped module from different registry', async () => { const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { '@foo/has-dep-from-same-scope': { specifier: '^1.0.0', @@ -782,6 +786,10 @@ test('packages installed via tarball URL from the default registry are normalize const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { 'is-positive': { specifier: 'https://registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', @@ -1159,6 +1167,10 @@ test('tarball domain differs from registry domain', async () => { const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { 'is-positive': { specifier: '^3.1.0', @@ -1205,6 +1217,10 @@ test('tarball installed through non-standard URL endpoint from the registry doma const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { 'is-positive': { specifier: 'https://registry.npmjs.org/is-positive/download/is-positive-3.1.0.tgz', @@ -1478,7 +1494,7 @@ test('lockfile v6', async () => { { const lockfile = await readYamlFile(WANTED_LOCKFILE) // eslint-disable-line @typescript-eslint/no-explicit-any - expect(lockfile.lockfileVersion).toBe('6.0') + expect(lockfile.lockfileVersion).toBe(LOCKFILE_VERSION) expect(lockfile.packages).toHaveProperty(['/@pnpm.e2e/pkg-with-1-dep@100.0.0']) } @@ -1486,7 +1502,7 @@ test('lockfile v6', async () => { { const lockfile = await readYamlFile(WANTED_LOCKFILE) // eslint-disable-line @typescript-eslint/no-explicit-any - expect(lockfile.lockfileVersion).toBe('6.0') + expect(lockfile.lockfileVersion).toBe(LOCKFILE_VERSION) expect(lockfile.packages).toHaveProperty(['/@pnpm.e2e/pkg-with-1-dep@100.0.0']) expect(lockfile.packages).toHaveProperty(['/@pnpm.e2e/foo@100.0.0']) } @@ -1500,7 +1516,7 @@ test('lockfile v5 is converted to lockfile v6', async () => { await install({ dependencies: { '@pnpm.e2e/pkg-with-1-dep': '100.0.0' } }, await testDefaults()) const lockfile = await readYamlFile(WANTED_LOCKFILE) // eslint-disable-line @typescript-eslint/no-explicit-any - expect(lockfile.lockfileVersion).toBe('6.0') + expect(lockfile.lockfileVersion).toBe(LOCKFILE_VERSION) expect(lockfile.packages).toHaveProperty(['/@pnpm.e2e/pkg-with-1-dep@100.0.0']) }) diff --git a/pkg-manager/core/test/uninstall.ts b/pkg-manager/core/test/uninstall.ts index 4167603e7ef..b527060bcc8 100644 --- a/pkg-manager/core/test/uninstall.ts +++ b/pkg-manager/core/test/uninstall.ts @@ -317,6 +317,10 @@ test('uninstalling a dependency from package that uses shared lockfile', async ( const lockfile = await readYamlFile(WANTED_LOCKFILE) expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, importers: { 'project-1': {}, 'project-2': { diff --git a/pkg-manager/get-context/src/index.ts b/pkg-manager/get-context/src/index.ts index dcc737cfae9..ccb75320c66 100644 --- a/pkg-manager/get-context/src/index.ts +++ b/pkg-manager/get-context/src/index.ts @@ -71,6 +71,8 @@ interface HookOptions { } export interface GetContextOptions { + autoInstallPeers: boolean + excludeLinksFromLockfile: boolean allProjects: Array confirmModulesPurge?: boolean force: boolean @@ -178,6 +180,8 @@ export async function getContext ( storeDir: opts.storeDir, virtualStoreDir, ...await readLockfiles({ + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: opts.excludeLinksFromLockfile, force: opts.force, forceSharedLockfile: opts.forceSharedLockfile, frozenLockfile: opts.frozenLockfile === true, @@ -406,6 +410,8 @@ export interface PnpmSingleContext { export async function getContextForSingleImporter ( manifest: ProjectManifest, opts: { + autoInstallPeers: boolean + excludeLinksFromLockfile: boolean force: boolean forceNewModules?: boolean forceSharedLockfile: boolean @@ -520,6 +526,8 @@ export async function getContextForSingleImporter ( storeDir, virtualStoreDir, ...await readLockfiles({ + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: opts.excludeLinksFromLockfile, force: opts.force, forceSharedLockfile: opts.forceSharedLockfile, frozenLockfile: false, diff --git a/pkg-manager/get-context/src/readLockfiles.ts b/pkg-manager/get-context/src/readLockfiles.ts index d6ebe98de1f..d79bfdc3b62 100644 --- a/pkg-manager/get-context/src/readLockfiles.ts +++ b/pkg-manager/get-context/src/readLockfiles.ts @@ -26,6 +26,8 @@ export interface PnpmContext { export async function readLockfiles ( opts: { + autoInstallPeers: boolean + excludeLinksFromLockfile: boolean force: boolean forceSharedLockfile: boolean frozenLockfile: boolean @@ -103,7 +105,11 @@ export async function readLockfiles ( })() ) const files = await Promise.all(fileReads) - const sopts = { lockfileVersion: wantedLockfileVersion } + const sopts = { + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: opts.excludeLinksFromLockfile, + lockfileVersion: wantedLockfileVersion, + } const importerIds = opts.projects.map((importer) => importer.id) const currentLockfile = files[1] ?? createLockfileObject(importerIds, sopts) for (const importerId of importerIds) { diff --git a/pkg-manager/get-context/test/index.ts b/pkg-manager/get-context/test/index.ts index fa6274c005b..b485705b6c6 100644 --- a/pkg-manager/get-context/test/index.ts +++ b/pkg-manager/get-context/test/index.ts @@ -5,6 +5,8 @@ import { type GetContextOptions } from '../src' const DEFAULT_OPTIONS: GetContextOptions = { allProjects: [], + autoInstallPeers: true, + excludeLinksFromLockfile: false, extraBinPaths: [], force: false, forceSharedLockfile: false, diff --git a/pkg-manager/plugin-commands-installation/test/__snapshots__/dedupe.ts.snap b/pkg-manager/plugin-commands-installation/test/__snapshots__/dedupe.ts.snap index 45231b38e86..a7da937024e 100644 --- a/pkg-manager/plugin-commands-installation/test/__snapshots__/dedupe.ts.snap +++ b/pkg-manager/plugin-commands-installation/test/__snapshots__/dedupe.ts.snap @@ -15,7 +15,7 @@ exports[`pnpm dedupe updates old resolutions from importers block and removes ol }, @@ -20,18 +20,6 @@ }, - "lockfileVersion": "6.0", + "lockfileVersion": "6.1", "packages": Object { - "/ajv@6.10.2": Object { - "dependencies": Object { @@ -98,7 +98,7 @@ exports[`pnpm dedupe updates old resolutions from package block 1`] = ` @@ -20,15 +20,6 @@ }, - "lockfileVersion": "6.0", + "lockfileVersion": "6.1", "packages": Object { - "/punycode@2.1.1": Object { - "dev": false, diff --git a/pnpm/test/monorepo/index.ts b/pnpm/test/monorepo/index.ts index 72b72564224..047b611a914 100644 --- a/pnpm/test/monorepo/index.ts +++ b/pnpm/test/monorepo/index.ts @@ -964,6 +964,10 @@ test("shared-workspace-lockfile: don't install dependencies in projects that are const lockfile = await readYamlFile(WANTED_LOCKFILE) expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, importers: { 'package-1': { dependencies: { @@ -1041,6 +1045,10 @@ test('shared-workspace-lockfile: install dependencies in projects that are relat const lockfile = await readYamlFile(WANTED_LOCKFILE) expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, importers: { '.': { dependencies: { diff --git a/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts b/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts index 06db4e21074..13ae869cfb5 100644 --- a/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts +++ b/store/plugin-commands-store/src/storeStatus/extendStoreStatusOptions.ts @@ -4,6 +4,8 @@ import { type Registries } from '@pnpm/types' import { type ReporterFunction } from '../types' export interface StrictStoreStatusOptions { + autoInstallPeers: boolean + excludeLinksFromLockfile: boolean lockfileDir: string dir: string storeDir: string