Skip to content

strip_conflict_markers_keep_ours silently converts CRLF to LF, misaligning Windows attribution offsets #983

@svarlamov

Description

@svarlamov

Summary

strip_conflict_markers_keep_ours in src/authorship/virtual_attribution.rs:2111-2134 uses content.lines() (which strips both \n and \r\n) then rejoins with result.join("\n") (LF only). On Windows, working-tree files with CRLF endings are silently normalized to LF. The returned string is then passed as final_state to merge_attributions_favoring_first, where attribution diffing operates on byte offsets — but the stashed VA's byte offsets were computed against the original CRLF content, causing misalignment.

Affected code

src/authorship/virtual_attribution.rs:2128:

let mut out = result.join("\n");  // always LF, even if input was CRLF

Impact

Windows only. If a user has CRLF-ending files and runs checkout/switch --merge that produces conflicts, the conflict-marker stripping silently converts line endings, causing byte-offset drift between the cleaned content and the stashed VA. The result is degraded/misaligned attribution rather than a crash.

Notes

  • Not reproducible in CI: GIT_CONFIG_NOSYSTEM=1 suppresses core.autocrlf, and Windows CI tests were already failing for unrelated reasons before this PR.
  • The project's POSIX-normalization convention (paths use forward slashes per AGENTS.md) suggests LF-normalization of content may be intentional or at least acceptable.
  • Fix would be to detect CRLF input and rejoin with \r\n, or to normalize the stashed VA content to LF before computing offsets so both sides agree.

Discovered via Devin PR review on #959.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions