Preserve line endings when applying patches#30882
Open
charliemarsh-oai wants to merge 3 commits into
Open
Conversation
This was referenced Jul 2, 2026
ef44e33 to
ecd347e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why
apply_patchcurrently splits source contents on\n, which leaves\rattached to existing CRLF lines, while replacement lines parsed from the patch contain no\r. Joining the result with\ntherefore preserves CRLF on untouched lines but emits LF on changed lines, producing mixed-ending files.The previous fix in #7515 intentionally applied only to Windows. It stripped terminators with
str::lines, classified the entire file as CRLF only when every newline was CRLF, and then regenerated the whole file with one separator. That fixed uniform CRLF files, but it coupled behavior to the host OS and normalized mixed-ending files instead of preserving untouched source. The change was reverted wholesale by #7903, leaving the original split/join behavior in place.Design
This follows the line-ending design we use in Ruff. Ruff's universal newline model recognizes LF, CRLF, and CR and exposes the actual terminator for each source line. Ruff's
LineEnding::Autouses the first detected newline as the preferred style and defaults to LF.SourceFileapplies the same preferred-style rule for new text while remaining more conservative than a formatter: untouched lines retain their exact original terminators, including in mixed-ending files. The patch parser also records which old/new line pairs were context rather than trying to infer equality after parsing. Replacement ranges can then exclude those exact context lines, even when adjacent changed lines have identical text or matching required whitespace normalization.Closes #4003.