The diff-hunks store has a writer, but nothing fills it. Teach
builtin_diffstat() to do so: on a warming run (a writer is attached), a
modified pair's stat is produced by collecting the pair's hunk
coordinates instead of emitting text, the counts are summed from those
hunks, and the pair is recorded. A run without a writer is unchanged,
and nothing reads the store yet; the read side arrives next.
The store records one context-free entry per pair, and only for a
trim-stable pair: one whose zero-context trimmed diff (what blame will
read) and untrimmed diff (whose counts a nonzero-context stat matches)
are identical. The warming path computes both and hands them to
diff_hunks_writer_record_stable(), new here, which records only when
they agree; a divergent pair is never recorded and every consumer
computes it. The warming run displays the counts it shows a store-less
run: the trimmed ones, since xdi_diff trims at zero context, while the
untrimmed counts serve only the stability comparison.
Not everything the stat path computes may be recorded.
--ignore-blank-lines is part of the key, but it coalesces hunks
differently between the text-emitting and coordinate-callback paths, so
a recorded entry would not match a store-less run's --stat. -I
patterns, --anchored, and break detection (-B) shape the diff outside
the key entirely; the guard for those three sits in this consumer for
now and moves into the store's own provider when it registers, next. A
"log -L" range-scoped stat is not the whole-pair diff the key describes,
so it does not record. Recording also requires both sides to be valid
regular files whose blobs the key can name: a working-tree side,
textconv output, or a gitlink has no usable id.
"git diff", "git log", "git show", and "git diff-tree" with the --stat,
--numstat, and --shortstat formats attach a writer when writing is
enabled and flush it when the traversal finishes, so a warming run such
as
GIT_DIFF_HUNKS_WRITE=1 git log --all --stat >/dev/null
fills the cache as a side effect of the diff work the command already
does. Writing is controlled by diffHunks.write and GIT_DIFF_HUNKS_WRITE.
Add the write half of t4220:
- ordinary commands never create the store, and creation is gated off
by default, the environment overriding the config;
- a warming run builds a store that verifies, and a second refreshes it
in place;
- a warming run displays parity at zero context on a trim-divergent
pair, committed as a fixture (small synthetic pairs cannot diverge:
minimal diffs add and delete equal counts, and trimming preserves
that);
- binary and mode-only pairs do not break the writer;
- a corrupt store is discarded at seed;
- verify and clear run against the files a warming run builds.
Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||
|---|---|---|
| .. | ||
| README | ||
| trim-divergent-new | ||
| trim-divergent-old | ||
README
t4220 diff-hunks test fixtures
==============================
trim-divergent-old, trim-divergent-new
--------------------------------------
Two revisions of a single real file, used by t4220-diff-hunks.sh to
exercise a "trim-divergent" blob pair: one whose diff hunk counts change
with the amount of context, so the trimmed and untrimmed results
disagree.
They are two versions of git's own t/t6002-rev-list-bisect.sh, taken from
git.git history around:
090af9957c ("t6002: fix use of `expr` with `set -e`",
Patrick Steinhardt, 2026-04-21)
which rewrites `$(expr ...)` arithmetic as `$((...))` and reformats a few
test_expect_success blocks.
trim-divergent-old = 090af9957c^:t/t6002-rev-list-bisect.sh (blob daa009c9a1)
trim-divergent-new = 090af9957c :t/t6002-rev-list-bisect.sh (blob f2de40b5ed)
To regenerate them from any git.git checkout:
git show 090af9957c^:t/t6002-rev-list-bisect.sh >trim-divergent-old
git show 090af9957c:t/t6002-rev-list-bisect.sh >trim-divergent-new
Why this pair
-------------
The diff-hunks store records only "trim-stable" pairs: those whose hunks
are identical whether or not xdiff trims the common head and tail (which
it does at zero context, in trim_common_tail). This pair is deliberately
NOT trim-stable:
diff -U0 reports 9 added / 6 deleted
diff -U3 reports 10 added / 7 deleted
Because the counts diverge with context, the writer must refuse to record
this pair and every command must recompute it from the blobs. t4220 uses
it to prove that the displayed counts stay correct at each context, and
that a divergent pair is never served from the store. See
t4220-diff-hunks.sh ("a trim-divergent file is correct at each context"
and the store-poison test).
Why not a synthesized fixture
-----------------------------
The divergence needs real content that makes xdiff's common-tail trimming
shift a hunk boundary while the added/deleted balance stays equal. A
minimal hand-written file that reliably triggers the -U0 vs -U3 count
disagreement has not been found yet; until one is, this real pair is kept
verbatim. If you synthesize a smaller equivalent, replace these two files
and delete this note.