Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> --- diff.c | 10 ++-- diff.h | 1 + t/t4015-diff-whitespace.sh | 114 ++++++++++++++++++++++++++++++++++++++++++++- See, only 10 lines of code! (and a few more for tests) We have run out of space in diff_options.flags,touched_flags. as we 1<<U31 as the highest bit. We could reuse 1<<9 that is currently unused (removed in 882749a04f (diff: add --word-diff option that generalizes --color-words, 2010-04-14)). But that postpones the real fix for only a short amount of time. Ideas welcome how to extend the flag space. (We cannot just make it a long either, as some arcane architecures have 32 bit longs.) Another TODO: documentation I plan to trim the CC list for any resend that will be needed. Thanks, Stefan 3 files changed, 121 insertions(+), 4 deletions(-) diff --git a/diff.c b/diff.c index c4a669ffa8..ddb2018307 100644 --- a/diff.c +++ b/diff.c @@ -726,7 +726,8 @@ static int next_byte(const char **cp, const char **endp, return (int)' '; } - if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE)) { + if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE) || + diffopt->color_moved_ignore_space) { while (*cp < *endp && isspace(**cp)) (*cp)++; /* @@ -751,7 +752,8 @@ static int moved_entry_cmp(const struct diff_options *diffopt, const char *ap = a->es->line, *ae = a->es->line + a->es->len; const char *bp = b->es->line, *be = b->es->line + b->es->len; - if (!(diffopt->xdl_opts & XDF_WHITESPACE_FLAGS)) + if (!(diffopt->xdl_opts & XDF_WHITESPACE_FLAGS) && + !diffopt->color_moved_ignore_space) return a->es->len != b->es->len || memcmp(ap, bp, a->es->len); if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_AT_EOL)) { @@ -774,7 +776,7 @@ static int moved_entry_cmp(const struct diff_options *diffopt, static unsigned get_string_hash(struct emitted_diff_symbol *es, struct diff_options *o) { - if (o->xdl_opts & XDF_WHITESPACE_FLAGS) { + if ((o->xdl_opts & XDF_WHITESPACE_FLAGS) || o->color_moved_ignore_space) { static struct strbuf sb = STRBUF_INIT; const char *ap = es->line, *ae = es->line + es->len; int c; @@ -4660,6 +4662,8 @@ int diff_opt_parse(struct diff_options *options, DIFF_XDL_CLR(options, NEED_MINIMAL); else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) DIFF_XDL_SET(options, IGNORE_WHITESPACE); + else if (!strcmp(arg, "--ignore-all-space-in-move-detection")) + options->color_moved_ignore_space = 1; else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change")) DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE); else if (!strcmp(arg, "--ignore-space-at-eol")) diff --git a/diff.h b/diff.h index aca150ba2e..6ba3f53bbd 100644 --- a/diff.h +++ b/diff.h @@ -196,6 +196,7 @@ struct diff_options { } color_moved; #define COLOR_MOVED_DEFAULT COLOR_MOVED_ZEBRA #define COLOR_MOVED_MIN_ALNUM_COUNT 20 + int color_moved_ignore_space; }; void diff_emit_submodule_del(struct diff_options *o, const char *line); diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 6c9a93b734..d7ee3aabf2 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -1677,7 +1677,119 @@ test_expect_success 'move detection with submodules' ' # nor did we mess with it another way git diff --submodule=diff --color | test_decode_color >expect && - test_cmp expect decoded_actual + test_cmp expect decoded_actual && + rm -rf bananas && + git submodule deinit bananas +' + +test_expect_success 'move detection only ignores white spaces' ' + git reset --hard && + q_to_tab <<-\EOF >function.c && + int func() + { + Qif (foo) { + QQ// this part of the function + QQ// function will be very long + QQ// indeed. We must exceed both + QQ// per-line and number of line + QQ// minimums + QQ; + Q} + Qbaz(); + Qbar(); + Q// more unrelated stuff + } + EOF + git add function.c && + git commit -m "add function.c" && + q_to_tab <<-\EOF >function.c && + int do_foo() + { + Q// this part of the function + Q// function will be very long + Q// indeed. We must exceed both + Q// per-line and number of line + Q// minimums + Q; + } + + int func() + { + Qif (foo) + QQdo_foo(); + Qbaz(); + Qbar(); + Q// more unrelated stuff + } + EOF + + # Make sure we get a different diff using -w ("moved function header") + git diff --color --color-moved -w | + grep -v "index" | + test_decode_color >actual && + q_to_tab <<-\EOF >expected && + <BOLD>diff --git a/function.c b/function.c<RESET> + <BOLD>--- a/function.c<RESET> + <BOLD>+++ b/function.c<RESET> + <CYAN>@@ -1,6 +1,5 @@<RESET> + <RED>-int func()<RESET> + <GREEN>+<RESET><GREEN>int do_foo()<RESET> + {<RESET> + <RED>- if (foo) {<RESET> + Q// this part of the function<RESET> + Q// function will be very long<RESET> + Q// indeed. We must exceed both<RESET> + <CYAN>@@ -8,6 +7,11 @@<RESET> <RESET>int func()<RESET> + Q// minimums<RESET> + Q;<RESET> + }<RESET> + <GREEN>+<RESET> + <GREEN>+<RESET><GREEN>int func()<RESET> + <GREEN>+<RESET><GREEN>{<RESET> + <GREEN>+<RESET>Q<GREEN>if (foo)<RESET> + <GREEN>+<RESET>QQ<GREEN>do_foo();<RESET> + Qbaz();<RESET> + Qbar();<RESET> + Q// more unrelated stuff<RESET> + EOF + test_cmp expected actual && + + # And now ignoring white space only in the move detection + git diff --color --color-moved --ignore-all-space-in-move-detection | + grep -v "index" | + test_decode_color >actual && + q_to_tab <<-\EOF >expected && + <BOLD>diff --git a/function.c b/function.c<RESET> + <BOLD>--- a/function.c<RESET> + <BOLD>+++ b/function.c<RESET> + <CYAN>@@ -1,13 +1,17 @@<RESET> + <GREEN>+<RESET><GREEN>int do_foo()<RESET> + <GREEN>+<RESET><GREEN>{<RESET> + <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>// this part of the function<RESET> + <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>// function will be very long<RESET> + <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>// indeed. We must exceed both<RESET> + <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>// per-line and number of line<RESET> + <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>// minimums<RESET> + <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>;<RESET> + <BOLD;CYAN>+<RESET><BOLD;CYAN>}<RESET> + <GREEN>+<RESET> + int func()<RESET> + {<RESET> + <RED>-Qif (foo) {<RESET> + <BOLD;MAGENTA>-QQ// this part of the function<RESET> + <BOLD;MAGENTA>-QQ// function will be very long<RESET> + <BOLD;MAGENTA>-QQ// indeed. We must exceed both<RESET> + <BOLD;MAGENTA>-QQ// per-line and number of line<RESET> + <BOLD;MAGENTA>-QQ// minimums<RESET> + <BOLD;MAGENTA>-QQ;<RESET> + <BOLD;MAGENTA>-Q}<RESET> + <GREEN>+<RESET>Q<GREEN>if (foo)<RESET> + <GREEN>+<RESET>QQ<GREEN>do_foo();<RESET> + Qbaz();<RESET> + Qbar();<RESET> + Q// more unrelated stuff<RESET> + EOF + test_cmp expected actual ' test_done -- 2.15.0.rc2.6.g953226eb5f