From 972de58abf32cb7ccaa28bca8e7aca70a18e89a1 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 20 Feb 2023 11:39:58 +0200 Subject: [PATCH] fix: update the lockfile if a new project is added to the workspace with no deps (#6110) --- .changeset/hot-trainers-type.md | 7 ++ .changeset/silly-snails-try.md | 5 ++ pkg-manager/core/src/install/index.ts | 2 + pkg-manager/core/test/lockfile.ts | 98 +++++++++++++++++++++++++++ pkg-manager/headless/src/index.ts | 15 +++- 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 .changeset/hot-trainers-type.md create mode 100644 .changeset/silly-snails-try.md diff --git a/.changeset/hot-trainers-type.md b/.changeset/hot-trainers-type.md new file mode 100644 index 0000000000..9c27d3a523 --- /dev/null +++ b/.changeset/hot-trainers-type.md @@ -0,0 +1,7 @@ +--- +"@pnpm/headless": patch +"@pnpm/core": patch +"pnpm": patch +--- + +Update the lockfile if a workspace has a new project with no dependencies. diff --git a/.changeset/silly-snails-try.md b/.changeset/silly-snails-try.md new file mode 100644 index 0000000000..a49fcc5174 --- /dev/null +++ b/.changeset/silly-snails-try.md @@ -0,0 +1,5 @@ +--- +"@pnpm/headless": minor +--- + +New option added: useLockfile. diff --git a/pkg-manager/core/src/install/index.ts b/pkg-manager/core/src/install/index.ts index f6fc3efc86..41c2068e11 100644 --- a/pkg-manager/core/src/install/index.ts +++ b/pkg-manager/core/src/install/index.ts @@ -335,6 +335,8 @@ export async function mutateModules ( }) } if (opts.lockfileOnly) { + // The lockfile will only be changed if the workspace will have new projects with no dependencies. + await writeWantedLockfile(ctx.lockfileDir, ctx.wantedLockfile) return projects.map((mutatedProject) => ctx.projects[mutatedProject.rootDir]) } if (!ctx.existsWantedLockfile) { diff --git a/pkg-manager/core/test/lockfile.ts b/pkg-manager/core/test/lockfile.ts index 1c53123c50..d7e49b4b73 100644 --- a/pkg-manager/core/test/lockfile.ts +++ b/pkg-manager/core/test/lockfile.ts @@ -14,6 +14,8 @@ import { install, mutateModules, mutateModulesInSingleProject, + MutatedProject, + ProjectOptions, } from '@pnpm/core' import rimraf from '@zkochan/rimraf' import loadJsonFile from 'load-json-file' @@ -1423,3 +1425,99 @@ test('lockfile v5 is converted to lockfile v6', async () => { expect(lockfile.packages).toHaveProperty(['/@pnpm.e2e/pkg-with-1-dep@100.0.0']) } }) + +test('update the lockfile when a new project is added to the workspace', async () => { + preparePackages([ + { + location: 'project-1', + package: { name: 'project-1' }, + }, + ]) + + const importers: MutatedProject[] = [ + { + mutation: 'install', + rootDir: path.resolve('project-1'), + }, + ] + const allProjects: ProjectOptions[] = [ + { + buildIndex: 0, + manifest: { + name: 'project-1', + version: '1.0.0', + + dependencies: { + 'is-positive': '1.0.0', + }, + }, + rootDir: path.resolve('project-1'), + }, + ] + await mutateModules(importers, await testDefaults({ allProjects })) + + importers.push({ + mutation: 'install', + rootDir: path.resolve('project-2'), + }) + allProjects.push({ + buildIndex: 0, + manifest: { + name: 'project-2', + version: '1.0.0', + }, + rootDir: path.resolve('project-2'), + }) + await mutateModules(importers, await testDefaults({ allProjects })) + + const lockfile: Lockfile = await readYamlFile(WANTED_LOCKFILE) + expect(Object.keys(lockfile.importers)).toStrictEqual(['project-1', 'project-2']) +}) + +test('update the lockfile when a new project is added to the workspace and lockfile-only installation is used', async () => { + preparePackages([ + { + location: 'project-1', + package: { name: 'project-1' }, + }, + ]) + + const importers: MutatedProject[] = [ + { + mutation: 'install', + rootDir: path.resolve('project-1'), + }, + ] + const allProjects: ProjectOptions[] = [ + { + buildIndex: 0, + manifest: { + name: 'project-1', + version: '1.0.0', + + dependencies: { + 'is-positive': '1.0.0', + }, + }, + rootDir: path.resolve('project-1'), + }, + ] + await mutateModules(importers, await testDefaults({ allProjects, lockfileOnly: true })) + + importers.push({ + mutation: 'install', + rootDir: path.resolve('project-2'), + }) + allProjects.push({ + buildIndex: 0, + manifest: { + name: 'project-2', + version: '1.0.0', + }, + rootDir: path.resolve('project-2'), + }) + await mutateModules(importers, await testDefaults({ allProjects, lockfileOnly: true })) + + const lockfile: Lockfile = await readYamlFile(WANTED_LOCKFILE) + expect(Object.keys(lockfile.importers)).toStrictEqual(['project-1', 'project-2']) +}) diff --git a/pkg-manager/headless/src/index.ts b/pkg-manager/headless/src/index.ts index a08b5c16c1..67b101438e 100644 --- a/pkg-manager/headless/src/index.ts +++ b/pkg-manager/headless/src/index.ts @@ -28,6 +28,7 @@ import { Lockfile, readCurrentLockfile, readWantedLockfile, + writeLockfiles, writeCurrentLockfile, PatchFile, } from '@pnpm/lockfile-file' @@ -152,6 +153,7 @@ export interface HeadlessOptions { enableModulesDir?: boolean nodeLinker?: 'isolated' | 'hoisted' | 'pnp' useGitBranchLockfile?: boolean + useLockfile?: boolean } export async function headlessInstall (opts: HeadlessOptions) { @@ -543,7 +545,18 @@ export async function headlessInstall (opts: HeadlessOptions) { storeDir: opts.storeDir, virtualStoreDir, }) - await writeCurrentLockfile(virtualStoreDir, filteredLockfile) + if (opts.useLockfile) { + // We need to write the wanted lockfile as well. + // Even though it will only be changed if the workspace will have new projects with no dependencies. + await writeLockfiles({ + wantedLockfileDir: opts.lockfileDir, + currentLockfileDir: virtualStoreDir, + wantedLockfile, + currentLockfile: filteredLockfile, + }) + } else { + await writeCurrentLockfile(virtualStoreDir, filteredLockfile) + } } // waiting till package requests are finished