Repository navigation
fix(lockfile): preserve pnpm patch hashes on re-resolve - #1035
Conversation
📝 WalkthroughWalkthroughpnpm lockfile parsing now preserves patch hashes, while native pnpm writing computes normalized patch-content hashes and propagates them into patched dependency entries and dependency references. Tests cover round trips, peer-context references, and frozen installation behavior. Changespnpm patch hash handling
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant LockfileGraph
participant PatchFile
participant PnpmWriter
participant PnpmLockfile
LockfileGraph->>PnpmWriter: provide patched dependency paths
PnpmWriter->>PatchFile: read and normalize patch content
PatchFile-->>PnpmWriter: return SHA-256 patch hash
PnpmWriter->>PnpmLockfile: emit hash and qualified references
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR fixes a pnpm lockfile round-trip regression where patched package identities (
Confidence Score: 5/5Safe to merge. The change is scoped to pnpm lockfile read/write semantics and the new filesystem access is guarded by path traversal checks and skipped entirely when a stored hash is already present. The path validation correctly blocks absolute paths, Windows drive letters, and parent-directory traversal. The hash detection uses a 64-char all-hex check matching both pnpm v9/v10 Object-form and v11 scalar-form bare-hex hashes (confirmed via web search). strip-then-reinsert in with_patch_hash handles re-resolution correctly, and the while-loop in strip_patch_hash_suffix removes multiple stale occurrences. Tests cover all three decoration sites and hash preservation without the patch file. No files require special attention. Important Files Changed
Reviews (2): Last reviewed commit: "fix(lockfile): harden pnpm patch hash ha..." | Re-trigger Greptile |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/aube-lockfile/src/pnpm/write.rs (1)
184-212: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate "resolve target + apply patch hash" logic across three sites.
The target-package lookup (direct
dep_path, falling back topeerless_dep_path) followed bywith_patch_hash(&value, patch_hash_for(pkg))is repeated in the importer loop,rewrite_local_deps, and the snapshot-key construction. Consider factoring the lookup+decorate step into one shared helper so future changes to the patch-hash rule only need updating once.♻️ Sketch
+fn decorate_with_patch_hash<'a>( + value: &str, + target: Option<&'a crate::LockedPackage>, + patch_hash_for: impl Fn(&'a crate::LockedPackage) -> Option<&'a str>, +) -> String { + target + .map(|pkg| with_patch_hash(value, patch_hash_for(pkg))) + .unwrap_or_else(|| value.to_string()) +}Also applies to: 640-663, 674-690
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/aube-lockfile/src/pnpm/write.rs` around lines 184 - 212, Factor the repeated target-package lookup and patch-hash decoration into a shared helper in the lockfile writer, covering the importer loop, rewrite_local_deps, and snapshot-key construction. The helper should check the direct dep_path first, fall back to peerless_dep_path, and apply with_patch_hash using patch_hash_for; replace each duplicated implementation while preserving existing values and native_pnpm_aliases conditions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/aube-lockfile/src/pnpm/write.rs`:
- Around line 184-212: Factor the repeated target-package lookup and patch-hash
decoration into a shared helper in the lockfile writer, covering the importer
loop, rewrite_local_deps, and snapshot-key construction. The helper should check
the direct dep_path first, fall back to peerless_dep_path, and apply
with_patch_hash using patch_hash_for; replace each duplicated implementation
while preserving existing values and native_pnpm_aliases conditions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 0a9a4c65-7f96-469b-984c-cccba82f0486
📒 Files selected for processing (6)
crates/aube-lockfile/src/lib.rscrates/aube-lockfile/src/pnpm/raw.rscrates/aube-lockfile/src/pnpm/read.rscrates/aube-lockfile/src/pnpm/tests.rscrates/aube-lockfile/src/pnpm/write.rstest/patch.bats
|
Addressed the remaining review and CI feedback in ca6abc9:
Local validation passes: This comment was generated by Codex. |
Summary
(patch_hash=...)identities on direct, transitive, snapshot, and peer-context referencesRoot cause
The shared lockfile graph collapsed pnpm patch metadata to a path, and the pnpm writer explicitly emitted that path without decorating importer versions or snapshot keys. PR #1022 made current manifest/workspace declarations authoritative after a fresh resolve, which kept patches applied but exposed this metadata loss whenever unrelated manifest drift rewrote
pnpm-lock.yaml.The pnpm boundary now preserves an existing hash or computes the same normalized patch-content SHA-256 as pnpm 11, then applies that identity consistently while writing
pnpm-lock.yaml.Resolves the behavior reported in Discussion #1029.
Validation
cargo testcargo clippy --all-targets -- -D warningscargo fmt --checkmise run test:bats test/patch.batstmp-aube-issues/pnpm-patch-reresolve-drop/repro.shwith pnpm 11.7.0, including the native frozen reinstallThis PR was generated by Codex.
Note
Medium Risk
Touches lockfile parse/write and install-visible
pnpm-lock.yamlidentity strings; mistakes could break frozen installs or patch parity with pnpm 11, but scope is pnpm-native writes with new regression tests.Overview
Fixes pnpm patched-dependency metadata being dropped when
pnpm-lock.yamlis rewritten after a non-frozen install.Read path:
patchedDependenciesno longer collapses to patch file paths only—v11 scalar hashes and v9/v10{ path, hash }objects are stored on the shared graph (hash preferred when present).Write path: For native
pnpm-lock.yaml, the writer either keeps existing 64-char hashes or SHA-256-hashes patch files (CRLF→LF, relative-path validation). Top-levelpatchedDependenciesserializes as selector→hash (pnpm 11 style). Importerversion:lines, snapshot keys, and dependency edges get(patch_hash=<sha256>)inserted before peer suffixes (e.g.3.0.1(patch_hash=…)(react@19.0.0)), including transitive and alias targets.Tests cover round-trip with object-form hashes, full decoration across direct/transitive/peer refs, lockfile ordering with real patch files, and a BATS non-frozen re-resolve scenario aligned with Discussion #1029.
Reviewed by Cursor Bugbot for commit ca6abc9. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit