Repository navigation
Fix vex remedy for a vendored gem leftover (#2076) - #2081
Mikola Lysenko (mikolalysenko) wants to merge 6 commits into
Conversation
Assisted-by: Claude Code:claude-fable-5-2
Once Gemfile.lock takes a vendored gem from its PATH source, Bundler loads the vendored directory and installs nothing for the gem. The registry copy an earlier bundle install left in the gem home stays, unpatched, until bundle clean. vex counted it as the live tree and warned vendored_tree_out_of_sync on every run, with a remedy (re-run the install) that could never clear it. The probe now skips a vendored gem's gem-home copies, as it does Go's module cache and Gradle's files-2.1 copies. A default gem's copy still counts, since RubyGems can load it before Bundler sets the load path. The verdict was never affected and is unchanged. Fixes #2076 Assisted-by: Claude Code:claude-fable-5-2
This replaces the previous commit's approach. Dropping the gem-home copy from the drift probe hid a copy that a load outside Bundler still runs (plain ruby, a stale --standalone setup script), so the probe is back to what main has. What #2076 reports is the wording. For a vendored gem the warning said the live tree carries different bytes and to re-run the install. Bundler loads the vendored path and bundle install never replaces the old registry copy, so the advice could not clear it. The gem detail now says the copy is a leftover Bundler no longer loads, and names bundle clean (a project bundle path) or gem uninstall NAME -v VERSION (a shared gem home). The warning code, the verdict and every other ecosystem's text are unchanged. Fixes #2076 Assisted-by: Claude Code:claude-fable-5-2
Review of the previous commit found the gem wording wrong in three cases: a default gem (no command removes it, and RubyGems can load it before Bundler), a shared gem home (gem uninstall needs -i and the platform), and a Hatch note appended to a gem's warning. The drift probe now records which copy drifted, and the warning names that directory and gives the remedy for where it is: bundle clean inside the project, gem uninstall with -i and --platform outside it, none for a default gem. A gem takes no pypi notes. Refs #2076 Assisted-by: Claude Code:claude-fable-5-2
Review of the previous commit: choosing bundle clean by whether the copy sits under --cwd broke on a relative --cwd, on a GEM_HOME inside the project (bundle clean refuses there) and on a bundle path outside it, and only the first drifted copy was named. The gem warning now lists every drifted copy and gives one gem uninstall NAME -v VERSION -i HOME per gem home, which removes the copy from any home, a Bundler path included, and mentions bundle clean for the project's own bundle path. The home is shell-quoted and the platform percent-decoded. The text no longer names Gemfile.lock, since the lock may be gems.locked. Refs #2076 Assisted-by: Claude Code:claude-fable-5-2
Review of the previous commit: the printed gem uninstall command stopped at the dependents prompt, failed through a symlinked gem home, and carried purl text from committed files into a line meant to be pasted into a shell. The gem warning now lists the drifted copies and says in words what removes one: bundle clean for the project's own bundle path, gem uninstall in any other gem home no other project uses, and nothing for a default gem. No part of the purl reaches the remedy. Only a gem's probe collects every drifted copy; the others stop at the first, as before. The e2e test runs bundle clean on a copy of the project, so the revert leg keeps its starting tree. Refs #2076 Assisted-by: Claude Code:claude-fable-5-2
|
bugbot run Generated by Claude Code |
PR SummaryLow Risk Overview Verification now records CLI adds Contract & tests: Reviewed by Cursor Bugbot for commit a27356d. Configure here. |
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 a27356d. Configure here.
|
[agent] PR shepherd: review brief for the approver What it does. After a gem is vendored, Risk: low. Warning wording plus one new field on Look here
Verified. Read the full diff, the issue (#2076) and the description; they match. New unit tests pin gem vs. cargo copy listing and the gem wording (including a purl with a shell-looking qualifier). Changes I made. None. Open questions. None blocking. The description notes that in a gem home shared with other projects the warning still repeats each run (by design, since the copy is loadable there). Generated by Claude Code |
LLM Description written by Claude Code:claude-fable-5-2
Fixes #2076
Summary
After vendoring a gem,
socket-patch vexwarnedvendored_tree_out_of_synconevery run and told the user to re-run the package manager's install. With
Bundler that can never clear it: the lock takes the gem from the vendored
path, so
bundle installinstalls nothing for it and leaves the old registrycopy in the gem home.
The warning stays (same code, same trigger, same verdict), but for a gem it
now says what is true and what removes the copy:
Every other ecosystem's text is byte-identical to
main.Root cause
vex.rshad one wording for every ecosystem ("the live tree carries differentbytes — re-run your package manager's install"), with addenda for Hatch and
PDM, the two managers known not to resync on install. Bundler is a third, and
had none.
What changed
crates/socket-patch-core/src/vex/verify.rs: the drift probe records whichcopy drifted (
VerifyOutcome::vendored_out_of_sync_copies). For a gem itrecords every drifted copy, since each gem home needs its own cleanup; other
ecosystems still stop at the first.
vendored_out_of_syncis unchanged.crates/socket-patch-cli/src/commands/vex.rs:vendored_out_of_sync_detailbuilds the text. A gem gets the wording above and no Hatch/PDM notes.
CLI_CONTRACT.md: the two places that describe this warning.Why the warning is not simply dropped for gems
The issue offers two fixes: stop counting the leftover, or fix the wording.
The first commit on this branch did the former, and
/code-reviewshowed whythat is unsafe: unlike Go's module cache, a gem-home copy is reachable. Plain
ruby -rrack, a stalebundle install --standalonesetup script, or anotherGemfile sharing the gem home all run the unpatched copy, and this warning is
the only disclosure. So the detection is exactly what
mainhas.The remedy is described rather than printed as a command for the same reason:
an earlier revision printed
gem uninstall <name> -v <version> -i <home>, andreview reproduced it failing (dependents prompt, symlinked gem home) and noted
that it put purl text from committed files into a line meant to be pasted
into a shell. No part of the purl reaches the remedy text now; a unit test
pins that.
The branch history shows those steps (4 commits); the net diff is small.
Evidence
Red on
main, real Bundler 4.0.18 / Ruby 3.3.6:Green on this branch:
cargo test -p socket-patch-core --libcargo test -p socket-patch-cli --libe2e_vendor_gem_build(--include-ignored, real Bundler)e2e_redirect_gem_build(--include-ignored)e2e_vex,e2e_vex_vendor,e2e_vex_redirect,e2e_embedded_vex,in_process_vendorcargo clippy --locked --workspace --all-features -- -D warnings(CI's form)cargo fmt --checkon the touched filesTests for #2076:
e2e_vendor_gem_build::gem_vendor_fresh_checkout_bundle_install_and_revert:after vendoring, the warning names the leftover directory and
bundle cleanand no longer says to re-run the install; then
bundle clean(on a copy ofthe project) removes the leftover, leaves
Gemfile.lockbyte-identical, andvexno longer warns.commands::vex::tests::out_of_sync_detail_names_a_remedy_bundler_honors:gem wording, no purl text in the remedy, no pypi notes on a gem, other
ecosystems unchanged.
vex::verify::tests::vendored_drift_probe_lists_every_drifted_gem_copyandthe extended
vendored_drift_probe_checks_every_installed_copy.Notes for the reviewer
cargo clippy -p <crate> --all-targetsfails locally onmaintoo (44errors in test targets of files this PR does not touch, e.g.
patch/jvm_jar.rs); none are in the touched files.every run, because there the copy really is on disk and loadable outside
Bundler. Silencing it there would need a maintainer decision (for example
an opt-out flag); not done here.
crates/socket-patch-cli/tests/e2e_redirect_gem_stale_install.rsandCLI_CONTRACT.mdstill sayvexreports such a leftover, which remains true.https://claude.ai/code/session_011f9aeT1WzjP49EBEYrCf1s
Generated by Claude Code