Fix pnpm 7/8 vendored specifier YAML quoting (#754) - #755
Mikola Lysenko (mikolalysenko) merged 5 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Vendoring on a pnpm 7/8 lock writes the project's absolute path into pnpm-lock.yaml. When that path contained " #" or ": " (for example "My Project #2"), it was written unquoted, so YAML cut it short or rejected the line and every frozen install failed while vendor reported success. The specifier is now spelled the way pnpm itself writes it: plain when safe, single-quoted otherwise. Re-running vendor heals a lock an older release left broken, and revert still restores the original bytes. Fixes #754 Assisted-by: Claude Code:claude-opus-5-5
Adds end-to-end legs that vendor with real pnpm 7.33.5 and 8.15.9 in project directories named "hash #x" and "colon: x", then require the same-path frozen offline install to land the patched bytes. Without the quoting fix both fail with ERR_PNPM_OUTDATED_LOCKFILE. Refs #754 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
1 similar comment
|
BugBot review Generated by Claude Code |
Windows does not allow ":" in a directory name, so the #754 tests that create a "colon: x" project dir would fail there before testing anything. Those cases now run on Linux and macOS only; the " #" case still runs everywhere. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
The quoting commit reformatted 130 files outside the fix, which buries the real change and conflicts with every other open PR touching those files. Restore them to main; the fix itself (pnpm_lock_legacy.rs, formats/pnpm/lines.rs, e2e_vendor_pnpm_build.rs) is unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
|
bugbot run Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit ca37b7e. Configure here.
|
[agent] Generated by Claude Code |
|
Ready for review at
Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #754
Summary
Vendoring a pnpm 7/8 project (lockfile 5.4 / 6.0) writes the project's
absolute path into
pnpm-lock.yamlas the root dependency'sspecifier. When that path contained
#or:(e.g.~/src/My Project #2), the value was written unquoted, so YAML cut itshort at
#or rejected the line at:. Everypnpm install --frozen-lockfilethen failed at the very path thelock was written for, while
vendorreported success. The specifieris now written the way pnpm itself writes it: plain when safe,
single-quoted otherwise (double-quoted with escapes for characters
single quotes can't carry).
Root cause
vendor/pnpm_lock_legacy.rssplicedfile:<abs root>/<tgz>into thespecifiers:line (5.4) and the nestedspecifier:line (6.0) withformat!, never encoding it as a YAML scalar. The in-sync checkscompared that same raw text, so a re-run agreed with the broken write.
Changes
formats/pnpm/lines.rs: newyaml_value, which spells a mappingvalue the way pnpm's writer (js-yaml
dump) does.vendor/pnpm_lock_legacy.rs: both specifier writers and theirin-sync checks use the encoded spelling. Ownership checks read the
unquoted value. Revert recognizes our own value in quoted form too.
not treated as in sync. Re-running
vendorrewrites it to thequoted spelling, records no "original" for our own stale value, and
the first ledger entry still reverts byte-for-byte.
Test evidence
#and:)pnpm_lock_legacy::tests::absolute_specifier_is_yaml_quoted_under_indicator_pathspnpm_lock_legacy::tests::unquoted_absolute_specifier_from_an_older_release_is_healede2e_vendor_pnpm_build::pnpm7_real_lifecycle_under_yaml_indicator_pathsERR_PNPM_OUTDATED_LOCKFILEe2e_vendor_pnpm_build::pnpm8_real_lifecycle_under_yaml_indicator_pathsERR_PNPM_OUTDATED_LOCKFILEformats::pnpm::lines::tests::yaml_value_*(plain-safe cells from the issue's matrix stay plain)The e2e legs run the existing legacy capstone (vendor, same-path
--frozen-lockfile --offlineinstall of the patched bytes, movedcheckout, idempotent re-vendor, byte-exact revert) in
hash #xandcolon: xproject dirs (colon: xon unix only: Windows forbids:in apath component). The red runs used this branch's tests with
origin/main's writer.Commands run locally (Linux):
cargo fmt --all -- --check: cleancargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --lib -- pnpm_lock_legacy formats::pnpm: 80 passedcargo test -p socket-patch-cli --test e2e_vendor_pnpm_build -- real_lifecycle: 4 passedcargo test --workspace --all-features --no-fail-fast: the only failures arethe permission and self-update tests that fail when run as root in this
sandbox (chmod-0555 / unremovable-file write-failure cases, self-update
lock/state-dir legs). None touch pnpm; CI runs them as non-root.
No wrapper changes: this is Rust-only lock surgery, and the npm, pypi
and gem wrappers only dispatch to the binary.
Notes
vexnever reads importer specifiers (vex/discover/npm.rs), and onmain
vendor --checkchecks only the committed artifact for npm-familyentries. With the write fixed, both report a lock that installs.
Teaching
vendor --checkto re-verify npm-family wiring is thegeneral gap tracked in
vendor --checksays "committed artifact and wiring verified" (exit 0) afterpipenv lockdrops the vendored reference, so a freshpipenv install --deployinstalls the unpatched wheel while vex says vendor_unwired #725 / Fix vendor --check passing unwired vendored entries (#725) #730.affected.
🤖 Generated with Claude Code
https://claude.ai/code/session_01WrJKfSVrc5xqCq2bHEQsUA
Note
Medium Risk
Changes how pnpm 7/8 lockfiles are rewritten and reconciled; mistakes could corrupt locks or mis-detect drift, but scope is limited to legacy vendoring and is heavily tested.
Overview
Fixes #754: vendoring on pnpm 7/8 (lockfile 5.4 / 6.0) used to splice the machine-absolute
file:root specifier intopnpm-lock.yamlas a plain scalar. Paths containing YAML trouble spots (#,:) then broke the lock (ERR_PNPM_OUTDATED_LOCKFILE/ broken lockfile) even thoughvendorreported success.Adds
yaml_valueinformats/pnpm/lines.rsto spell mapping values like pnpm’s js-yaml writer (plain when safe, single-quoted for indicators, double-quoted for non-printables). The legacy lock writer uses it for 5.4specifiersand 6.0 rootspecifier:lines, compares in-sync state against the encoded form, and teaches revert/drift to treat quoted spellings as ours. Re-vendor heals locks an older release left unquoted (not “in sync”) without recording our stale value as the user’s original.Tests: unit tests for the encoder;
pnpm_lock_legacyfixtures underhash #x/colon: xdirs; e2e legacy capstone runs with a configurable project dir name (unix-only for:paths on Windows).Reviewed by Cursor Bugbot for commit ca37b7e. Configure here.
Generated by Claude Code