Skip to content

Commit a264c51

Browse files
committed
Merge branch 'ly/diff-name-only-with-diff-from-content' into seen
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. Looking better. * ly/diff-name-only-with-diff-from-content: fixup! diff: ensure consistent diff behavior with ignore options diff: ensure consistent diff behavior with ignore options
2 parents 990db2f + 9795c1d commit a264c51

File tree

5 files changed

+74
-20
lines changed

5 files changed

+74
-20
lines changed

diff.c

Lines changed: 51 additions & 16 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;
@@ -3703,6 +3712,7 @@ static void builtin_diff(const char *name_a,
37033712
xdemitconf_t xecfg;
37043713
struct emit_callback ecbdata;
37053714
const struct userdiff_funcname *pe;
3715+
int dry_run = o->diff_optimize == DIFF_OPT_DRY_RUN;
37063716

37073717
if (must_show_header) {
37083718
emit_diff_symbol(o, DIFF_SYMBOL_HEADER,
@@ -3735,16 +3745,17 @@ static void builtin_diff(const char *name_a,
37353745
xpp.ignore_regex_nr = o->ignore_regex_nr;
37363746
xpp.anchors = o->anchors;
37373747
xpp.anchors_nr = o->anchors_nr;
3738-
xecfg.ctxlen = o->context;
3739-
xecfg.interhunkctxlen = o->interhunkcontext;
3748+
xecfg.ctxlen = dry_run ? 0 : o->context;
3749+
xecfg.interhunkctxlen = dry_run ? 0 : o->interhunkcontext;
37403750
xecfg.flags = XDL_EMIT_FUNCNAMES;
37413751
if (o->flags.funccontext)
37423752
xecfg.flags |= XDL_EMIT_FUNCCONTEXT;
37433753
if (pe)
37443754
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
37453755

37463756
diffopts = getenv("GIT_DIFF_OPTS");
3747-
if (!diffopts)
3757+
/* ignore ctxlen if we are in dry run mode */
3758+
if (!diffopts || dry_run)
37483759
;
37493760
else if (skip_prefix(diffopts, "--unified=", &v))
37503761
xecfg.ctxlen = strtoul(v, NULL, 10);
@@ -3753,8 +3764,11 @@ static void builtin_diff(const char *name_a,
37533764

37543765
if (o->word_diff)
37553766
init_diff_words_data(&ecbdata, o, one, two);
3756-
if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
3757-
&ecbdata, &xpp, &xecfg))
3767+
if (dry_run)
3768+
xdi_diff_outf(&mf1, &mf2, NULL, quick_consume,
3769+
&ecbdata, &xpp, &xecfg);
3770+
else if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
3771+
&ecbdata, &xpp, &xecfg))
37583772
die("unable to generate diff for %s", one->path);
37593773
if (o->word_diff)
37603774
free_diff_words_data(&ecbdata);
@@ -4985,6 +4999,8 @@ void diff_setup_done(struct diff_options *options)
49854999

49865000
if (options->pathspec.has_wildcard && options->max_depth_valid)
49875001
die("max-depth cannot be used with wildcard pathspecs");
5002+
5003+
options->diff_optimize = DIFF_OPT_NONE;
49885004
}
49895005

49905006
int parse_long_opt(const char *opt, const char **argv,
@@ -6163,6 +6179,22 @@ static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
61636179
run_diff(p, o);
61646180
}
61656181

6182+
/* return 1 if any change is found; otherwise, return 0 */
6183+
static int diff_flush_patch_quiet(struct diff_filepair *p, struct diff_options *o)
6184+
{
6185+
int diff_opt = o->diff_optimize;
6186+
int found_changes = o->found_changes;
6187+
int ret;
6188+
6189+
o->diff_optimize = DIFF_OPT_DRY_RUN;
6190+
o->found_changes = 0;
6191+
diff_flush_patch(p, o);
6192+
ret = o->found_changes;
6193+
o->diff_optimize = diff_opt;
6194+
o->found_changes |= found_changes;
6195+
return ret;
6196+
}
6197+
61666198
static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
61676199
struct diffstat_t *diffstat)
61686200
{
@@ -6791,7 +6823,19 @@ void diff_flush(struct diff_options *options)
67916823
DIFF_FORMAT_CHECKDIFF)) {
67926824
for (i = 0; i < q->nr; i++) {
67936825
struct diff_filepair *p = q->queue[i];
6794-
if (check_pair_status(p))
6826+
int need_flush = 1;
6827+
6828+
if (!check_pair_status(p))
6829+
continue;
6830+
6831+
if (options->flags.diff_from_contents) {
6832+
if (diff_flush_patch_quiet(p, options))
6833+
need_flush = 1;
6834+
else
6835+
need_flush = 0;
6836+
}
6837+
6838+
if (need_flush)
67956839
flush_one_pair(p, options);
67966840
}
67976841
separator++;
@@ -6844,19 +6888,10 @@ void diff_flush(struct diff_options *options)
68446888
if (output_format & DIFF_FORMAT_NO_OUTPUT &&
68456889
options->flags.exit_with_status &&
68466890
options->flags.diff_from_contents) {
6847-
/*
6848-
* run diff_flush_patch for the exit status. setting
6849-
* options->file to /dev/null should be safe, because we
6850-
* aren't supposed to produce any output anyway.
6851-
*/
6852-
diff_free_file(options);
6853-
options->file = xfopen("/dev/null", "w");
6854-
options->close_file = 1;
6855-
options->color_moved = 0;
68566891
for (i = 0; i < q->nr; i++) {
68576892
struct diff_filepair *p = q->queue[i];
68586893
if (check_pair_status(p))
6859-
diff_flush_patch(p, options);
6894+
diff_flush_patch_quiet(p, options);
68606895
if (options->found_changes)
68616896
break;
68626897
}

diff.h

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

403+
enum {
404+
DIFF_OPT_NONE = 0,
405+
DIFF_OPT_DRY_RUN = 1,
406+
} diff_optimize;
407+
403408
struct repository *repo;
404409
struct strmap *additional_path_headers;
405410

t/t4013-diff-various.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,20 @@ 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_seq 50 >file1 &&
653+
git add file1 &&
654+
test_seq 50 | sed -e "s/13/ten and three/" -e "s/^[124-9].*/& /" >file1 &&
655+
656+
: >actual &&
657+
git diff --raw --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
658+
git diff --name-only --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
659+
git diff --name-status --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
660+
! grep "file1" actual &&
661+
662+
git rm -f file1
663+
'
664+
651665
# check_prefix <patch> <src> <dst>
652666
# check only lines with paths to avoid dependency on exact oid/contents
653667
check_prefix () {

t/t4015-diff-whitespace.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ 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
1616
opts=${opt_res%!} expect_failure=
1717
test "$opts" = "$opt_res" ||

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)