Git fork

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

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
··· 2438 2438 return 0; 2439 2439 } 2440 2440 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 + 2441 2450 static void pprint_rename(struct strbuf *name, const char *a, const char *b) 2442 2451 { 2443 2452 const char *old_name = a; ··· 3753 3762 3754 3763 if (o->word_diff) 3755 3764 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)) 3758 3780 die("unable to generate diff for %s", one->path); 3759 3781 if (o->word_diff) 3760 3782 free_diff_words_data(&ecbdata); ··· 6144 6166 run_diff(p, o); 6145 6167 } 6146 6168 6169 + /* return 1 if any change is found; otherwise, return 0 */ 6170 + static int diff_flush_patch_quietly(struct diff_filepair *p, struct diff_options *o) 6171 + { 6172 + int saved_dry_run = o->dry_run; 6173 + int saved_found_changes = o->found_changes; 6174 + int ret; 6175 + 6176 + o->dry_run = 1; 6177 + o->found_changes = 0; 6178 + diff_flush_patch(p, o); 6179 + ret = o->found_changes; 6180 + o->dry_run = saved_dry_run; 6181 + o->found_changes |= saved_found_changes; 6182 + return ret; 6183 + } 6184 + 6147 6185 static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o, 6148 6186 struct diffstat_t *diffstat) 6149 6187 { ··· 6772 6810 DIFF_FORMAT_CHECKDIFF)) { 6773 6811 for (i = 0; i < q->nr; i++) { 6774 6812 struct diff_filepair *p = q->queue[i]; 6775 - if (check_pair_status(p)) 6776 - flush_one_pair(p, options); 6813 + 6814 + if (!check_pair_status(p)) 6815 + continue; 6816 + 6817 + if (options->flags.diff_from_contents && 6818 + !diff_flush_patch_quietly(p, options)) 6819 + continue; 6820 + 6821 + flush_one_pair(p, options); 6777 6822 } 6778 6823 separator++; 6779 6824 } ··· 6825 6870 if (output_format & DIFF_FORMAT_NO_OUTPUT && 6826 6871 options->flags.exit_with_status && 6827 6872 options->flags.diff_from_contents) { 6828 - /* 6829 - * run diff_flush_patch for the exit status. setting 6830 - * options->file to /dev/null should be safe, because we 6831 - * aren't supposed to produce any output anyway. 6832 - */ 6833 - diff_free_file(options); 6834 - options->file = xfopen("/dev/null", "w"); 6835 - options->close_file = 1; 6836 - options->color_moved = 0; 6837 6873 for (i = 0; i < q->nr; i++) { 6838 6874 struct diff_filepair *p = q->queue[i]; 6839 6875 if (check_pair_status(p)) 6840 - diff_flush_patch(p, options); 6876 + diff_flush_patch_quietly(p, options); 6841 6877 if (options->found_changes) 6842 6878 break; 6843 6879 }
+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,