Skip to content

LF line endings everywhere #26

Description

@rent-a-developer

Problem

.gitattributes pins working-tree line endings per file type: eol=crlf for .csproj, .props,
.slnx, .ps1 and others, LF for .json, .yml, .md. .cs is marked text with no eol, so C#
files check out CRLF on Windows and LF on Linux. .editorconfig deliberately sets no end_of_line.

This costs us:

  • Every new file type needs a decision. The types nobody listed — PublicAPI.*.txt, .svg,
    .csharpierignore, .codex/*.toml — fall back to each contributor's core.autocrlf.
  • Working trees differ per OS, so byte-level tooling can behave differently locally and in CI.
  • Nothing verifies that stored files match the attributes, so drift stays invisible.

Proposal

One rule: * text=auto eol=lf, plus end_of_line = lf in .editorconfig and a CI step that proves the
repository stays normalized. The repository has no .cmd or .bat files, so there is no exception.

Blocker to fix first

C# does not normalize newlines inside string literals — a literal's value is the file's bytes. Seven
assertions in tests/DbConnectionPlus.UnitTests/SqlStatements/InterpolatedSqlStatementTests.cs compare
an SQL fragment taken verbatim from a multi-line raw string literal against Environment.NewLine.

They pass today only because .cs checks out platform-native, so both sides move together. Once .cs
is LF everywhere, the literal is LF while Environment.NewLine on Windows is CRLF, and these tests fail
on Windows. CI runs the unit tests on Linux only, so CI would stay green.

Fix: expect a plain LF escape instead of Environment.NewLine, in its own commit before renormalizing.

Not affected: the CommandText assertions compare two multi-line literals from the same file, and the
other Environment.NewLine uses assert messages built at runtime.

Scope

  1. Decouple those seven assertions from Environment.NewLine.
  2. Rename scripts/tidy-cs.ps1 to scripts/tidy-code.ps1 and update every reference.
  3. .gitattributes: * text=auto eol=lf plus the binary list. No per-type text pins.
  4. .editorconfig: end_of_line = lf.
  5. CI lint: add a renormalization guard.
  6. Renormalize, and document the policy in CONTRIBUTING.md.

Acceptance criteria

  • dotnet test passes on Windows as well as Linux.
  • .gitattributes contains no per-type text pins.
  • .editorconfig sets end_of_line = lf.
  • git ls-files --eol shows no i/crlf or i/mixed entries.
  • CI fails when a committed file does not match the attributes.
  • scripts/tidy-code.ps1 replaces tidy-cs.ps1, with no reference to the old name left.
  • CONTRIBUTING.md explains the policy.

Suggested branch: chore/lf-line-endings.

Activity

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

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions