git diff --numstat prints - for added and - for deleted when it has NO TEXTUAL
DIFF for a path. Code that reads those dashes as "this file is binary" is reading a
decision as if it were a fact about the bytes.
There are three separate causes, and only ONE of them is about the content:
- A NUL byte in the first 8,000 bytes. This is the only one that says anything
about what the file contains.
- A
.gitattributes decision: -diff, binary, or a named diff driver. Someone
configured it. The bytes are irrelevant.
core.bigFileThreshold. A size cutoff, also a configuration decision.
Where this bites in this repo
Four tracked .ifc sample files are TEXT, and about twenty Rust and CLI tests read them
byte for byte. They report as binary to --numstat, so anything classifying paths by
that signal puts them in the inert or non-diffable bucket while the test suite is
parsing them as STEP.
That is the shape worth fixing regardless of any one consumer: a tool asked "did this
change" and got back "I chose not to tell you", and read the second as the first.
What to do
- Pin the
.gitattributes -diff case as a test, with one of the four real .ifc
samples, so the classification cannot silently flip back.
- Carry a comment at the read site recording that
-/- means "no textual diff" and
listing the three causes, since the meaning is not guessable from the output.
- Anywhere the question is really "is this file text", ask that directly rather than
inferring it from a diff tool's willingness to diff.
Provenance
Found by another session while working #4137. Its branch was closed in favour of #4140,
which is a simpler implementation that never consults git and so is immune to this hole.
That means the finding would have evaporated with the closed branch, which is why it is
recorded here rather than lost. The three causes above are that session's, verbatim in
substance.
Filed on their behalf so the knowledge outlives the branch. I am not claiming it.
git diff --numstatprints-for added and-for deleted when it has NO TEXTUALDIFF for a path. Code that reads those dashes as "this file is binary" is reading a
decision as if it were a fact about the bytes.
There are three separate causes, and only ONE of them is about the content:
about what the file contains.
.gitattributesdecision:-diff,binary, or a named diff driver. Someoneconfigured it. The bytes are irrelevant.
core.bigFileThreshold. A size cutoff, also a configuration decision.Where this bites in this repo
Four tracked
.ifcsample files are TEXT, and about twenty Rust and CLI tests read thembyte for byte. They report as binary to
--numstat, so anything classifying paths bythat signal puts them in the inert or non-diffable bucket while the test suite is
parsing them as STEP.
That is the shape worth fixing regardless of any one consumer: a tool asked "did this
change" and got back "I chose not to tell you", and read the second as the first.
What to do
.gitattributes -diffcase as a test, with one of the four real.ifcsamples, so the classification cannot silently flip back.
-/-means "no textual diff" andlisting the three causes, since the meaning is not guessable from the output.
inferring it from a diff tool's willingness to diff.
Provenance
Found by another session while working #4137. Its branch was closed in favour of #4140,
which is a simpler implementation that never consults git and so is immune to this hole.
That means the finding would have evaporated with the closed branch, which is why it is
recorded here rather than lost. The three causes above are that session's, verbatim in
substance.
Filed on their behalf so the knowledge outlives the branch. I am not claiming it.