builtin/diff-pairs: allow explicit diff queue flush

The diffs queued from git-diff-pairs(1) are flushed when stdin is
closed. To enable greater flexibility, allow control over when the diff
queue is flushed by writing a single NUL byte on stdin between input
file pairs. Diff output between flushes is separated by a single NUL
byte.

Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Justin Tobler 2025-02-28 15:33:46 -06:00 committed by Junio C Hamano
parent 5bd10b2adc
commit cf15095ec5
3 changed files with 27 additions and 0 deletions

View File

@ -17,6 +17,10 @@ in the NUL-terminated raw output format as generated by commands such as `git
diff-tree -z -r --raw`. By default, the outputted diffs are computed and shown
in the patch format when stdin closes.

A single NUL byte may be written to stdin between raw input lines to compute
file pair diffs up to that point instead of waiting for stdin to close. A NUL
byte is also written to the output to delimit between these batches of diffs.

Usage of this command enables the traditional diff pipeline to be broken up
into separate stages where `diff-pairs` acts as the output phase. Other
commands, such as `diff-tree`, may serve as a frontend to compute the raw

View File

@ -57,6 +57,7 @@ int cmd_diff_pairs(int argc, const char **argv, const char *prefix,
show_usage_with_options_if_asked(argc, argv, builtin_diff_pairs_usage, parseopts);

repo_config(repo, git_diff_basic_config, NULL);
revs.diffopt.no_free = 1;
revs.disable_stdin = 1;
revs.abbrev = 0;
revs.diff = 1;
@ -106,6 +107,18 @@ int cmd_diff_pairs(int argc, const char **argv, const char *prefix,
break;

p = meta.buf;
if (!*p) {
diffcore_std(&revs.diffopt);
diff_flush(&revs.diffopt);
/*
* When the diff queue is explicitly flushed, append a
* NUL byte to separate batches of diffs.
*/
fputc('\0', revs.diffopt.file);
fflush(revs.diffopt.file);
continue;
}

if (*p != ':')
die(_("invalid raw diff input"));
p++;
@ -179,6 +192,7 @@ int cmd_diff_pairs(int argc, const char **argv, const char *prefix,
}
}

revs.diffopt.no_free = 0;
diffcore_std(&revs.diffopt);
diff_flush(&revs.diffopt);
ret = diff_result_code(&revs);

View File

@ -78,4 +78,13 @@ test_expect_success 'diff-pairs does not support pathspec arguments' '
test_cmp expect err
'

test_expect_success 'diff-pairs explicit queue flush' '
git diff-tree -r -M -C -C -z base new >expect &&
printf "\0" >>expect &&
git diff-tree -r -M -C -C -z base new >>expect &&

git diff-pairs --raw -z <expect >actual &&
test_cmp expect actual
'

test_done