mirror of
https://github.com/pnpm/pnpm.git
synced 2026-06-28 09:55:39 -04:00
## Summary Fixes `pnpm install` with `optimisticRepeatInstall` incorrectly returning `Already up to date` when `pnpm-lock.yaml` changed but project manifests did not. Fixes #12100. ## Root Cause `checkDepsStatus` used modified manifest mtimes as the only signal for whether it needed to validate dependency status. If no manifest was newer than `workspaceState.lastValidatedTimestamp`, it returned `upToDate: true` before checking whether the wanted lockfile had changed. That skipped lockfile validation for workflows like: - `git checkout HEAD~1 -- pnpm-lock.yaml` - restoring only `pnpm-lock.yaml` from a stash - external tools rewriting the lockfile without touching manifests ## Changes - Check wanted lockfile mtimes before taking the optimistic fast path. - If any wanted lockfile is missing or newer than the workspace state timestamp, validate all projects instead of only modified manifests. - Add a regression test proving a lockfile-only change does not skip wanted-lockfile validation. - Add a patch changeset for `@pnpm/deps.status` and `pnpm`. --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
import fs from 'node:fs'
|
|
import os from 'node:os'
|
|
import path from 'node:path'
|
|
|
|
import { expect, test } from '@jest/globals'
|
|
|
|
import { getGitBranchLockfileNames, getGitBranchLockfileNamesSync } from '../lib/gitBranchLockfile.js'
|
|
|
|
process.chdir(import.meta.dirname)
|
|
|
|
test('getGitBranchLockfileNames()', async () => {
|
|
const lockfileDir: string = path.join('fixtures', '6')
|
|
const gitBranchLockfileNames = await getGitBranchLockfileNames(lockfileDir)
|
|
expect(gitBranchLockfileNames).toEqual(['pnpm-lock.branch.yaml'])
|
|
})
|
|
|
|
test('getGitBranchLockfileNamesSync()', () => {
|
|
const lockfileDir: string = path.join('fixtures', '6')
|
|
expect(getGitBranchLockfileNamesSync(lockfileDir)).toEqual(['pnpm-lock.branch.yaml'])
|
|
})
|
|
|
|
test('git-branch lockfile matcher requires literal dots and a branch segment', () => {
|
|
const lockfileDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pnpm-git-branch-lockfile-'))
|
|
try {
|
|
for (const name of [
|
|
'pnpm-lock.main.yaml', // branch lockfile
|
|
'pnpm-lock.feature.x.yaml', // branch name containing a dot
|
|
'pnpm-lock.yaml', // base lockfile, not a branch lockfile
|
|
'pnpm-lock-main-yaml', // no literal dots
|
|
'my-pnpm-lock.main.yaml', // does not start at the beginning
|
|
'README.md',
|
|
]) {
|
|
fs.writeFileSync(path.join(lockfileDir, name), '')
|
|
}
|
|
expect(getGitBranchLockfileNamesSync(lockfileDir).sort()).toEqual([
|
|
'pnpm-lock.feature.x.yaml',
|
|
'pnpm-lock.main.yaml',
|
|
])
|
|
} finally {
|
|
fs.rmSync(lockfileDir, { force: true, recursive: true })
|
|
}
|
|
})
|