Skip to content

Pick the line terminator for spliced lines through one line_endings::terminator #815

Open

Description

[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: register comment.

Kind: refactor. Source: review 4.4 and 5.4 (CRLF policies); register E16. Child 1 of tracking #814.

Problem

Writers that insert or append lines pick the terminator with three hand-written rules (main @ 045d7ec):

Drift, proved by execution. A throwaway unit probe on main, run twice, gave:

  • for "a\nb\r\nc\r\n": detect_eol and pypi_uv::newline_of → CRLF, gradle::newline_of → LF, majority_terminator → CRLF;
  • for "a\r\nb\nc\n": the first two → CRLF, gradle::newline_of → CRLF, majority_terminator → LF.

On a uniform file all three agree.

Symptoms

None filed for these sites specifically. The same disagreement produced #467 and #695 in other writers (see #814).

Impact

Low risk, small. The rules differ only on mixed CRLF/LF files, where a new line comes out in a style that depends on which copy the writer was pasted from.

Proposed change

Size and scope

About 15 files, roughly −60/+40 production lines, plus unit tests. Out of scope: preserve_line_endings and crlf_to_lf (child 2), yarn classic's mixed-file posture (child 3, #467), the pnpm CRLF refusal (review 4.7 G) and the Poetry/PDM rule (PR #703).

Acceptance criteria

  • rg 'contains\("\\r\\n"\) \{ "\\r\\n"' crates/socket-patch-core/src finds no production hits; detect_eol and both newline_of functions are gone.
  • New unit tests in utils/line_endings.rs for terminator: LF, CRLF, None, and mixed with a CRLF majority, an LF majority and a tie.
  • A regression test on one append-and-revert writer (for example go_sum_edit or Gradle append_line) over a mixed file: forward then revert is byte-exact.
  • These stay green: crlf_go_sum_preserves_line_endings, test_crlf_go_mod_preserves_line_endings, rewrites_hash_pinned_continuation_and_preserves_crlf, transitive_append_crlf_root_without_trailing_newline, crlf_pyproject_and_lock_round_trip_byte_exact, kotlin_settings_crlf_and_missing_newline_are_preserved, crlf_and_tabs_are_preserved (maven_reactor), gem_crlf_lock_checksum_pinned_preserving_crlf, gem_crlf_lock_checksums_header_gains_crlf_entry, gemfile_rerun_on_crlf_checkout_never_nests, and the full cargo test -p socket-patch-core.

Dependencies

Blocked by nothing. It touches gradle.rs and maven_reactor.rs lines that #715's children also edit, so rebase whichever lands second. It unblocks children 2–4 of #814.

Activity

  1. added
    arch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)
    refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code
    on Oct 5, 2026
  2. mikolalysenko commented on Oct 5, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged: priority:p3 (a cross-cutting refactor). This is child 1 of tracking issue #814. Confirmed on main: common::detect_eol, pypi_uv::newline_of and gradle::newline_of (which follows a different rule) all still exist. Not a duplicate, and no open PR covers it.


    Generated by Claude Code

  3. mikolalysenko commented on Oct 8, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue for the architecture refactor routine (highest leverage: the only refactor slice left whose files no open PR changes; it collapses 8 copies of the "any \r\n → CRLF" rule into one line_endings::terminator). Branch: arch-refactor/815-line-terminator. Claim-ID: 2026-10-08T03:56:03Z-4c3126

    Slice taken (slice 1): add utils::line_endings::terminator and route the copies in files no open PR touches: formats/gem/hosted.rs, redirect/upstream/{composer,gem,pypi}.rs, redirect/pipenv.rs, utils/python_script.rs and vendor/go_mod_edit.rs (2 sites). Remaining (slice 2, after the open PRs that change those files land): vendor::common::detect_eol and its callers, pypi_uv::newline_of, maven_reactor.rs ×2, redirect/mod.rs, the crlf flags in upstream/cargo.rs/npmrc.rs/pypi_pipenv.rs, and the Gradle newline_of.


    Generated by Claude Code

  4. mikolalysenko commented on Oct 8, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR for slice 1: #1108.


    Generated by Claude Code

  5. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue for the architecture refactor routine (highest leverage: every other ranked slice touches files open PRs change; this one collapses common::detect_eol and pypi_uv::newline_of into line_endings::terminator). Branch: arch-refactor/815-line-terminator-2. Claim-ID: 2026-10-09T04:55:52Z-b2f6b6

    Slice taken (slice 2): delete vendor::common::detect_eol (callers go_sum_edit.rs, yarn_classic_lock.rs, formats/yarn/blocks.rs, pypi_requirements.rs) and vendor::pypi_uv::newline_of, and route the npmrc.rs insert terminator through terminator. Remaining after it: maven_reactor.rs ×2 (#1036), redirect/mod.rs (several open PRs), and the Gradle first-line rule (gradle::eol::newline_of, paired with sniff_crlf/apply_eol for block matching, so it moves as a unit in its own slice). The whole-file crlf flags (upstream/cargo.rs, pypi_pipenv.rs) belong to children 2 and 4.


    Generated by Claude Code

  6. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR for slice 2: #1227.


    Generated by Claude Code

  7. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue for the architecture refactor routine (highest leverage: the top-ranked slices touch files open PRs change; this one deletes the Gradle-only line-ending module and its first-line rule, plus the two maven_reactor.rs copies, so only redirect/mod.rs is left). Branch: arch-refactor/815-jvm-line-terminator. Claim-ID: 2026-10-09T12:00:03Z-78dc6b

    Slice taken (slice 3): gradle::eol::{newline_of, sniff_crlf, apply_eol} and the vendor/jvm/gradle.rs newline_of wrapper go through line_endings::terminator, forward and revert together so a mixed file still reverts byte-exact; eol_eq and the byte to_lf move into utils::line_endings and gradle/eol.rs is deleted; maven_reactor.rs ×2 use terminator. Remaining after it: the redirect/mod.rs Gemfile site (several open PRs change that file).


    Generated by Claude Code

  8. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR for slice 3: #1264.


    Generated by Claude Code

  9. mikolalysenko commented on Oct 12, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Janitor: releasing the stale claim Claim-ID: 2026-10-09T12:00:03Z-78dc6b. slices merged, last #1264 on 2026-10-09 14:58Z; no open PR for the rest of this issue, and the claimer has been silent since 2026-10-09T12:00:39Z (more than 48h). Removing agent:claimed so another fixer can pick up what remains.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)priority:p3refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions