mirror of
https://github.com/git/git
synced 2024-11-05 01:58:18 +00:00
diff: fix --exit-code with external diff
You can ask the diff machinery to let the exit code indicate whether there are changes, e.g. with --exit-code. It as two ways to calculate that bit: The quick one assumes blobs with different hashes have different content, and the more elaborate way actually compares the contents, possibly applying transformations like ignoring whitespace. Always use the slower path by setting the flag diff_from_contents, because any of the files could have an external diff driver set via an attribute, which might consider binary differences irrelevant, like e.g. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
7b30c3ad2d
commit
11be65cfa4
2 changed files with 38 additions and 3 deletions
33
diff.c
33
diff.c
|
@ -40,6 +40,7 @@
|
|||
#include "setup.h"
|
||||
#include "strmap.h"
|
||||
#include "ws.h"
|
||||
#include "write-or-die.h"
|
||||
|
||||
#ifdef NO_FAST_WORKING_DIRECTORY
|
||||
#define FAST_WORKING_DIRECTORY 0
|
||||
|
@ -4396,8 +4397,33 @@ static void run_external_diff(const char *pgm,
|
|||
diff_free_filespec_data(one);
|
||||
diff_free_filespec_data(two);
|
||||
cmd.use_shell = 1;
|
||||
if (run_command(&cmd))
|
||||
die(_("external diff died, stopping at %s"), name);
|
||||
if (o->flags.diff_from_contents) {
|
||||
int got_output = 0;
|
||||
cmd.out = -1;
|
||||
if (start_command(&cmd))
|
||||
die(_("external diff died, stopping at %s"), name);
|
||||
for (;;) {
|
||||
char buffer[8192];
|
||||
ssize_t len = xread(cmd.out, buffer, sizeof(buffer));
|
||||
if (!len)
|
||||
break;
|
||||
if (len < 0)
|
||||
die(_("unable to read from external diff,"
|
||||
" stopping at %s"), name);
|
||||
got_output = 1;
|
||||
if (write_in_full(1, buffer, len) < 0)
|
||||
die(_("unable to write output of external diff,"
|
||||
" stopping at %s"), name);
|
||||
}
|
||||
close(cmd.out);
|
||||
if (finish_command(&cmd))
|
||||
die(_("external diff died, stopping at %s"), name);
|
||||
if (got_output)
|
||||
o->found_changes = 1;
|
||||
} else {
|
||||
if (run_command(&cmd))
|
||||
die(_("external diff died, stopping at %s"), name);
|
||||
}
|
||||
|
||||
remove_tempfile();
|
||||
}
|
||||
|
@ -4844,6 +4870,7 @@ void diff_setup_done(struct diff_options *options)
|
|||
*/
|
||||
|
||||
if ((options->xdl_opts & XDF_WHITESPACE_FLAGS) ||
|
||||
options->flags.exit_with_status ||
|
||||
options->ignore_regex_nr)
|
||||
options->flags.diff_from_contents = 1;
|
||||
else
|
||||
|
@ -6732,7 +6759,7 @@ void diff_flush(struct diff_options *options)
|
|||
if (output_format & DIFF_FORMAT_CALLBACK)
|
||||
options->format_callback(q, options, options->format_callback_data);
|
||||
|
||||
if (output_format & DIFF_FORMAT_NO_OUTPUT &&
|
||||
if ((!output_format || output_format & DIFF_FORMAT_NO_OUTPUT) &&
|
||||
options->flags.exit_with_status &&
|
||||
options->flags.diff_from_contents) {
|
||||
/*
|
||||
|
|
|
@ -172,6 +172,14 @@ test_expect_success 'no diff with -diff' '
|
|||
grep Binary out
|
||||
'
|
||||
|
||||
test_expect_success 'diff.external and --exit-code with output' '
|
||||
test_expect_code 1 git -c diff.external=echo diff --exit-code
|
||||
'
|
||||
|
||||
test_expect_success 'diff.external and --exit-code without output' '
|
||||
git -c diff.external=true diff --exit-code
|
||||
'
|
||||
|
||||
echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file
|
||||
|
||||
test_expect_success 'force diff with "diff"' '
|
||||
|
|
Loading…
Reference in a new issue