Repository navigation
Fix gem unwind dropping source-block ! (#1056) - #1303
Conversation
A gem declared inside the user's own `source "..." do` block is locked by Bundler as `name (= v)!`. The hosted unwind (`rollback`, `remove`) puts the declaration back inside that block but always dropped the `!` from DEPENDENCIES, so the restored pair no longer matched what Bundler writes and every frozen install failed with exit 16. The restore now drops the `!` only when the restored declaration is outside every `source ... do` block (the case where hosted mode added the pin), and keeps it otherwise. Unit and real-bundler e2e tests pin the byte-identical round trip and the frozen install. Fixes #1056 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
BugBot review |
|
[final reviewer] I disarmed auto-merge at Generated by Claude Code |
in_source_block pushed only on `do` lines but popped on every `end`, so the `end` of an `if`/`case`/`def`/`begin` inside a user `source "..." do` block cleared the source from the stack. restore_one then chose Unpin and stripped the DEPENDENCIES `!` for a gem still inside that block, and the frozen install failed as in #1056. Push a non-source entry for line-leading keyword constructs (not modifiers, not ones closed on the same line) so their `end` pops that instead. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
|
[burn-down agent] Disabled auto-merge before pushing f8c511c (fix for the Bugbot Generated by Claude Code |
|
bugbot run Generated by Claude Code |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f8c511c. Configure here.
|
[final reviewer] Not enqueuing. Tanmay Singla (@Tanmay182003), one non-merge commit landed after your approval at
Generated by Claude Code |
Resolve CLI_CONTRACT conflict: take main's pypi paragraph (hosted uv override marker) and keep this branch's gem paragraph (the `!` stays inside the user's own source block). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
in_source_block and declaration_prefix cut each line at the first '#', so
a user source line interpolating its URL ("https://#{host}/") lost its
trailing do, never opened a source frame, and the restore unpinned the
lock's ! for a gem put back inside that block. ruby_code now strips only a
# outside a quoted string.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

LLM Description written by Claude Code:claude-opus-5-5
Fixes #1056
Summary
Bundler locks a gem declared inside the user's own
source "…" doblock asname (= v)!, rubygems.org blocks included. The hosted unwind (rollback,remove <purl>) put the declaration back inside that block but always stripped the!fromDEPENDENCIES. The restored pair then didn't match what Bundler writes, so every frozen install (BUNDLE_FROZEN=true bundle install) failed with exit 16 after a "successful" rollback.Root cause
lock_editincrates/socket-patch-core/src/patch/redirect/upstream/gem.rsranentry.strip_suffix('!')on every non-transitive gem. It never checked whether the restored manifest declaration still sits in a source block.Fix
lock_editnow takes aDepEntry(Unpin/Keep/Drop) in place of thetransitivebool.restore_onepicksKeepwhen the hosted block being undone sits inside a usersource … doblock. That check isin_source_block, a line-leveldo/endscan that also covers agroupnested in the source block and thesource(…) doform. Otherwise it picksUnpin(hosted mode added the!) orDrop(transitive append).Tests (per issue)
rollback/removestrips theDEPENDENCIES!of a gem the user declared inside asource "https://rubygems.org" doblock, so every frozen install fails after the unwind #1056:upstream::gem::tests::source_block_declaration_keeps_its_bang_through_restoreruns the real forward rewrite and then the restore, for a plain source block and for a group nested in asource(…)block. Both come back byte-identical.source_block_detectioncovers the helper.rollback/removestrips theDEPENDENCIES!of a gem the user declared inside asource "https://rubygems.org" doblock, so every frozen install fails after the unwind #1056 e2e:e2e_redirect_gem_build::gem_hosted_unwind_keeps_a_source_block_bang(real Bundler). It runs a hosted scan, an unfrozen converging install, thenrollbackandremove. The lock and Gemfile come back byte for byte, and a frozen install of a fresh checkout succeeds with the upstream bytes.Red→green: with the
Keeparm disabled, the e2e fails withDEPENDENCIES\n vuln-gem (= 1.0.0)where it expectsvuln-gem (= 1.0.0)!. The unit round-trip test failed the same way before the fix.Commands run
cargo test -p socket-patch-core --lib gem: 338 passedcargo test -p socket-patch-cli --test e2e_redirect_gem_build -- --ignored(Ruby 3.4, Bundler 4.0.15): 29 passedcargo clippy --workspace --all-features -- -D warnings: cleancargo fmt --all -- --check: clean for the changed files. The only diff is inupstream/mod.rs, which already differs on main.🤖 Generated with Claude Code
Generated by Claude Code
Note
Medium Risk
Changes gem lockfile restore semantics for rollback/remove; wrong
!handling breaks frozen Bundler installs, but the change is narrowly scoped and heavily tested.Overview
Fixes hosted gem unwind (
rollback/remove) soGemfile.lockDEPENDENCIESlines keep Bundler’s!source pin when the restoredgemdeclaration still lives inside the user’s ownsource "…" doblock (#1056). Previously the unwind always stripped!, so the restored lock no longer matched Bundler’s format andBUNDLE_FROZEN=true bundle installfailed after a “successful” restore.The upstream restore path replaces the transitive-only flag with a
DepEntryaction (Unpin/Keep/Drop).in_source_blockscans the manifest to chooseKeepfor source-block declarations; hosted-added pins stillUnpin, transitive appends stillDrop. CLI_CONTRACT.md documents the exception, with unit and ignored e2e coverage for rollback and remove.Reviewed by Cursor Bugbot for commit f8c511c. Configure here.