diff --git a/diff.c b/diff.c index 941956d8c4..03ffe467e4 100644 --- a/diff.c +++ b/diff.c @@ -794,9 +794,11 @@ static void moved_block_clear(struct moved_block *b) memset(b, 0, sizeof(*b)); } +#define INDENT_BLANKLINE INT_MIN + static void fill_es_indent_data(struct emitted_diff_symbol *es) { - unsigned int off = 0; + unsigned int off = 0, i; int width = 0, tab_width = es->flags & WS_TAB_WIDTH_MASK; const char *s = es->line; const int len = es->len; @@ -820,8 +822,18 @@ static void fill_es_indent_data(struct emitted_diff_symbol *es) } } - es->indent_off = off; - es->indent_width = width; + /* check if this line is blank */ + for (i = off; i < len; i++) + if (!isspace(s[i])) + break; + + if (i == len) { + es->indent_width = INDENT_BLANKLINE; + es->indent_off = len; + } else { + es->indent_off = off; + es->indent_width = width; + } } static int compute_ws_delta(const struct emitted_diff_symbol *a, @@ -836,6 +848,11 @@ static int compute_ws_delta(const struct emitted_diff_symbol *a, b_width = b->indent_width; int delta; + if (a_width == INDENT_BLANKLINE && b_width == INDENT_BLANKLINE) { + *out = INDENT_BLANKLINE; + return 1; + } + if (a->s == DIFF_SYMBOL_PLUS) delta = a_width - b_width; else @@ -879,6 +896,10 @@ static int cmp_in_block_with_wsd(const struct diff_options *o, if (al != bl) return 1; + /* If 'l' and 'cur' are both blank then they match. */ + if (a_width == INDENT_BLANKLINE && c_width == INDENT_BLANKLINE) + return 0; + /* * The indent changes of the block are known and stored in pmb->wsd; * however we need to check if the indent changes of the current line @@ -890,6 +911,13 @@ static int cmp_in_block_with_wsd(const struct diff_options *o, else delta = c_width - a_width; + /* + * If the previous lines of this block were all blank then set its + * whitespace delta. + */ + if (pmb->wsd == INDENT_BLANKLINE) + pmb->wsd = delta; + return !(delta == pmb->wsd && al - a_off == cl - c_off && !memcmp(a, b, al) && ! memcmp(a + a_off, c + c_off, al - a_off)); diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index e023839ba6..9d6f88b07f 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -1901,10 +1901,20 @@ test_expect_success 'compare whitespace delta incompatible with other space opti test_i18ngrep allow-indentation-change err ' +EMPTY='' test_expect_success 'compare mixed whitespace delta across moved blocks' ' git reset --hard && tr Q_ "\t " <<-EOF >text.txt && + ${EMPTY} + ____too short without + ${EMPTY} + ___being grouped across blank line + ${EMPTY} + context + lines + to + anchor ____Indented text to _Q____be further indented by four spaces across ____Qseveral lines @@ -1918,9 +1928,18 @@ test_expect_success 'compare mixed whitespace delta across moved blocks' ' git commit -m "add text.txt" && tr Q_ "\t " <<-EOF >text.txt && + context + lines + to + anchor QIndented text to QQbe further indented by four spaces across Q____several lines + ${EMPTY} + QQtoo short without + ${EMPTY} + Q_______being grouped across blank line + ${EMPTY} Q_QThese two lines have had their indentation reduced by four spaces QQdifferent indentation change @@ -1937,7 +1956,16 @@ test_expect_success 'compare mixed whitespace delta across moved blocks' ' diff --git a/text.txt b/text.txt --- a/text.txt +++ b/text.txt - @@ -1,7 +1,7 @@ + @@ -1,16 +1,16 @@ + - + - too short without + - + - being grouped across blank line + - + context + lines + to + anchor - Indented text to - be further indented by four spaces across - several lines @@ -1948,9 +1976,14 @@ test_expect_success 'compare mixed whitespace delta across moved blocks' ' + Indented text to + be further indented by four spaces across + several lines - + These two lines have had their - +indentation reduced by four spaces - + different indentation change + + + + too short without + + + + being grouped across blank line + + + + These two lines have had their + +indentation reduced by four spaces + + different indentation change + too short EOF