Skip to main content

normalisation_is_reversible

Function normalisation_is_reversible 

Source
pub fn normalisation_is_reversible(text: TextMode, content: &[u8]) -> bool
Expand 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:

contentgit, safecrlf=warnthis
a\nb\nc\n, out CRLFwarnsquiet — comes back as uniform CRLF, stable from then on
a\r\nb\r\nc\r\n, out LFwarnsquiet — mirror image
a\r\nb\nc\r\n mixedwarnscatches
a\r\r\nb under textsilent, byte lostcatches
a\r\r\nb under autosilent, untouchedquiet — 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.