From 38985c7610d3b3e84d9237612591b7087565cad2 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Sun, 21 May 2023 02:40:39 +0300 Subject: [PATCH] feat: include some settings as fields in the lockfile (#6557) ref #6312 close #6609 --- .changeset/fast-news-deliver.md | 15 ++++ .changeset/itchy-moons-approve.md | 5 ++ .changeset/sharp-trees-pretend.md | 5 ++ .changeset/short-coats-fetch.md | 5 ++ .changeset/tender-candles-sleep.md | 7 ++ .../implementation/extendRebuildOptions.ts | 2 + .../inlineSpecifiersLockfileConverters.ts | 4 +- lockfile/lockfile-file/src/read.ts | 5 ++ .../lockfile-file/src/sortLockfileKeys.ts | 11 +-- lockfile/lockfile-types/src/index.ts | 6 ++ 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 | 70 +++++++++++++++---- 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 | 20 +++++- pkg-manager/core/test/uninstall.ts | 4 ++ pkg-manager/get-context/src/index.ts | 4 ++ pkg-manager/get-context/src/readLockfiles.ts | 6 +- pkg-manager/get-context/test/index.ts | 2 + pnpm/test/monorepo/index.ts | 8 +++ .../storeStatus/extendStoreStatusOptions.ts | 2 + 28 files changed, 227 insertions(+), 41 deletions(-) create mode 100644 .changeset/fast-news-deliver.md create mode 100644 .changeset/itchy-moons-approve.md create mode 100644 .changeset/sharp-trees-pretend.md create mode 100644 .changeset/short-coats-fetch.md create mode 100644 .changeset/tender-candles-sleep.md diff --git a/.changeset/fast-news-deliver.md b/.changeset/fast-news-deliver.md new file mode 100644 index 00000000000..4e9d82054cf --- /dev/null +++ b/.changeset/fast-news-deliver.md @@ -0,0 +1,15 @@ +--- +"@pnpm/lockfile-types": minor +"@pnpm/lockfile-file": minor +"@pnpm/core": minor +"pnpm": minor +--- + +Some settings influence the structure of the lockfile, so we cannot reuse the lockfile if those settings change. As a result, we need to store such settings in the lockfile. This way we will know with which settings the lockfile has been created. + +A new field will now be present in the lockfile: `settings`. It will store the values of two settings: `autoInstallPeers` and `excludeLinksFromLockfile`. If someone tries to perform a `frozen-lockfile` installation and their active settings don't match the ones in the lockfile, then an error message will be thrown. + +The lockfile format version is bumped from v6.0 to v6.1. + +Related PR: [#6557](https://github.com/pnpm/pnpm/pull/6557) +Related issue: [#6312](https://github.com/pnpm/pnpm/issues/6312) diff --git a/.changeset/itchy-moons-approve.md b/.changeset/itchy-moons-approve.md new file mode 100644 index 00000000000..8b117afc643 --- /dev/null +++ b/.changeset/itchy-moons-approve.md @@ -0,0 +1,5 @@ +--- +"@pnpm/lockfile-file": patch +--- + +Convertion should work for all lockfile v6 formats, not just 6.0. diff --git a/.changeset/sharp-trees-pretend.md b/.changeset/sharp-trees-pretend.md new file mode 100644 index 00000000000..dda819b29ae --- /dev/null +++ b/.changeset/sharp-trees-pretend.md @@ -0,0 +1,5 @@ +--- +"@pnpm/constants": minor +--- + +Bump lockfile v6 version to v6.1. diff --git a/.changeset/short-coats-fetch.md b/.changeset/short-coats-fetch.md new file mode 100644 index 00000000000..4b0cdc87e09 --- /dev/null +++ b/.changeset/short-coats-fetch.md @@ -0,0 +1,5 @@ +--- +"@pnpm/plugin-commands-patching": patch +--- + +Don't run install with the `frozen-lockfile=true` setting. diff --git a/.changeset/tender-candles-sleep.md b/.changeset/tender-candles-sleep.md new file mode 100644 index 00000000000..60fc0bad791 --- /dev/null +++ b/.changeset/tender-candles-sleep.md @@ -0,0 +1,7 @@ +--- +"@pnpm/plugin-commands-rebuild": major +"@pnpm/plugin-commands-store": major +"@pnpm/get-context": major +--- + +New required options added: autoInstallPeers and excludeLinksFromLockfile. diff --git a/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts b/exec/plugin-commands-rebuild/src/implementation/extendRebuildOptions.ts index 72a42e57085..1c486980fc9 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..7ae7adfce45 100644 --- a/lockfile/lockfile-file/src/read.ts +++ b/lockfile/lockfile-file/src/read.ts @@ -136,6 +136,7 @@ export function createLockfileObject ( importerIds: string[], opts: { lockfileVersion: number | string + autoInstallPeers: boolean } ) { const importers = importerIds.reduce((acc, importerId) => { @@ -148,6 +149,10 @@ export function createLockfileObject ( return { importers, lockfileVersion: opts.lockfileVersion || LOCKFILE_VERSION, + settings: { + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: false, + }, } } 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 ea656741b1f..369597097cf 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 { 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..a8ed9b9b323 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 669e479fefb..9e296f5675b 100644 --- a/pkg-manager/core/src/install/index.ts +++ b/pkg-manager/core/src/install/index.ts @@ -83,6 +83,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', @@ -311,25 +320,42 @@ export async function mutateModules ( if (opts.useLockfileV6 == null) { opts.useLockfileV6 = ctx.wantedLockfile.lockfileVersion.toString().startsWith('6.') } - 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, 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 || opts.useLockfileV6 && !ctx.wantedLockfile.lockfileVersion.toString().startsWith('6.') if (needsFullResolution) { + ctx.wantedLockfile.settings = { + autoInstallPeers: opts.autoInstallPeers, + excludeLinksFromLockfile: false, + } 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: false, + } } - const frozenLockfile = opts.frozenLockfile || - opts.frozenLockfileIfExists && ctx.existsWantedLockfile if ( !ctx.lockfileHadConflicts && !opts.fixLockfile && @@ -619,7 +645,7 @@ async function calcPatchHashes (patches: Record, lockfileDir: st }, patches) } -function lockfileIsNotUpToDate ( +function getOutdatedLockfileSetting ( lockfile: Lockfile, { neverBuiltDependencies, @@ -627,18 +653,38 @@ function lockfileIsNotUpToDate ( overrides, packageExtensionsChecksum, patchedDependencies, + autoInstallPeers, }: { 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 + } +) { + 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) { + 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 ae2571c7261..2fb2f9bfa66 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: '/is-negative/1.0.0', positive: '/is-positive/3.1.0', @@ -68,6 +72,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': '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 7b7d55e91fa..ee0bb8e9f31 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': 'link:../local-pkg', }, @@ -86,6 +90,10 @@ test('local file via link:', async () => { const lockfile = await project.readLockfile() expect(lockfile).toStrictEqual({ + settings: { + autoInstallPeers: true, + excludeLinksFromLockfile: false, + }, dependencies: { 'local-pkg': 'link:../local-pkg', }, @@ -112,6 +120,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': 'link:../local-pkg', }, diff --git a/pkg-manager/core/test/install/overrides.ts b/pkg-manager/core/test/install/overrides.ts index c0e1edd493d..f50c0b90a97 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 lockfile needs updates' + 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 ad3b1ceb4b1..3e4e2dfb711 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 lockfile needs updates' + 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 5fcf68f5265..c63a219379a 100644 --- a/pkg-manager/core/test/lockfile.ts +++ b/pkg-manager/core/test/lockfile.ts @@ -454,6 +454,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': '1.0.0', '@zkochan/foo': '1.0.0', @@ -757,6 +761,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': '@registry.npmjs.org/is-positive/-/is-positive-1.0.0.tgz', '@pnpm.e2e/pkg-with-tarball-dep-from-registry': '1.0.0', @@ -1130,6 +1138,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': 'registry.npmjs.org/is-positive/3.1.0', }, @@ -1174,6 +1186,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': '@registry.npmjs.org/is-positive/download/is-positive-3.1.0.tgz', }, @@ -1446,7 +1462,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']) } @@ -1454,7 +1470,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']) } diff --git a/pkg-manager/core/test/uninstall.ts b/pkg-manager/core/test/uninstall.ts index 414691fe87a..98ad9817842 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': { specifiers: {}, diff --git a/pkg-manager/get-context/src/index.ts b/pkg-manager/get-context/src/index.ts index 1da6a029336..bf580d64d96 100644 --- a/pkg-manager/get-context/src/index.ts +++ b/pkg-manager/get-context/src/index.ts @@ -69,6 +69,7 @@ interface HookOptions { } export interface GetContextOptions { + autoInstallPeers: boolean allProjects: Array force: boolean forceNewModules?: boolean @@ -176,6 +177,7 @@ export async function getContext ( storeDir: opts.storeDir, virtualStoreDir, ...await readLockfiles({ + autoInstallPeers: opts.autoInstallPeers, force: opts.force, forceSharedLockfile: opts.forceSharedLockfile, frozenLockfile: opts.frozenLockfile === true, @@ -373,6 +375,7 @@ export interface PnpmSingleContext { export async function getContextForSingleImporter ( manifest: ProjectManifest, opts: { + autoInstallPeers: boolean force: boolean forceNewModules?: boolean forceSharedLockfile: boolean @@ -486,6 +489,7 @@ export async function getContextForSingleImporter ( storeDir, virtualStoreDir, ...await readLockfiles({ + autoInstallPeers: opts.autoInstallPeers, 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 a6231fcf3da..ffa18b709b1 100644 --- a/pkg-manager/get-context/src/readLockfiles.ts +++ b/pkg-manager/get-context/src/readLockfiles.ts @@ -25,6 +25,7 @@ export interface PnpmContext { export async function readLockfiles ( opts: { + autoInstallPeers: boolean force: boolean forceSharedLockfile: boolean frozenLockfile: boolean @@ -103,7 +104,10 @@ export async function readLockfiles ( })() ) const files = await Promise.all(fileReads) - const sopts = { lockfileVersion: wantedLockfileVersion } + const sopts = { + autoInstallPeers: opts.autoInstallPeers, + 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/pnpm/test/monorepo/index.ts b/pnpm/test/monorepo/index.ts index e859352a7ca..0aeb9912fa3 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: { @@ -1039,6 +1043,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