Files
pnpm/pnpr
Zoltan Kochan 8c9edf29c6 feat(lockfile): emit patchedDependencies block in pacquet lockfile (#12281)
* feat(lockfile): emit patchedDependencies block in pacquet lockfile

pacquet resolved and hashed patches for the depPath `(patch_hash=...)`
suffix and at build time, but never wrote the top-level
`patchedDependencies:` block into `pnpm-lock.yaml`, so a
`pacquet install --lockfile-only` diverged from pnpm (issue item 6 of
pnpm/pnpm#12266).

Add a `patched_dependencies` field to the `Lockfile` struct in its
`sortLockfileKeys` slot (between `pnpmfileChecksum` and `importers`),
populated via a new `Config::patched_dependency_hashes()` that ports
pnpm's `calcPatchHashes(opts.patchedDependencies)`: resolve each patch
path against the workspace dir and hash it, keeping the user's verbatim
keys so a bare `foo` and `foo@*` stay separate lockfile keys rather than
collapsing into one group bucket. The hashes are computed once per
install and threaded through `GraphToLockfileOptions`; the current
lockfile (`lock.yaml`) carries them through.

* feat(lockfile): check patchedDependencies drift in frozen freshness gate

Now that the lockfile records `patchedDependencies` hashes, the
frozen-lockfile freshness gate must reject an install when those hashes
drift — otherwise editing a patch file would not invalidate the
lockfile even though the patch hash participates in `(patch_hash=...)`
depPath identity.

Port pnpm's `getOutdatedLockfileSetting` patchedDependencies check:
`check_lockfile_settings` now takes the current install's
`patched_dependency_hashes()` and compares it (order-insensitively)
against `lockfile.patched_dependencies`, surfacing a new
`StalenessReason::PatchedDependenciesChanged` between the
`ignoredOptionalDependencies` and settings checks, matching upstream's
order. The pnpr fast-path bails when patches are configured.

Addresses review feedback on the patchedDependencies-block PR.

* feat(package-manager): detect in-place patch edits in the repeat-install fast path

The optimistic repeat-install fast path skipped the whole pipeline
before `check_lockfile_freshness` ran, and its workspace-state
comparison only checks the `patchedDependencies` key→path map. A patch
file edited in place (same config entry, new contents) therefore slipped
through: `node_modules` and the lockfile's recorded patch hash could stay
stale behind an "Already up to date".

Port the patch-file branch of pnpm's `patchesOrHooksAreModified`: a
configured patch whose mtime is newer than the workspace state's
`lastValidatedTimestamp` invalidates the fast path, checked before the
manifest-mtime exit so the patch reason wins. The pnpmfile branch and
the `assertWantedLockfileUpToDate` re-verification remain unported.

Addresses review feedback on the patchedDependencies-block PR.
2026-06-09 12:01:42 +02:00
..