chore: The CSharpier gate cannot pass on a non-Windows checkout (CRLF vs LF) #129
Copy link
Copy link
Closed
Labels
triageNeeds maintainer classification and follow-upNeeds maintainer classification and follow-up
Description
Activity
- addedtriageNeeds maintainer classification and follow-upNeeds maintainer classification and follow-up
on Oct 2, 2026 Found while validating PR #130, which touches no C# file, so the failure is pre-existing on
main.The reproduction in this issue is the one that matters: on a fresh Linux clone,
dotnet tool run csharpier -- check Editor Runtime Testsreports all 110 checked files asWas not formatted. The file contained different line endings than formatting it would result in., exit code 2.Additional evidence gathered while confirming it:
- Formatting any single
.csfile changes nothing but line endings. The unified diff shows every line changed, the formatted result hasCRLFon all lines, and normalizing both sides to LF makes the two files byte-identical. git statusafter such a format reportsCRLF will be replaced by LF the next time Git touches it, which is why the churn never lands as a commit.- The cause is the pair
.editorconfig([*] end_of_line = crlf) and.gitattributes(* text=auto). Git stores LF and checks out LF on Linux and macOS, so CSharpier disagrees with the working tree everywhere except Windows.
- Formatting any single
- added a commit that references this issue
on Oct 2, 2026 Fixed by PR #131, verified on a Linux checkout of this repository.
- Red:
dotnet tool run csharpier -- check Editor Runtime Testsreported all 110 checked files asWas not formatted. The file contained different line endings than formatting it would result in., exit 1. - Root cause confirmed:
.editorconfig[ * ]requiredend_of_line = crlf,.gitattributesset* text=autowith noeol, and all 112 tracked*.csblobs are LF-only. - Green:
.gitattributesnow pins* text=auto eol=lfand.editorconfigdeclaresend_of_line = lf. The same command reportsChecked 110 filesand exits 0. A no-op format of a tracked file leaves its blob hash unchanged, and acore.autocrlf=truecheckout simulation produces LF C# files, which is the Windows default that used to pass by accident. - Criterion 4:
scripts/lint-line-endings.jsresolves every path either file names on both sides and fails closed when the endings differ, when atextrule omitseol, wheneolis set withouttext, when a binary rule pins an ending, when the base*rule or the[*]section is missing, or when an ending name is unknown. It runs inlint:llm:full, the llm-lint workflow on both operating systems, and pre-commit. 25 self-test cases cover it, and five seeded regressions are each killed by a distinct case.
Acceptance criteria 1 to 4 are met. Criterion 4 does not add CSharpier to CI; the harness stays tool-light and the config pair is guarded instead.
- Red:
Metadata
Metadata
Assignees
Labels
triageNeeds maintainer classification and follow-upNeeds maintainer classification and follow-up
Problem
.llm/context.md's validation ladder requiresdotnet tool run csharpier -- check Editor Runtime Teststo be green before review. On a clean Linux or macOS checkout that command can never pass: it reports every tracked C# file as unformatted.Reproduction (repository at
9bbd7f2, verified 2026-10-02)Actual:
Checked 110 filesand 110Error ... Was not formatted. The file contained different line endings than formatting it would result in.lines, exit code 2. CSharpier 1.1.2, as pinned in.config/dotnet-tools.json.Evidence that no source file is misformatted:
*.csblobs in git contain zeroCRLFand zero loneCRbytes, so no file has mixed endings.dotnet tool run csharpier -- format <one file>changes nothing but line endings: the diff is every line, and the result hasCRLFon all lines. Normalizing both sides to LF makes the two files byte-identical..editorconfigline 4 setsend_of_line = crlffor[*], so CSharpier writes CRLF..gitattributesline 4 sets* text=auto, so git stores LF in the repository and checks out LF on Linux and macOS (native) but CRLF on Windows. The gate therefore passes only on Windows.Expected
csharpier -- checkis green on every supported contributor platform, or the configuration states one canonical line ending that git and CSharpier agree on everywhere.Impact
.pre-commit-config.yamlCSharpier hook rewrites every staged C# file to CRLF in the working tree while git normalizes it straight back to LF, so the change never lands and the churn repeats..github/workflows/llm-lint.ymlruns the.llmlinters and the harness self-tests but never CSharpier.Acceptance criteria
dotnet tool run csharpier -- check Editor Runtime Testsexits 0 on Linux, macOS, and Windows from a fresh clone..gitattributesand.editorconfigagreeing: either git checks out CRLF for*.cson every platform, or.editorconfigstops requiring CRLF.Notes
Found while validating a documentation-only change that touched no C# file, so the failure is pre-existing on
mainand unrelated to that work.