From 192d67bef0d24e976ad8e1a67f36ad6a2d996611 Mon Sep 17 00:00:00 2001 From: Rayan Salhab Date: Sun, 3 May 2026 01:02:35 +0300 Subject: [PATCH] fix(clean): ignore lockfile setting unless flag is passed (#11431) Keep pnpm clean from removing pnpm-lock.yaml just because the workspace config sets lockfile: true. The lockfile cleanup now follows the command-line --lockfile option. Co-authored-by: cyphercodes --- .changeset/clean-lockfile-cli-option.md | 5 +++++ pnpm/src/cmd/clean.ts | 7 +++++-- pnpm/test/clean.ts | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .changeset/clean-lockfile-cli-option.md diff --git a/.changeset/clean-lockfile-cli-option.md b/.changeset/clean-lockfile-cli-option.md new file mode 100644 index 0000000000..1fe4977798 --- /dev/null +++ b/.changeset/clean-lockfile-cli-option.md @@ -0,0 +1,5 @@ +--- +"pnpm": patch +--- + +Do not remove `pnpm-lock.yaml` during `pnpm clean` when `lockfile: true` is configured in `pnpm-workspace.yaml`. The lockfile is only removed when the `--lockfile` option is passed to `pnpm clean`. diff --git a/pnpm/src/cmd/clean.ts b/pnpm/src/cmd/clean.ts index 48db8c1113..4c7204552b 100644 --- a/pnpm/src/cmd/clean.ts +++ b/pnpm/src/cmd/clean.ts @@ -13,7 +13,7 @@ export const commandNames = ['clean', 'purge'] export const overridableByScript = true -export const rcOptionsTypes = cliOptionsTypes +export const rcOptionsTypes = (): Record => ({}) export function cliOptionsTypes (): Record { return { @@ -58,11 +58,14 @@ export async function handler ( virtualStoreDir?: string workspaceDir?: string workspacePackagePatterns?: string[] + cliOptions?: { + lockfile?: boolean + } } ): Promise { const modulesDir = opts.modulesDir ?? 'node_modules' const rootDir = opts.workspaceDir ?? opts.dir - const cleanOpts = { modulesDir, removeLockfile: opts.lockfile } + const cleanOpts = { modulesDir, removeLockfile: opts.cliOptions?.lockfile === true } const dirs = await getProjectDirs(opts) await Promise.all(dirs.map(cleanProjectDir.bind(null, cleanOpts))) if (opts.virtualStoreDir) { diff --git a/pnpm/test/clean.ts b/pnpm/test/clean.ts index 572097b7d1..ab8e74510b 100644 --- a/pnpm/test/clean.ts +++ b/pnpm/test/clean.ts @@ -70,6 +70,20 @@ test('pnpm clean preserves lockfile by default', () => { expect(fs.existsSync('pnpm-lock.yaml')).toBe(true) }) +test('pnpm clean preserves lockfile when pnpm-workspace.yaml sets lockfile', () => { + tempDir() + fs.writeFileSync('package.json', '{}', 'utf8') + writeYamlFileSync('pnpm-workspace.yaml', { lockfile: true }) + fs.writeFileSync('pnpm-lock.yaml', 'lockfileVersion: 9') + fs.mkdirSync('node_modules/.pnpm', { recursive: true }) + + const result = execPnpmSync(['clean']) + expect(result.status).toBe(0) + + expect(fs.existsSync('node_modules/.pnpm')).toBe(false) + expect(fs.existsSync('pnpm-lock.yaml')).toBe(true) +}) + test('pnpm clean --lockfile removes lockfile', () => { tempDir() fs.writeFileSync('package.json', '{}', 'utf8')