Skip to content

Commit 1454f0a

Browse files
peffdscho
authored andcommitted
diff: restore redirection to /dev/null for diff_from_contents
Note: This is _not_ strictly necessary, but adds a layer of protection against bugs similar to the one that was reported very quickly after Git v2.51.1 was released, one time via https://lore.kernel.org/git/CACJRbWjwOQwJB13CwTfvhV3p+Hbn4KrNM9AtBanGtUS4V_1MbQ@mail.gmail.com/ and one time via https://lore.kernel.org/git/527ba5fb-5fc1-b34c-9c93-61cd919da78f@gmx.de/. In --quiet mode, since we produce only an exit code for "something was changed" and no actual output, we can often get by with just a tree-level diff. However, certain options require us to actually look at the file contents (e.g., if we are ignoring whitespace changes). We have a flag "diff_from_contents" for that, and if it is set we call diff_flush() on each path. To avoid producing any output (since we were asked to be --quiet), we traditionally just redirected the output to /dev/null. That changed in b55e6d3 (diff: ensure consistent diff behavior with ignore options, 2025-08-08), which replaced that with a "dry_run" flag. In theory, with dry_run set, we should produce no output. But it carries a risk of regression: if we forget to respect dry_run in any of the output paths, we'll accidentally produce output. And indeed, there is at least one such regression in that commit, as it covered only the case where we actually call into xdiff, and not creation or deletion diffs, where we manually generate the headers. We even test this case in t4035, but only with diff-tree, which does not show the bug by default because it does not require diff_from_contents. But git-diff does, because it allows external diff programs by default (so we must dig into each diff filepair to decide if it requires running an external diff that may declare two distinct blobs to actually be the same). We should fix all of those code paths to respect dry_run correctly, but in the meantime we can protect ourselves more fully by restoring the redirection to /dev/null. This gives us an extra layer of protection against regressions dues to other code paths we've missed. Though the original issue was reported with "git diff" (and due to its default of --ext-diff), I've used "diff-tree -w" in the new test. It triggers the same issue, but I think the fact that "-w" implies diff_from_contents is a bit more obvious, and fits in with the rest of t4035. Reported-by: Jake Zimmerman <jake@zimmerman.io> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 3b8dce0 commit 1454f0a

File tree

2 files changed

+13
-0
lines changed

2 files changed

+13
-0
lines changed

diff.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6879,6 +6879,15 @@ void diff_flush(struct diff_options *options)
68796879
if (output_format & DIFF_FORMAT_NO_OUTPUT &&
68806880
options->flags.exit_with_status &&
68816881
options->flags.diff_from_contents) {
6882+
/*
6883+
* run diff_flush_patch for the exit status. setting
6884+
* options->file to /dev/null should be safe, because we
6885+
* aren't supposed to produce any output anyway.
6886+
*/
6887+
diff_free_file(options);
6888+
options->file = xfopen("/dev/null", "w");
6889+
options->close_file = 1;
6890+
options->color_moved = 0;
68826891
for (i = 0; i < q->nr; i++) {
68836892
struct diff_filepair *p = q->queue[i];
68846893
if (check_pair_status(p))

t/t4035-diff-quiet.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ test_expect_success 'git diff-tree HEAD HEAD' '
5050
test_expect_code 0 git diff-tree --quiet HEAD HEAD >cnt &&
5151
test_line_count = 0 cnt
5252
'
53+
test_expect_success 'git diff-tree -w HEAD^ HEAD' '
54+
test_expect_code 1 git diff-tree --quiet -w HEAD^ HEAD >cnt &&
55+
test_line_count = 0 cnt
56+
'
5357
test_expect_success 'git diff-files' '
5458
test_expect_code 0 git diff-files --quiet >cnt &&
5559
test_line_count = 0 cnt

0 commit comments

Comments
 (0)