Merge branch 'jk/diff-color-moved-fix' into maint

The experimental "color moved lines differently in diff output"
feature was buggy around "ignore whitespace changes" edges, whihch
has been corrected.

* jk/diff-color-moved-fix:
  diff: handle NULs in get_string_hash()
  diff: fix whitespace-skipping with --color-moved
  t4015: test the output of "diff --color-moved -b"
  t4015: check "negative" case for "-w --color-moved"
  t4015: refactor --color-moved whitespace test
This commit is contained in:
Junio C Hamano 2017-11-15 12:04:51 +09:00
commit fd506238f0
2 changed files with 188 additions and 42 deletions

17
diff.c
View File

@ -712,7 +712,7 @@ static int next_byte(const char **cp, const char **endp,
{ {
int retval; int retval;
if (*cp > *endp) if (*cp >= *endp)
return -1; return -1;
if (isspace(**cp)) { if (isspace(**cp)) {
@ -729,7 +729,12 @@ static int next_byte(const char **cp, const char **endp,
if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE)) { if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE)) {
while (*cp < *endp && isspace(**cp)) while (*cp < *endp && isspace(**cp))
(*cp)++; (*cp)++;
/* return the first non-ws character via the usual below */ /*
* return the first non-ws character via the usual
* below, unless we ate all of the bytes
*/
if (*cp >= *endp)
return -1;
} }
} }
@ -750,9 +755,9 @@ static int moved_entry_cmp(const struct diff_options *diffopt,
return a->es->len != b->es->len || memcmp(ap, bp, a->es->len); return a->es->len != b->es->len || memcmp(ap, bp, a->es->len);
if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_AT_EOL)) { if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_AT_EOL)) {
while (ae > ap && isspace(*ae)) while (ae > ap && isspace(ae[-1]))
ae--; ae--;
while (be > bp && isspace(*be)) while (be > bp && isspace(be[-1]))
be--; be--;
} }
@ -775,9 +780,9 @@ static unsigned get_string_hash(struct emitted_diff_symbol *es, struct diff_opti
int c; int c;
strbuf_reset(&sb); strbuf_reset(&sb);
while (ae > ap && isspace(*ae)) while (ae > ap && isspace(ae[-1]))
ae--; ae--;
while ((c = next_byte(&ap, &ae, o)) > 0) while ((c = next_byte(&ap, &ae, o)) >= 0)
strbuf_addch(&sb, c); strbuf_addch(&sb, c);
return memhash(sb.buf, sb.len); return memhash(sb.buf, sb.len);

View File

@ -1318,30 +1318,38 @@ test_expect_success 'no effect from --color-moved with --word-diff' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'move detection ignoring whitespace ' ' test_expect_success 'set up whitespace tests' '
git reset --hard && git reset --hard &&
cat <<\EOF >lines.txt && # Note that these lines have no leading or trailing whitespace.
cat <<-\EOF >lines.txt &&
line 1 line 1
line 2 line 2
line 3 line 3
line 4 line 4
long line 5 line 5
long line 6 long line 6
long line 7 long line 7
long line 8
long line 9
EOF EOF
git add lines.txt && git add lines.txt &&
git commit -m "add poetry" && git commit -m "add poetry" &&
cat <<\EOF >lines.txt && git config color.diff.oldMoved "magenta" &&
long line 5 git config color.diff.newMoved "cyan"
long line 6 '
long line 7
test_expect_success 'move detection ignoring whitespace ' '
q_to_tab <<-\EOF >lines.txt &&
Qlong line 6
Qlong line 7
Qlong line 8
Qchanged long line 9
line 1 line 1
line 2 line 2
line 3 line 3
line 4 line 4
line 5
EOF EOF
test_config color.diff.oldMoved "magenta" &&
test_config color.diff.newMoved "cyan" &&
git diff HEAD --no-renames --color-moved --color | git diff HEAD --no-renames --color-moved --color |
grep -v "index" | grep -v "index" |
test_decode_color >actual && test_decode_color >actual &&
@ -1349,17 +1357,20 @@ EOF
<BOLD>diff --git a/lines.txt b/lines.txt<RESET> <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
<BOLD>--- a/lines.txt<RESET> <BOLD>--- a/lines.txt<RESET>
<BOLD>+++ b/lines.txt<RESET> <BOLD>+++ b/lines.txt<RESET>
<CYAN>@@ -1,7 +1,7 @@<RESET> <CYAN>@@ -1,9 +1,9 @@<RESET>
<GREEN>+<RESET> <GREEN>long line 5<RESET>
<GREEN>+<RESET> <GREEN>long line 6<RESET> <GREEN>+<RESET> <GREEN>long line 6<RESET>
<GREEN>+<RESET> <GREEN>long line 7<RESET> <GREEN>+<RESET> <GREEN>long line 7<RESET>
<GREEN>+<RESET> <GREEN>long line 8<RESET>
<GREEN>+<RESET> <GREEN>changed long line 9<RESET>
line 1<RESET> line 1<RESET>
line 2<RESET> line 2<RESET>
line 3<RESET> line 3<RESET>
line 4<RESET> line 4<RESET>
<RED>-long line 5<RESET> line 5<RESET>
<RED>-long line 6<RESET> <RED>-long line 6<RESET>
<RED>-long line 7<RESET> <RED>-long line 7<RESET>
<RED>-long line 8<RESET>
<RED>-long line 9<RESET>
EOF EOF
test_cmp expected actual && test_cmp expected actual &&
@ -1370,21 +1381,160 @@ EOF
<BOLD>diff --git a/lines.txt b/lines.txt<RESET> <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
<BOLD>--- a/lines.txt<RESET> <BOLD>--- a/lines.txt<RESET>
<BOLD>+++ b/lines.txt<RESET> <BOLD>+++ b/lines.txt<RESET>
<CYAN>@@ -1,7 +1,7 @@<RESET> <CYAN>@@ -1,9 +1,9 @@<RESET>
<CYAN>+<RESET> <CYAN>long line 5<RESET>
<CYAN>+<RESET> <CYAN>long line 6<RESET> <CYAN>+<RESET> <CYAN>long line 6<RESET>
<CYAN>+<RESET> <CYAN>long line 7<RESET> <CYAN>+<RESET> <CYAN>long line 7<RESET>
<CYAN>+<RESET> <CYAN>long line 8<RESET>
<GREEN>+<RESET> <GREEN>changed long line 9<RESET>
line 1<RESET> line 1<RESET>
line 2<RESET> line 2<RESET>
line 3<RESET> line 3<RESET>
line 4<RESET> line 4<RESET>
<MAGENTA>-long line 5<RESET> line 5<RESET>
<MAGENTA>-long line 6<RESET> <MAGENTA>-long line 6<RESET>
<MAGENTA>-long line 7<RESET> <MAGENTA>-long line 7<RESET>
<MAGENTA>-long line 8<RESET>
<RED>-long line 9<RESET>
EOF EOF
test_cmp expected actual test_cmp expected actual
' '
test_expect_success 'move detection ignoring whitespace changes' '
git reset --hard &&
# Lines 6-8 have a space change, but 9 is new whitespace
q_to_tab <<-\EOF >lines.txt &&
longQline 6
longQline 7
longQline 8
long liQne 9
line 1
line 2
line 3
line 4
line 5
EOF
git diff HEAD --no-renames --color-moved --color |
grep -v "index" |
test_decode_color >actual &&
cat <<-\EOF >expected &&
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
<BOLD>--- a/lines.txt<RESET>
<BOLD>+++ b/lines.txt<RESET>
<CYAN>@@ -1,9 +1,9 @@<RESET>
<GREEN>+<RESET><GREEN>long line 6<RESET>
<GREEN>+<RESET><GREEN>long line 7<RESET>
<GREEN>+<RESET><GREEN>long line 8<RESET>
<GREEN>+<RESET><GREEN>long li ne 9<RESET>
line 1<RESET>
line 2<RESET>
line 3<RESET>
line 4<RESET>
line 5<RESET>
<RED>-long line 6<RESET>
<RED>-long line 7<RESET>
<RED>-long line 8<RESET>
<RED>-long line 9<RESET>
EOF
test_cmp expected actual &&
git diff HEAD --no-renames -b --color-moved --color |
grep -v "index" |
test_decode_color >actual &&
cat <<-\EOF >expected &&
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
<BOLD>--- a/lines.txt<RESET>
<BOLD>+++ b/lines.txt<RESET>
<CYAN>@@ -1,9 +1,9 @@<RESET>
<CYAN>+<RESET><CYAN>long line 6<RESET>
<CYAN>+<RESET><CYAN>long line 7<RESET>
<CYAN>+<RESET><CYAN>long line 8<RESET>
<GREEN>+<RESET><GREEN>long li ne 9<RESET>
line 1<RESET>
line 2<RESET>
line 3<RESET>
line 4<RESET>
line 5<RESET>
<MAGENTA>-long line 6<RESET>
<MAGENTA>-long line 7<RESET>
<MAGENTA>-long line 8<RESET>
<RED>-long line 9<RESET>
EOF
test_cmp expected actual
'
test_expect_success 'move detection ignoring whitespace at eol' '
git reset --hard &&
# Lines 6-9 have new eol whitespace, but 9 also has it in the middle
q_to_tab <<-\EOF >lines.txt &&
long line 6Q
long line 7Q
long line 8Q
longQline 9Q
line 1
line 2
line 3
line 4
line 5
EOF
# avoid cluttering the output with complaints about our eol whitespace
test_config core.whitespace -blank-at-eol &&
git diff HEAD --no-renames --color-moved --color |
grep -v "index" |
test_decode_color >actual &&
cat <<-\EOF >expected &&
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
<BOLD>--- a/lines.txt<RESET>
<BOLD>+++ b/lines.txt<RESET>
<CYAN>@@ -1,9 +1,9 @@<RESET>
<GREEN>+<RESET><GREEN>long line 6 <RESET>
<GREEN>+<RESET><GREEN>long line 7 <RESET>
<GREEN>+<RESET><GREEN>long line 8 <RESET>
<GREEN>+<RESET><GREEN>long line 9 <RESET>
line 1<RESET>
line 2<RESET>
line 3<RESET>
line 4<RESET>
line 5<RESET>
<RED>-long line 6<RESET>
<RED>-long line 7<RESET>
<RED>-long line 8<RESET>
<RED>-long line 9<RESET>
EOF
test_cmp expected actual &&
git diff HEAD --no-renames --ignore-space-at-eol --color-moved --color |
grep -v "index" |
test_decode_color >actual &&
cat <<-\EOF >expected &&
<BOLD>diff --git a/lines.txt b/lines.txt<RESET>
<BOLD>--- a/lines.txt<RESET>
<BOLD>+++ b/lines.txt<RESET>
<CYAN>@@ -1,9 +1,9 @@<RESET>
<CYAN>+<RESET><CYAN>long line 6 <RESET>
<CYAN>+<RESET><CYAN>long line 7 <RESET>
<CYAN>+<RESET><CYAN>long line 8 <RESET>
<GREEN>+<RESET><GREEN>long line 9 <RESET>
line 1<RESET>
line 2<RESET>
line 3<RESET>
line 4<RESET>
line 5<RESET>
<MAGENTA>-long line 6<RESET>
<MAGENTA>-long line 7<RESET>
<MAGENTA>-long line 8<RESET>
<RED>-long line 9<RESET>
EOF
test_cmp expected actual
'
test_expect_success 'clean up whitespace-test colors' '
git config --unset color.diff.oldMoved &&
git config --unset color.diff.newMoved
'
test_expect_success '--color-moved block at end of diff output respects MIN_ALNUM_COUNT' ' test_expect_success '--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
git reset --hard && git reset --hard &&
>bar && >bar &&
@ -1530,13 +1680,4 @@ test_expect_success 'move detection with submodules' '
test_cmp expect decoded_actual test_cmp expect decoded_actual
' '
test_expect_success 'move detection with whitespace changes' '
test_when_finished "git reset --hard" &&
test_seq 10 >test &&
git add test &&
sed s/3/42/ <test >test.tmp &&
mv test.tmp test &&
git -c diff.colormoved diff --ignore-space-change -- test
'
test_done test_done