diff --color-moved-ws: handle blank lines
When using --color-moved-ws=allow-indentation-change allow lines with the same indentation change to be grouped across blank lines. For now this only works if the blank lines have been moved as well, not for blocks that have just had their indentation changed. This completes the changes to the implementation of --color-moved=allow-indentation-change. Running git diff --color-moved=allow-indentation-change v2.18.0 v2.19.0 now takes 5.0s. This is a saving of 41% from 8.5s for the optimized version of the previous implementation and 66% from the original which took 14.6s. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Reviewed-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Phillip Wood committed
Nov 23, 2018 at 11:16 UTC
0cd51e9d05e65608126c30fbb65a0cdd197cd570
2 files changed
+68
-7
diff.c
+31
-3
@@ -794,9 +794,11 @@ static void moved_block_clear(struct moved_block *b)
794
memset(b, 0, sizeof(*b));
795
}
796
797
+#define INDENT_BLANKLINE INT_MIN
798
+
799
static void fill_es_indent_data(struct emitted_diff_symbol *es)
800
{
799
- unsigned int off = 0;
801
+ unsigned int off = 0, i;
802
int width = 0, tab_width = es->flags & WS_TAB_WIDTH_MASK;
803
const char *s = es->line;
804
const int len = es->len;
@@ -820,8 +822,18 @@ static void fill_es_indent_data(struct emitted_diff_symbol *es)
822
}
823
}
824
823
- es->indent_off = off;
824
- es->indent_width = width;
825
+ /* check if this line is blank */
826
+ for (i = off; i < len; i++)
827
+ if (!isspace(s[i]))
828
+ break;
829
+
830
+ if (i == len) {
831
+ es->indent_width = INDENT_BLANKLINE;
832
+ es->indent_off = len;
833
+ } else {
834
+ es->indent_off = off;
835
+ es->indent_width = width;
836
+ }
837
}
838
839
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,
848
b_width = b->indent_width;
849
int delta;
850
851
+ if (a_width == INDENT_BLANKLINE && b_width == INDENT_BLANKLINE) {
852
+ *out = INDENT_BLANKLINE;
853
+ return 1;
854
+ }
855
+
856
if (a->s == DIFF_SYMBOL_PLUS)
857
delta = a_width - b_width;
858
else
@@ -879,6 +896,10 @@ static int cmp_in_block_with_wsd(const struct diff_options *o,
896
if (al != bl)
897
return 1;
898
899
+ /* If 'l' and 'cur' are both blank then they match. */
900
+ if (a_width == INDENT_BLANKLINE && c_width == INDENT_BLANKLINE)
901
+ return 0;
902
+
903
/*
904
* The indent changes of the block are known and stored in pmb->wsd;
905
* 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,
911
else
912
delta = c_width - a_width;
913
914
+ /*
915
+ * If the previous lines of this block were all blank then set its
916
+ * whitespace delta.
917
+ */
918
+ if (pmb->wsd == INDENT_BLANKLINE)
919
+ pmb->wsd = delta;
920
+
921
return !(delta == pmb->wsd && al - a_off == cl - c_off &&
922
!memcmp(a, b, al) && !
923
memcmp(a + a_off, c + c_off, al - a_off));
t/t4015-diff-whitespace.sh
+37
-4
@@ -1901,10 +1901,20 @@ test_expect_success 'compare whitespace delta incompatible with other space opti
1901
test_i18ngrep allow-indentation-change err
1902
'
1903
1904
+EMPTY=''
1905
test_expect_success 'compare mixed whitespace delta across moved blocks' '
1906
1907
git reset --hard &&
1908
tr Q_ "\t " <<-EOF >text.txt &&
1909
+ ${EMPTY}
1910
+ ____too short without
1911
+ ${EMPTY}
1912
+ ___being grouped across blank line
1913
+ ${EMPTY}
1914
+ context
1915
+ lines
1916
+ to
1917
+ anchor
1918
____Indented text to
1919
_Q____be further indented by four spaces across
1920
____Qseveral lines
@@ -1918,9 +1928,18 @@ test_expect_success 'compare mixed whitespace delta across moved blocks' '
1928
git commit -m "add text.txt" &&
1929
1930
tr Q_ "\t " <<-EOF >text.txt &&
1931
+ context
1932
+ lines
1933
+ to
1934
+ anchor
1935
QIndented text to
1936
QQbe further indented by four spaces across
1937
Q____several lines
1938
+ ${EMPTY}
1939
+ QQtoo short without
1940
+ ${EMPTY}
1941
+ Q_______being grouped across blank line
1942
+ ${EMPTY}
1943
Q_QThese two lines have had their
1944
indentation reduced by four spaces
1945
QQdifferent indentation change
@@ -1937,7 +1956,16 @@ test_expect_success 'compare mixed whitespace delta across moved blocks' '
1956
<BOLD>diff --git a/text.txt b/text.txt<RESET>
1957
<BOLD>--- a/text.txt<RESET>
1958
<BOLD>+++ b/text.txt<RESET>
1940
- <CYAN>@@ -1,7 +1,7 @@<RESET>
1959
+ <CYAN>@@ -1,16 +1,16 @@<RESET>
1960
+ <BOLD;MAGENTA>-<RESET>
1961
+ <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA> too short without<RESET>
1962
+ <BOLD;MAGENTA>-<RESET>
1963
+ <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA> being grouped across blank line<RESET>
1964
+ <BOLD;MAGENTA>-<RESET>
1965
+ <RESET>context<RESET>
1966
+ <RESET>lines<RESET>
1967
+ <RESET>to<RESET>
1968
+ <RESET>anchor<RESET>
1969
<BOLD;MAGENTA>-<RESET><BOLD;MAGENTA> Indented text to<RESET>
1970
<BOLD;MAGENTA>-<RESET><BRED> <RESET> <BOLD;MAGENTA> be further indented by four spaces across<RESET>
1971
<BOLD;MAGENTA>-<RESET><BRED> <RESET> <BOLD;MAGENTA>several lines<RESET>
@@ -1948,9 +1976,14 @@ test_expect_success 'compare mixed whitespace delta across moved blocks' '
1976
<BOLD;CYAN>+<RESET> <BOLD;CYAN>Indented text to<RESET>
1977
<BOLD;CYAN>+<RESET> <BOLD;CYAN>be further indented by four spaces across<RESET>
1978
<BOLD;CYAN>+<RESET> <BOLD;CYAN> several lines<RESET>
1951
- <BOLD;YELLOW>+<RESET> <BRED> <RESET> <BOLD;YELLOW>These two lines have had their<RESET>
1952
- <BOLD;YELLOW>+<RESET><BOLD;YELLOW>indentation reduced by four spaces<RESET>
1953
- <BOLD;CYAN>+<RESET> <BOLD;CYAN>different indentation change<RESET>
1979
+ <BOLD;YELLOW>+<RESET>
1980
+ <BOLD;YELLOW>+<RESET> <BOLD;YELLOW>too short without<RESET>
1981
+ <BOLD;YELLOW>+<RESET>
1982
+ <BOLD;YELLOW>+<RESET> <BOLD;YELLOW> being grouped across blank line<RESET>
1983
+ <BOLD;YELLOW>+<RESET>
1984
+ <BOLD;CYAN>+<RESET> <BRED> <RESET> <BOLD;CYAN>These two lines have had their<RESET>
1985
+ <BOLD;CYAN>+<RESET><BOLD;CYAN>indentation reduced by four spaces<RESET>
1986
+ <BOLD;YELLOW>+<RESET> <BOLD;YELLOW>different indentation change<RESET>
1987
<GREEN>+<RESET><BRED> <RESET> <GREEN>too short<RESET>
1988
EOF
1989