The blob-vs-non-blob classifier tried to mirror git's flag grammar and was
wrong three rounds running: it missed --ignore-matching-lines and the combined
short-flag clusters (-pS, -wG, -pI, -pwG, -wpG) whose tail git re-parses, so a
colon-carrying flag VALUE was windowed as if it were a blob.
Ask git instead. show_route stays a cheap pure pre-filter (does the first
positional look like rev:path?); run_show then confirms authoritatively with
'git cat-file -t <arg>' via git_cmd(global_args) and only windows an exact
'blob'. tree/commit/tag or a non-zero exit route to the normal commit-diff /
passthrough path. This subsumes and removes the raw.starts_with("tree ")
content-sniff (a false positive for Newick/NEXUS blobs). Marked with a
TODO(after #3681) so a flag pre-filter can later avoid the probe on the common
path.
Fidelity invariant ('byte-identical unless we successfully windowed'): window
ONLY content that is valid UTF-8 byte-for-byte, so the 'git show rev:path |
tail -n +N' hint always reconstructs exactly. Latin-1, UTF-16/BOM, binary and
lossy-UTF-8 now pass through byte-identically instead of being transcoded and
windowed (which broke recovery and could inflate output past git). This orphans
decode_output and its Latin-1/CJK/BOM helpers in core::stream, which are
removed. The recovery hint now carries the command's global args (-C, -c,
--git-dir, --work-tree) so it is runnable from outside the repo.
N1: emit small blobs (<= 8 KiB) as git's raw bytes with no decode, so a
passthrough blob keeps its BOM.
N2: derive the recovery hint from the blob arg itself
(`git show <rev>:<path> | tail -n +N`) instead of a tee file, so the
windowing works for blobs larger than the tee's max_file_size cap; drop
the MaxRecoverable cap and tee::max_recoverable_bytes entirely.
N3: track savings against the raw bytes git wrote, not the transcoded text,
via TimedExecution::track_bytes (avoids overstating the reduction).
N5: decode captured stderr with decode_process_output, not from_utf8_lossy.
N6: skip windowing when stdout is not a TTY — truncation changes the bytes a
piped consumer receives, not just the on-screen presentation.
N8: window the token-savings test against a committed deterministic fixture
instead of include_str!(main.rs).
N9: replace bare see-also doc pointers with the real rationale.
N10: surface git's stderr on success too, not only on failure.
N4/N7 do not apply: with N2 this path no longer writes a tee file, so there
is no tee-write ordering to fix nor a tee.mode to honour here.
`git show <rev>:<path>` dumps raw file content that RTK previously passed
through unfiltered (0% savings). Large text blobs are now capped to an 8 KiB
byte budget with a `tail -n +N` recovery pointer (the full blob is tee'd),
mirroring the commit-diff path. Small blobs, tree listings, binary, and
blobs too large for the recovery file to store intact are passed through
unchanged.
Blobs are captured as raw bytes and decoded encoding-aware: ISO-8859 /
Latin-1 files (e.g. Oracle PL/SQL packages) are transcoded losslessly
instead of being corrupted into U+FFFD by lossy UTF-8 decoding, which also
unblocks their compression. Ambiguous single-byte encodings (CP1252 range)
and binary content are passed through raw rather than guessed.