From 4361aea34cbbdc02ffaf0887b1c7512fb285ee52 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Thu, 28 Jul 2022 15:12:57 +0300 Subject: [PATCH] fix: don't include specifiers field in new experimental lockfile format (#5110) * fix: don't include specifiers field in new experimental lockfile format * test(lockfile-file): update arguments in normalizeLockfile test * test: lockfile-file Co-authored-by: Brandon Cheng --- packages/lockfile-file/src/write.ts | 31 ++++++++---- .../test/normalizeLockfile.test.ts | 47 ++++++++++++++++++- .../src/satisfiesPackageManifest.ts | 2 +- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/packages/lockfile-file/src/write.ts b/packages/lockfile-file/src/write.ts index 78ef036606..28a9d37f8e 100644 --- a/packages/lockfile-file/src/write.ts +++ b/packages/lockfile-file/src/write.ts @@ -72,13 +72,16 @@ async function writeLockfile ( ? convertToInlineSpecifiersFormat(wantedLockfile) as unknown as Lockfile : wantedLockfile - const yamlDoc = yamlStringify(lockfileToStringify, opts?.forceSharedFormat === true) + const yamlDoc = yamlStringify(lockfileToStringify, { + forceSharedFormat: opts?.forceSharedFormat === true, + includeEmptySpecifiersField: !opts?.useInlineSpecifiersFormat, + }) return writeFileAtomic(lockfilePath, yamlDoc) } -function yamlStringify (lockfile: Lockfile, forceSharedFormat: boolean) { - let normalizedLockfile = normalizeLockfile(lockfile, forceSharedFormat) +function yamlStringify (lockfile: Lockfile, opts: NormalizeLockfileOpts) { + let normalizedLockfile = normalizeLockfile(lockfile, opts) normalizedLockfile = sortLockfileKeys(normalizedLockfile) return yaml.dump(normalizedLockfile, LOCKFILE_YAML_FORMAT) } @@ -89,9 +92,14 @@ function isEmptyLockfile (lockfile: Lockfile) { export type LockfileFile = Omit & Partial & Partial> -export function normalizeLockfile (lockfile: Lockfile, forceSharedFormat: boolean) { +export interface NormalizeLockfileOpts { + forceSharedFormat: boolean + includeEmptySpecifiersField: boolean +} + +export function normalizeLockfile (lockfile: Lockfile, opts: NormalizeLockfileOpts) { let lockfileToSave!: LockfileFile - if (!forceSharedFormat && equals(Object.keys(lockfile.importers), ['.'])) { + if (!opts.forceSharedFormat && equals(Object.keys(lockfile.importers), ['.'])) { lockfileToSave = { ...lockfile, ...lockfile.importers['.'], @@ -110,8 +118,9 @@ export function normalizeLockfile (lockfile: Lockfile, forceSharedFormat: boolea ...lockfile, importers: Object.keys(lockfile.importers).reduce((acc, alias) => { const importer = lockfile.importers[alias] - const normalizedImporter: ProjectSnapshot = { - specifiers: importer.specifiers ?? {}, + const normalizedImporter: Partial = {} + if (!isEmpty(importer.specifiers ?? {}) || opts.includeEmptySpecifiersField) { + normalizedImporter['specifiers'] = importer.specifiers ?? {} } if (importer.dependenciesMeta != null && !isEmpty(importer.dependenciesMeta)) { normalizedImporter['dependenciesMeta'] = importer.dependenciesMeta @@ -183,7 +192,11 @@ export default async function writeLockfiles ( const wantedLockfileToStringify = (opts.useInlineSpecifiersFormat ?? false) ? convertToInlineSpecifiersFormat(opts.wantedLockfile) as unknown as Lockfile : opts.wantedLockfile - const yamlDoc = yamlStringify(wantedLockfileToStringify, forceSharedFormat) + const normalizeOpts = { + forceSharedFormat, + includeEmptySpecifiersField: !opts.useInlineSpecifiersFormat, + } + const yamlDoc = yamlStringify(wantedLockfileToStringify, normalizeOpts) // in most cases the `pnpm-lock.yaml` and `node_modules/.pnpm-lock.yaml` are equal // in those cases the YAML document can be stringified only once for both files @@ -204,7 +217,7 @@ export default async function writeLockfiles ( prefix: opts.wantedLockfileDir, }) - const currentYamlDoc = yamlStringify(opts.currentLockfile, forceSharedFormat) + const currentYamlDoc = yamlStringify(opts.currentLockfile, normalizeOpts) await Promise.all([ writeFileAtomic(wantedLockfilePath, yamlDoc), diff --git a/packages/lockfile-file/test/normalizeLockfile.test.ts b/packages/lockfile-file/test/normalizeLockfile.test.ts index 4d42c537b0..fb693a204c 100644 --- a/packages/lockfile-file/test/normalizeLockfile.test.ts +++ b/packages/lockfile-file/test/normalizeLockfile.test.ts @@ -20,7 +20,10 @@ test('empty overrides and neverBuiltDependencies are removed during lockfile nor }, }, }, - }, false)).toStrictEqual({ + }, { + forceSharedFormat: false, + includeEmptySpecifiersField: false, + })).toStrictEqual({ lockfileVersion: LOCKFILE_VERSION, onlyBuiltDependencies: [], importers: { @@ -35,3 +38,45 @@ test('empty overrides and neverBuiltDependencies are removed during lockfile nor }, }) }) + +test('empty specifiers field is preserved', () => { + expect(normalizeLockfile({ + lockfileVersion: LOCKFILE_VERSION, + packages: {}, + importers: { + foo: { + specifiers: {}, + }, + }, + }, { + forceSharedFormat: false, + includeEmptySpecifiersField: true, + })).toStrictEqual({ + lockfileVersion: LOCKFILE_VERSION, + importers: { + foo: { + specifiers: {}, + }, + }, + }) +}) + +test('empty specifiers field is removed', () => { + expect(normalizeLockfile({ + lockfileVersion: LOCKFILE_VERSION, + packages: {}, + importers: { + foo: { + specifiers: {}, + }, + }, + }, { + forceSharedFormat: false, + includeEmptySpecifiersField: false, + })).toStrictEqual({ + lockfileVersion: LOCKFILE_VERSION, + importers: { + foo: {}, + }, + }) +}) diff --git a/packages/lockfile-utils/src/satisfiesPackageManifest.ts b/packages/lockfile-utils/src/satisfiesPackageManifest.ts index fd3569520f..4da7ad6df1 100644 --- a/packages/lockfile-utils/src/satisfiesPackageManifest.ts +++ b/packages/lockfile-utils/src/satisfiesPackageManifest.ts @@ -57,7 +57,7 @@ export default (lockfile: Lockfile, pkg: ProjectManifest, importerId: string, op return false } for (const depName of pkgDepNames) { - if (!importerDeps[depName] || importer.specifiers[depName] !== pkgDeps[depName]) return false + if (!importerDeps[depName] || importer.specifiers?.[depName] !== pkgDeps[depName]) return false } } return true