fix(lockfile): handle yarn berry builtin compat flags & ~/ patch paths#963
Conversation
aube's berry `patch:` parser mishandled three patch-path selector forms, all stemming from an incomplete reading of Yarn's grammar (plugin-patch/sources/patchUtils.ts). Mirror Yarn faithfully: split the selector on `&`, strip flags, then classify each segment. - optional!builtin<…>: Yarn ≥3.2's plugin-compat emits its builtin compat shims (fsevents, resolve, typescript) with an `optional!` flag — the canonical form that pervades real lockfiles. aube only matched the bare `builtin<…>` prefix, so the flagged form slipped through and was recorded as a real project patch pointing at a nonexistent file. Strip `!`-delimited flags up to the last `!`, then match `^builtin<…>$`. - ~builtin<…>: Yarn 2.4–3.1 spelled the optional flag as a leading `~` (plugin-compat #2543), so older lockfiles carry `~builtin<…>`. Strip a bare leading `~` so these legacy compat patches are skipped too. - ~/.yarn/patches/…: Yarn's `patch-commit -s` default writes project-root-relative paths with a `~/` prefix. aube kept it verbatim, so the materializer looked for a literal `~` directory and the install failed. Strip `~/` to aube's canonical project-root-relative form (the two `~` meanings never collide: a project path keeps its slash, the legacy flag does not). Builtin segments are ignored (the package survives via its plain npm block); a composed `real.patch&optional!builtin<…>` keeps the real file. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Property test the yarn berry patch-selector parser: for any &-joined selector of Yarn-shaped segments, patch_protocol_path returns either None or a clean project-relative path — never a leftover `~` prefix and never a `builtin<…>` marker (the exact forms that broke installs). Plus a no-panic property over arbitrary input. Helper is made pub(super) to test directly, matching the existing parse_berry_spec / split_berry_header convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthrough
Yarn Berry patch protocol selector parsing
Changes🎯 3 (Moderate) | ⏱️ ~20 minutes 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 improves Yarn Berry patch handling in the lockfile parser. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (4): Last reviewed commit: "test(lockfile): add yarn patch-selector ..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@crates/aube-lockfile/src/yarn/berry.rs`:
- Around line 458-485: The patch selector parser in patch_protocol_path is
currently truncating multi-file selectors by returning only the first real patch
path, which can silently ignore additional diffs. Update the logic to detect
when selector.split('&') contains more than one non-builtin<…> path and return
an error or otherwise fail loudly instead of picking the first entry. Keep the
existing builtin<…> filtering and prefix stripping, but make the function/its
callers reject unsupported multi-patch selectors until the patch graph can
represent them.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 9c2509ef-5e28-4c19-9fb8-c24e3f908a67
⛔ Files ignored due to path filters (2)
fixtures/import-yarn-patch-tilde/.yarn/patches/is-number.patchis excluded by!**/.yarn/**fixtures/import-yarn-patch-tilde/yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (4)
crates/aube-lockfile/src/yarn/berry.rscrates/aube-lockfile/src/yarn/tests.rsfixtures/import-yarn-patch-tilde/package.jsontest/import.bats
…iles patch_protocol_path kept only the first real patch in a `&`-joined selector and silently ignored the rest. Yarn's grammar allows multiple real patches (its CLI never emits this), so warn (WARN_AUBE_YARN_BERRY_UNSUPPORTED) instead of dropping them silently. Still applies the first; one path per package is aube's model. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…omments Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hey there, hope you're doing fine!
Follow-up of the work in #728. I was trying aube on a Yarn v4 project and got a few import/install failures around Yarn patch handling.
It seems like aube's Yarn Berry
patch:parser matched only a slice of Yarn's grammar. This rewritespatch_protocol_pathto mirror Yarn patchUtils.ts across Yarn 2.4–4.x.
The PR was written by Claude: I'm not too much of a Rust person, so I hope this is a good starting point, but I'll be a poor judge of whether the code is good. Fine to close it and move it to a Discussion :)
bug
aube installfails at the patch step on Yarn v4 projects I tried, including Yarn itself and backstage(.io). Thepatch:selector parser only handled part of Yarn's grammar, so two forms break:optional!builtin<compat/fsevents>: Yarn's compat shim that can't be disabled. It's in almost every Yarn 4 lockfile (via fsevents). due to theoptional!, aube treats it as a real patch path and tries to read a file that doesn't exist.~/.yarn/patches/foo.patch: the pathyarn patch-commit -swrites by default. aube keeps the~/, so it looks for a literal~dir.Either one gives
× failed to read patch file .../optional!builtin<compat/fsevents>...fix
Parse the selector the way Yarn does: split on
&, drop the flags, skipbuiltin<...>, strip a leading~/. Builtin compat patches get skipped, since aube can't apply Yarn's bundled shims, but the package still installs from its normal npm entry. It's one function, no other call sites.The flag handling also covers the older compat-shim spellings (
builtin<...>and~builtin<...>from Yarn 2.x) alongside today'soptional!builtin<...>The fix does not add support for multiple patch files, which currently can't be emitted with
yarn patch.test
In addition to the tests, I ran
aube import/aube installbefore/after on backstage and yarnpkg/berry, plus a parse diff across about a dozen Yarn 4 repos. No obvious regressions in my runs.Summary by CodeRabbit
Bug Fixes
patch:selectors, including robust parsing of composed selectors and selector::parameters.~/) patch paths are normalized correctly, and selectors that resolve to multiple real patch files are rejected.Tests
~/normalization.aube installtest for#~/.yarn/patches/...references.