Signed-off-by: Stefan Beller <sbel...@google.com>
---

 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

Reply via email to