From: Phillip Wood <phillip.w...@dunelm.org.uk>

Currently when using --color-moved=zebra the color of moved blocks
depends on the number of lines separating them. This means that adding
an odd number of unmoved lines between blocks that are already separated
by one or more unmoved lines will change the color of subsequent moved
blocks. This does not make much sense as the blocks were already
separated by unmoved lines and causes problems when adding lines to test
cases.

Fix this by only using the alternate colors for adjacent moved blocks.

Signed-off-by: Phillip Wood <phillip.w...@dunelm.org.uk>
---

Notes:
    An alternative would be to always alternate the color of blocks whether
    are not they are adjacent to each other.

 diff.c                     | 27 +++++++++++++++++++--------
 t/t4015-diff-whitespace.sh |  6 +++---
 2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/diff.c b/diff.c
index 53a7ab5aca..8c08dd68df 100644
--- a/diff.c
+++ b/diff.c
@@ -1038,26 +1038,30 @@ static int shrink_potential_moved_blocks(struct 
moved_block *pmb,
  * The last block consists of the (n - block_length)'th line up to but not
  * including the nth line.
  *
+ * Returns 0 if the last block is empty or is unset by this function, non zero
+ * otherwise.
+ *
  * NEEDSWORK: This uses the same heuristic as blame_entry_score() in blame.c.
  * Think of a way to unify them.
  */
-static void adjust_last_block(struct diff_options *o, int n, int block_length)
+static int adjust_last_block(struct diff_options *o, int n, int block_length)
 {
        int i, alnum_count = 0;
        if (o->color_moved == COLOR_MOVED_PLAIN)
-               return;
+               return block_length;
        for (i = 1; i < block_length + 1; i++) {
                const char *c = o->emitted_symbols->buf[n - i].line;
                for (; *c; c++) {
                        if (!isalnum(*c))
                                continue;
                        alnum_count++;
                        if (alnum_count >= COLOR_MOVED_MIN_ALNUM_COUNT)
-                               return;
+                               return 1;
                }
        }
        for (i = 1; i < block_length + 1; i++)
                o->emitted_symbols->buf[n - i].flags &= ~DIFF_SYMBOL_MOVED_LINE;
+       return 0;
 }
 
 /* Find blocks of moved code, delegate actual coloring decision to helper */
@@ -1067,14 +1071,15 @@ static void mark_color_as_moved(struct diff_options *o,
 {
        struct moved_block *pmb = NULL; /* potentially moved blocks */
        int pmb_nr = 0, pmb_alloc = 0;
-       int n, flipped_block = 1, block_length = 0;
+       int n, flipped_block = 0, block_length = 0;
 
 
        for (n = 0; n < o->emitted_symbols->nr; n++) {
                struct hashmap *hm = NULL;
                struct moved_entry *key;
                struct moved_entry *match = NULL;
                struct emitted_diff_symbol *l = &o->emitted_symbols->buf[n];
+               enum diff_symbol last_symbol = 0;
 
                switch (l->s) {
                case DIFF_SYMBOL_PLUS:
@@ -1090,7 +1095,7 @@ static void mark_color_as_moved(struct diff_options *o,
                        free(key);
                        break;
                default:
-                       flipped_block = 1;
+                       flipped_block = 0;
                }
 
                if (!match) {
@@ -1101,10 +1106,13 @@ static void mark_color_as_moved(struct diff_options *o,
                                moved_block_clear(&pmb[i]);
                        pmb_nr = 0;
                        block_length = 0;
+                       flipped_block = 0;
+                       last_symbol = l->s;
                        continue;
                }
 
                if (o->color_moved == COLOR_MOVED_PLAIN) {
+                       last_symbol = l->s;
                        l->flags |= DIFF_SYMBOL_MOVED_LINE;
                        continue;
                }
@@ -1135,19 +1143,22 @@ static void mark_color_as_moved(struct diff_options *o,
                                }
                        }
 
-                       flipped_block = (flipped_block + 1) % 2;
+                       if (adjust_last_block(o, n, block_length) &&
+                           pmb_nr && last_symbol != l->s)
+                               flipped_block = (flipped_block + 1) % 2;
+                       else
+                               flipped_block = 0;
 
-                       adjust_last_block(o, n, block_length);
                        block_length = 0;
                }
 
                if (pmb_nr) {
                        block_length++;
-
                        l->flags |= DIFF_SYMBOL_MOVED_LINE;
                        if (flipped_block && o->color_moved != 
COLOR_MOVED_BLOCKS)
                                l->flags |= DIFF_SYMBOL_MOVED_LINE_ALT;
                }
+               last_symbol = l->s;
        }
        adjust_last_block(o, n, block_length);
 
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index eee81a1987..fe8a2ab06e 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -1802,14 +1802,14 @@ test_expect_success 'only move detection ignores white 
spaces' '
        <BOLD;MAGENTA>-a long line to exceed per-line minimum<RESET>
        <BOLD;MAGENTA>-another long line to exceed per-line minimum<RESET>
        <RED>-original file<RESET>
-       <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>a long line to exceed per-line 
minimum<RESET>
-       <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>another long line to exceed per-line 
minimum<RESET>
+       <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>a long line to exceed per-line 
minimum<RESET>
+       <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>another long line to exceed per-line 
minimum<RESET>
        <GREEN>+<RESET><GREEN>new file<RESET>
        EOF
        test_cmp expected actual
 '
 
-test_expect_failure 'compare whitespace delta across moved blocks' '
+test_expect_success 'compare whitespace delta across moved blocks' '
 
        git reset --hard &&
        q_to_tab <<-\EOF >text.txt &&
-- 
2.19.1

Reply via email to