Repository navigation
Fix hosted gem block mixing CRLF Gemfile endings (#1831) - #1841
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A hosted scan or get over a CRLF Gemfile (a Windows checkout, or core.autocrlf=true) wrote the Socket `source ... do` block with bare LF endings, so the committed Gemfile ended up with mixed line endings and churned under editors and .gitattributes normalization. The rewritten block now takes the ending of the gem line it replaces (the file's ending for an unterminated last line), and the block appended for a transitive gem takes the file's ending. This matches what vendored mode does since #1822. Fixes #1831 Assisted-by: Claude Code:claude-opus-5-5
Rollback restored a hosted gem declaration with CRLF whenever the Gemfile held any CRLF line. It now takes the ending of the Socket block it replaces, which the redirect writes in the ending of the original line, so a mixed-ending Gemfile round-trips. A gem line that ends in a lone CR at end of file no longer leaves a stray CR, and the recorded edit now shows exactly what was written. Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review 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 210c955. Configure here.
|
Burn-down agent: labeled Ready for review at
Generated by Claude Code |
Final review brief (
|
Wenxin Jiang (Wenxin-Jiang)
left a comment
There was a problem hiding this comment.
[agent] Reviewed 210c955b3813d9b5c0d4a3916b0a9c66e3a819ea. Checked CRLF in-place/appended Gemfile blocks and restore line-ending handling. No major correctness issues found. Validation: source and regression-test review plus the available exact-head CI checks; no local test pass is claimed.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1831
Summary
scan --mode hosted/get --mode hostedover a CRLF Gemfile (a Windows checkout, orcore.autocrlf=true) wrote the Socketsource "…" do … endblock with bare LF endings, so the committed Gemfile ended up with mixed line endings. Now:gemline (plain, with options, parenthesized, inside the user's ownsource … doblock): the block takes the ending of the line it replaces. The line's CR goes back at the end of the block, not inside it. An unterminated last line takes the file's ending, and a lone trailing CR at EOF is no longer read as a line ending.line_endings::terminator, so the majority wins on a mixed file), for both the separator and the block.upstream/gem.rsrestore_manifest) now restores the declaration with the block's own ending. Before, it used CRLF whenever the file held any CRLF line. An LF block (the only spelling written before this PR) takes the ending of the lines around it, so existing redirected projects restore the same as before.This is the hosted-mode twin of #1821 / #1822 (vendored mode).
Root cause
rewrite_gemincrates/socket-patch-core/src/patch/redirect/mod.rsbuilt the block from a literal with hard-coded\nin both arms (in-place and append). The in-place arm'sgem_line_rematch also ran up to the line's CR, so the CR was dropped and the block ended in the original line's bare LF.The recognizers already accept
\r?\n: the re-run idempotency guard,gem_spelling_residue, the restore'ssocket_blocks, and VEX'sparse_source_blocks(viastr::lines). So a CRLF block is recognized everywhere, and the e2e test below confirms that against real bundler.No wrapper changes:
npm/,pypi/andgem/only dispatch to the binary.Tests (red → green)
gem(…), decl inside a usersource … doblock, unterminated last line, lone trailing CR, transitive append (terminated and not), plus a re-run no-op for eachpatch::redirect::tests::gemfile_source_block_keeps_crlf_line_endingsmixed line endings: "…\r\nsource \"https://patch.test/…\" do\n gem …\nend\n"gemfile_source_block_keeps_lf_line_endingsDriver::ScanVexandDriver::ScanVexSourceBlockshapes) stays CRLF after hosted scan, convergingbundle installpasses, re-scan is byte-identical,rollbackgives back a CRLF Gemfile that declares the geme2e_redirect_gem_build::gem_hosted_redirect_keeps_a_crlf_gemfile_crlf(--ignored, bundler 4.0.18 / Ruby 3.3.6 locally; runs in the gem e2e CI legs)crlf-gemfile: the redirected Gemfile mixes line endings: "source \"http://127.0.0.1:…/upstream\"\r\nsource \"…/patch-registry/gem/…\" do\n gem \"vuln-gem\", \"1.0.0\"\nend\n"One existing test changed its expectation:
gemfile_single_line_declaration_lookalikes_still_rewritehas a CRLF declaration in an LF file (gem "vuln-gem", require: false\r). It pinned the old LF block and now expects that line's CRLF. That is the intended rule: the block takes the ending of the line it replaces.Commands run locally:
cargo fmt --all -- --check: cleancargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --lib: 6992 passed, 4 failed. All 4 are the known permission-denial tests that can't fail a write as root in this sandbox (copy_tree::relax_loop_must_not_traverse_symlinked_root,vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry,pypi_poetry::wire_write_failure_…,pypi_requirements::wire_failure_rolls_back_…). None touch gem code.cargo test -p socket-patch-cli --all-features --test e2e_redirect_gem_build --test e2e_vendor_gem_build(--ignored): 38 + 11 passed. Without--ignored: 21 + 35 passed.cargo test --workspace --all-features: the sandbox ran out of disk while linking the CLI test binaries. CI is the full-suite gate.Per-issue checklist
source … doblock with LF endings into a CRLF Gemfile, leaving it with mixed line endings #1831 single-line declaration, CRLF Gemfile with LF or CRLF lock:gemfile_source_block_keeps_crlf_line_endings,gem_hosted_redirect_keeps_a_crlf_gemfile_crlf(crlf-gemfile)source … doblock with LF endings into a CRLF Gemfile, leaving it with mixed line endings #1831 declaration inside a usersource … doblock: same unit test, and e2e (crlf-gemfile-source-block)source … doblock with LF endings into a CRLF Gemfile, leaving it with mixed line endings #1831 append arm (transitive gem):gemfile_source_block_keeps_crlf_line_endings(puma → rails cases)source … doblock with LF endings into a CRLF Gemfile, leaving it with mixed line endings #1831 converging install, re-scan no-op, rollback in CRLF:gem_hosted_redirect_keeps_a_crlf_gemfile_crlf/code-review high
Fixed:
FileEdit.newleft out the CR that was actually written. It now records the exact spliced text.LineEndings::ofinstead of a hand-rolled counter.Not changed:
gem_line_reitself instead of stripping it after the match. That is equivalent, and keeping the regex unchanged leaves the swallowed-whitespace behaviour that rollback depends on (Gem hostedrollback/removeturn a redirected transitive gem into a top-level exact pin, because the restore looks for a blank line the rewriter never writes #457) untouched.https://claude.ai/code/session_011f9aeRvMuTRkgqjmDvPu3j
Generated by Claude Code