Skip to content

Commit 844efbe

Browse files
committed
Merge branch 'ly/diff-name-only-with-diff-from-content' into jch
Various options to "git diff" that makes comparison ignore certain aspects of the differences (like "space changes are ignored", "differences in lines that match these regular expressions are ignored") did not work well with "--name-only" and friends. * ly/diff-name-only-with-diff-from-content: diff: ensure consistent diff behavior with ignore options
2 parents f37354f + b55e6d3 commit 844efbe

File tree

5 files changed

+70
-23
lines changed

5 files changed

+70
-23
lines changed

diff.c

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2438,6 +2438,15 @@ static int fn_out_consume(void *priv, char *line, unsigned long len)
24382438
return 0;
24392439
}
24402440

2441+
static int quick_consume(void *priv, char *line UNUSED, unsigned long len UNUSED)
2442+
{
2443+
struct emit_callback *ecbdata = priv;
2444+
struct diff_options *o = ecbdata->opt;
2445+
2446+
o->found_changes = 1;
2447+
return 1;
2448+
}
2449+
24412450
static void pprint_rename(struct strbuf *name, const char *a, const char *b)
24422451
{
24432452
const char *old_name = a;
@@ -3753,8 +3762,21 @@ static void builtin_diff(const char *name_a,
37533762

37543763
if (o->word_diff)
37553764
init_diff_words_data(&ecbdata, o, one, two);
3756-
if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
3757-
&ecbdata, &xpp, &xecfg))
3765+
if (o->dry_run) {
3766+
/*
3767+
* Unlike the !dry_run case, we need to ignore the
3768+
* return value from xdi_diff_outf() here, because
3769+
* xdi_diff_outf() takes non-zero return from its
3770+
* callback function as a sign of error and returns
3771+
* early (which is why we return non-zero from our
3772+
* callback, quick_consume()). Unfortunately,
3773+
* xdi_diff_outf() signals an error by returning
3774+
* non-zero.
3775+
*/
3776+
xdi_diff_outf(&mf1, &mf2, NULL, quick_consume,
3777+
&ecbdata, &xpp, &xecfg);
3778+
} else if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
3779+
&ecbdata, &xpp, &xecfg))
37583780
die("unable to generate diff for %s", one->path);
37593781
if (o->word_diff)
37603782
free_diff_words_data(&ecbdata);
@@ -6168,6 +6190,22 @@ static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
61686190
run_diff(p, o);
61696191
}
61706192

6193+
/* return 1 if any change is found; otherwise, return 0 */
6194+
static int diff_flush_patch_quietly(struct diff_filepair *p, struct diff_options *o)
6195+
{
6196+
int saved_dry_run = o->dry_run;
6197+
int saved_found_changes = o->found_changes;
6198+
int ret;
6199+
6200+
o->dry_run = 1;
6201+
o->found_changes = 0;
6202+
diff_flush_patch(p, o);
6203+
ret = o->found_changes;
6204+
o->dry_run = saved_dry_run;
6205+
o->found_changes |= saved_found_changes;
6206+
return ret;
6207+
}
6208+
61716209
static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
61726210
struct diffstat_t *diffstat)
61736211
{
@@ -6796,8 +6834,15 @@ void diff_flush(struct diff_options *options)
67966834
DIFF_FORMAT_CHECKDIFF)) {
67976835
for (i = 0; i < q->nr; i++) {
67986836
struct diff_filepair *p = q->queue[i];
6799-
if (check_pair_status(p))
6800-
flush_one_pair(p, options);
6837+
6838+
if (!check_pair_status(p))
6839+
continue;
6840+
6841+
if (options->flags.diff_from_contents &&
6842+
!diff_flush_patch_quietly(p, options))
6843+
continue;
6844+
6845+
flush_one_pair(p, options);
68016846
}
68026847
separator++;
68036848
}
@@ -6849,19 +6894,10 @@ void diff_flush(struct diff_options *options)
68496894
if (output_format & DIFF_FORMAT_NO_OUTPUT &&
68506895
options->flags.exit_with_status &&
68516896
options->flags.diff_from_contents) {
6852-
/*
6853-
* run diff_flush_patch for the exit status. setting
6854-
* options->file to /dev/null should be safe, because we
6855-
* aren't supposed to produce any output anyway.
6856-
*/
6857-
diff_free_file(options);
6858-
options->file = xfopen("/dev/null", "w");
6859-
options->close_file = 1;
6860-
options->color_moved = 0;
68616897
for (i = 0; i < q->nr; i++) {
68626898
struct diff_filepair *p = q->queue[i];
68636899
if (check_pair_status(p))
6864-
diff_flush_patch(p, options);
6900+
diff_flush_patch_quietly(p, options);
68656901
if (options->found_changes)
68666902
break;
68676903
}

diff.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ struct diff_options {
400400
#define COLOR_MOVED_WS_ERROR (1<<0)
401401
unsigned color_moved_ws_handling;
402402

403+
bool dry_run;
404+
403405
struct repository *repo;
404406
struct strmap *additional_path_headers;
405407

t/t4013-diff-various.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,19 @@ test_expect_success 'diff -I<regex>: detect malformed regex' '
648648
test_grep "invalid regex given to -I: " error
649649
'
650650

651+
test_expect_success 'diff -I<regex>: ignore matching file' '
652+
test_when_finished "git rm -f file1" &&
653+
test_seq 50 >file1 &&
654+
git add file1 &&
655+
test_seq 50 | sed -e "s/13/ten and three/" -e "s/^[124-9].*/& /" >file1 &&
656+
657+
: >actual &&
658+
git diff --raw --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
659+
git diff --name-only --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
660+
git diff --name-status --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
661+
test_grep ! "file1" actual
662+
'
663+
651664
# check_prefix <patch> <src> <dst>
652665
# check only lines with paths to avoid dependency on exact oid/contents
653666
check_prefix () {

t/t4015-diff-whitespace.sh

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@ test_description='Test special whitespace in diff engine.
1111
. "$TEST_DIRECTORY"/lib-diff.sh
1212

1313
for opt_res in --patch --quiet -s --stat --shortstat --dirstat=lines \
14-
--raw! --name-only! --name-status!
14+
--raw --name-only --name-status
1515
do
16-
opts=${opt_res%!} expect_failure=
17-
test "$opts" = "$opt_res" ||
18-
expect_failure="test_expect_code 1"
19-
2016
test_expect_success "status with $opts (different)" '
2117
echo foo >x &&
2218
git add x &&
@@ -43,7 +39,7 @@ do
4339
echo foo >x &&
4440
git add x &&
4541
echo " foo" >x &&
46-
$expect_failure git diff -w $opts --exit-code x
42+
git diff -w $opts --exit-code x
4743
'
4844
done
4945

xdiff-interface.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
* from an error internal to xdiff, xdiff itself will see that
2929
* non-zero return and translate it to -1.
3030
*
31-
* See "diff_grep" in diffcore-pickaxe.c for a trick to work around
32-
* this, i.e. using the "consume_callback_data" to note the desired
33-
* early return.
31+
* See "diff_grep" in diffcore-pickaxe.c and "quick_consume" in diff.c
32+
* for a trick to work around this, i.e. using the "consume_callback_data"
33+
* to note the desired early return.
3434
*/
3535
typedef int (*xdiff_emit_line_fn)(void *, char *, unsigned long);
3636
typedef void (*xdiff_emit_hunk_fn)(void *data,

0 commit comments

Comments
 (0)