pub fn normalisation_is_reversible(text: TextMode, content: &[u8]) -> boolExpand description
Whether the working tree’s own bytes can still be recovered from what
clean is about to store.
Normalisation maps several working trees onto one plaintext, so for some
content the original is simply gone. This asks about that — whether the
information survives — and deliberately not whether the bytes change.
The distinction is the whole design of this predicate, and it is where we
part company with git’s core.safecrlf.
Git asks the wider question: it counts CRLF and lone LF before and after
a simulated round trip, so on a machine with core.autocrlf=true an ordinary
LF-only file warns — measured on 2.55, * text=auto and a\nb\nc\n give
LF will be replaced by CRLF the next time Git touches it. Git can afford
that because safecrlf defaults to false; the warning is opt-in. Ours is
always on and has no knob, so the wider question would put a line on stderr
for every text file in every Windows checkout — and a warning that fires on
healthy content is worse than none, because it teaches the reader to skip the
two that mean something.
Recoverable means some line-ending mode reproduces the original, which is the
question a uniform file always answers yes to and the two lossy shapes
always answer no to. Measured on git 2.55, verdict = working tree compared
byte for byte after add, commit, rm, checkout:
| content | git, safecrlf=warn | this |
|---|---|---|
a\nb\nc\n, out CRLF | warns | quiet — comes back as uniform CRLF, stable from then on |
a\r\nb\r\nc\r\n, out LF | warns | quiet — mirror image |
a\r\nb\nc\r\n mixed | warns | catches |
a\r\r\nb under text | silent, byte lost | catches |
a\r\r\nb under auto | silent, untouched | quiet — agrees, looks_binary declines to convert |
Git misses the fourth row because its two counters cannot see a lone CR:
one CRLF goes in and one comes out, so the totals agree while a byte is
gone.
Being a question about information rather than bytes, the answer needs no
EolMode and reads no configuration — so it is the same on every machine,
which is what keeps it from being one more thing that behaves differently on
Windows.
The two lossy shapes fail differently and a caller must not promise either:
mixed endings come back changed with git status clean, because the next
clean normalises the new bytes to the plaintext already stored; CR before
CRLF collapses one byte further on each pass and does show up as modified.