Git fork

Merge branch 'ly/diff-name-only-with-diff-from-content' into maint-2.51

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

+70 -23
+50 -14
diff.c
··· 2444 2444 return 0; 2445 2445 } 2446 2446 2447 + static int quick_consume(void *priv, char *line UNUSED, unsigned long len UNUSED) 2448 + { 2449 + struct emit_callback *ecbdata = priv; 2450 + struct diff_options *o = ecbdata->opt; 2451 + 2452 + o->found_changes = 1; 2453 + return 1; 2454 + } 2455 + 2447 2456 static void pprint_rename(struct strbuf *name, const char *a, const char *b) 2448 2457 { 2449 2458 const char *old_name = a; ··· 3759 3768 3760 3769 if (o->word_diff) 3761 3770 init_diff_words_data(&ecbdata, o, one, two); 3762 - if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume, 3763 - &ecbdata, &xpp, &xecfg)) 3771 + if (o->dry_run) { 3772 + /* 3773 + * Unlike the !dry_run case, we need to ignore the 3774 + * return value from xdi_diff_outf() here, because 3775 + * xdi_diff_outf() takes non-zero return from its 3776 + * callback function as a sign of error and returns 3777 + * early (which is why we return non-zero from our 3778 + * callback, quick_consume()). Unfortunately, 3779 + * xdi_diff_outf() signals an error by returning 3780 + * non-zero. 3781 + */ 3782 + xdi_diff_outf(&mf1, &mf2, NULL, quick_consume, 3783 + &ecbdata, &xpp, &xecfg); 3784 + } else if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume, 3785 + &ecbdata, &xpp, &xecfg)) 3764 3786 die("unable to generate diff for %s", one->path); 3765 3787 if (o->word_diff) 3766 3788 free_diff_words_data(&ecbdata); ··· 6150 6172 run_diff(p, o); 6151 6173 } 6152 6174 6175 + /* return 1 if any change is found; otherwise, return 0 */ 6176 + static int diff_flush_patch_quietly(struct diff_filepair *p, struct diff_options *o) 6177 + { 6178 + int saved_dry_run = o->dry_run; 6179 + int saved_found_changes = o->found_changes; 6180 + int ret; 6181 + 6182 + o->dry_run = 1; 6183 + o->found_changes = 0; 6184 + diff_flush_patch(p, o); 6185 + ret = o->found_changes; 6186 + o->dry_run = saved_dry_run; 6187 + o->found_changes |= saved_found_changes; 6188 + return ret; 6189 + } 6190 + 6153 6191 static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o, 6154 6192 struct diffstat_t *diffstat) 6155 6193 { ··· 6778 6816 DIFF_FORMAT_CHECKDIFF)) { 6779 6817 for (i = 0; i < q->nr; i++) { 6780 6818 struct diff_filepair *p = q->queue[i]; 6781 - if (check_pair_status(p)) 6782 - flush_one_pair(p, options); 6819 + 6820 + if (!check_pair_status(p)) 6821 + continue; 6822 + 6823 + if (options->flags.diff_from_contents && 6824 + !diff_flush_patch_quietly(p, options)) 6825 + continue; 6826 + 6827 + flush_one_pair(p, options); 6783 6828 } 6784 6829 separator++; 6785 6830 } ··· 6831 6876 if (output_format & DIFF_FORMAT_NO_OUTPUT && 6832 6877 options->flags.exit_with_status && 6833 6878 options->flags.diff_from_contents) { 6834 - /* 6835 - * run diff_flush_patch for the exit status. setting 6836 - * options->file to /dev/null should be safe, because we 6837 - * aren't supposed to produce any output anyway. 6838 - */ 6839 - diff_free_file(options); 6840 - options->file = xfopen("/dev/null", "w"); 6841 - options->close_file = 1; 6842 - options->color_moved = 0; 6843 6879 for (i = 0; i < q->nr; i++) { 6844 6880 struct diff_filepair *p = q->queue[i]; 6845 6881 if (check_pair_status(p)) 6846 - diff_flush_patch(p, options); 6882 + diff_flush_patch_quietly(p, options); 6847 6883 if (options->found_changes) 6848 6884 break; 6849 6885 }
+2
diff.h
··· 400 400 #define COLOR_MOVED_WS_ERROR (1<<0) 401 401 unsigned color_moved_ws_handling; 402 402 403 + bool dry_run; 404 + 403 405 struct repository *repo; 404 406 struct strmap *additional_path_headers; 405 407
+13
t/t4013-diff-various.sh
··· 648 648 test_grep "invalid regex given to -I: " error 649 649 ' 650 650 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 + 651 664 # check_prefix <patch> <src> <dst> 652 665 # check only lines with paths to avoid dependency on exact oid/contents 653 666 check_prefix () {
+2 -6
t/t4015-diff-whitespace.sh
··· 11 11 . "$TEST_DIRECTORY"/lib-diff.sh 12 12 13 13 for opt_res in --patch --quiet -s --stat --shortstat --dirstat=lines \ 14 - --raw! --name-only! --name-status! 14 + --raw --name-only --name-status 15 15 do 16 - opts=${opt_res%!} expect_failure= 17 - test "$opts" = "$opt_res" || 18 - expect_failure="test_expect_code 1" 19 - 20 16 test_expect_success "status with $opts (different)" ' 21 17 echo foo >x && 22 18 git add x && ··· 43 39 echo foo >x && 44 40 git add x && 45 41 echo " foo" >x && 46 - $expect_failure git diff -w $opts --exit-code x 42 + git diff -w $opts --exit-code x 47 43 ' 48 44 done 49 45
+3 -3
xdiff-interface.h
··· 28 28 * from an error internal to xdiff, xdiff itself will see that 29 29 * non-zero return and translate it to -1. 30 30 * 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. 34 34 */ 35 35 typedef int (*xdiff_emit_line_fn)(void *, char *, unsigned long); 36 36 typedef void (*xdiff_emit_hunk_fn)(void *data,