From d55ef3e04459a5f1a24f494b873d8590f2523add Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 26 May 2015 11:19:52 -0700 Subject: t4015: modernise style Move the preparatory steps that create the expected output inside the test bodies, remove unnecessary blank lines before and after the test bodies, and drop SP between redirection operator and its target. Signed-off-by: Junio C Hamano --- t/t4015-diff-whitespace.sh | 411 +++++++++++++++++++-------------------------- 1 file changed, 173 insertions(+), 238 deletions(-) diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 604a838c1a..0bfc7ffac8 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -9,138 +9,144 @@ test_description='Test special whitespace in diff engine. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -# Ray Lehtiniemi's example +test_expect_success "Ray Lehtiniemi's example" ' + cat <<-\EOF >x && + do { + nothing; + } while (0); + EOF + git update-index --add x && -cat << EOF > x -do { - nothing; -} while (0); -EOF + cat <<-\EOF >x && + do + { + nothing; + } + while (0); + EOF -git update-index --add x + cat <<-\EOF >expect && + diff --git a/x b/x + index adf3937..6edc172 100644 + --- a/x + +++ b/x + @@ -1,3 +1,5 @@ + -do { + +do + +{ + nothing; + -} while (0); + +} + +while (0); + EOF -cat << EOF > x -do -{ - nothing; -} -while (0); -EOF + git diff >out && + test_cmp expect out && -cat << EOF > expect -diff --git a/x b/x -index adf3937..6edc172 100644 ---- a/x -+++ b/x -@@ -1,3 +1,5 @@ --do { -+do -+{ - nothing; --} while (0); -+} -+while (0); -EOF + git diff -w >out && + test_cmp expect out && -git diff > out -test_expect_success "Ray's example without options" 'test_cmp expect out' + git diff -b >out && + test_cmp expect out +' -git diff -w > out -test_expect_success "Ray's example with -w" 'test_cmp expect out' +test_expect_success 'another test, without options' ' + tr Q "\015" <<-\EOF >x && + whitespace at beginning + whitespace change + whitespace in the middle + whitespace at end + unchanged line + CR at endQ + EOF -git diff -b > out -test_expect_success "Ray's example with -b" 'test_cmp expect out' + git update-index x && -tr 'Q' '\015' << EOF > x -whitespace at beginning -whitespace change -whitespace in the middle -whitespace at end -unchanged line -CR at endQ -EOF + tr "_" " " <<-\EOF >x && + _ whitespace at beginning + whitespace change + white space in the middle + whitespace at end__ + unchanged line + CR at end + EOF -git update-index x + tr "Q_" "\015 " <<-\EOF >expect && + diff --git a/x b/x + index d99af23..22d9f73 100644 + --- a/x + +++ b/x + @@ -1,6 +1,6 @@ + -whitespace at beginning + -whitespace change + -whitespace in the middle + -whitespace at end + + whitespace at beginning + +whitespace change + +white space in the middle + +whitespace at end__ + unchanged line + -CR at endQ + +CR at end + EOF -tr '_' ' ' << EOF > x - whitespace at beginning -whitespace change -white space in the middle -whitespace at end__ -unchanged line -CR at end -EOF + git diff >out && + test_cmp expect out && -tr 'Q_' '\015 ' << EOF > expect -diff --git a/x b/x -index d99af23..8b32fb5 100644 ---- a/x -+++ b/x -@@ -1,6 +1,6 @@ --whitespace at beginning --whitespace change --whitespace in the middle --whitespace at end -+ whitespace at beginning -+whitespace change -+white space in the middle -+whitespace at end__ - unchanged line --CR at endQ -+CR at end -EOF -git diff > out -test_expect_success 'another test, without options' 'test_cmp expect out' + >expect && + git diff -w >out && + test_cmp expect out && + + git diff -w -b >out && + test_cmp expect out && + + git diff -w --ignore-space-at-eol >out && + test_cmp expect out && + + git diff -w -b --ignore-space-at-eol >out && + test_cmp expect out && -cat << EOF > expect -EOF -git diff -w > out -test_expect_success 'another test, with -w' 'test_cmp expect out' -git diff -w -b > out -test_expect_success 'another test, with -w -b' 'test_cmp expect out' -git diff -w --ignore-space-at-eol > out -test_expect_success 'another test, with -w --ignore-space-at-eol' 'test_cmp expect out' -git diff -w -b --ignore-space-at-eol > out -test_expect_success 'another test, with -w -b --ignore-space-at-eol' 'test_cmp expect out' - -tr 'Q_' '\015 ' << EOF > expect -diff --git a/x b/x -index d99af23..8b32fb5 100644 ---- a/x -+++ b/x -@@ -1,6 +1,6 @@ --whitespace at beginning -+ whitespace at beginning - whitespace change --whitespace in the middle -+white space in the middle - whitespace at end__ - unchanged line - CR at end -EOF -git diff -b > out -test_expect_success 'another test, with -b' 'test_cmp expect out' -git diff -b --ignore-space-at-eol > out -test_expect_success 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out' - -tr 'Q_' '\015 ' << EOF > expect -diff --git a/x b/x -index d99af23..8b32fb5 100644 ---- a/x -+++ b/x -@@ -1,6 +1,6 @@ --whitespace at beginning --whitespace change --whitespace in the middle -+ whitespace at beginning -+whitespace change -+white space in the middle - whitespace at end__ - unchanged line - CR at end -EOF -git diff --ignore-space-at-eol > out -test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out' + + tr "Q_" "\015 " <<-\EOF >expect && + diff --git a/x b/x + index d99af23..22d9f73 100644 + --- a/x + +++ b/x + @@ -1,6 +1,6 @@ + -whitespace at beginning + +_ whitespace at beginning + whitespace change + -whitespace in the middle + +white space in the middle + whitespace at end__ + unchanged line + CR at end + EOF + git diff -b >out && + test_cmp expect out && + + git diff -b --ignore-space-at-eol >out && + test_cmp expect out && + + tr "Q_" "\015 " <<-\EOF >expect && + diff --git a/x b/x + index d99af23..22d9f73 100644 + --- a/x + +++ b/x + @@ -1,6 +1,6 @@ + -whitespace at beginning + -whitespace change + -whitespace in the middle + +_ whitespace at beginning + +whitespace change + +white space in the middle + whitespace at end__ + unchanged line + CR at end + EOF + git diff --ignore-space-at-eol >out && + test_cmp expect out +' test_expect_success 'ignore-blank-lines: only new lines' ' test_seq 5 >x && @@ -489,291 +495,219 @@ test_expect_success 'ignore-blank-lines: mix changes and blank lines' ' ' test_expect_success 'check mixed spaces and tabs in indent' ' - # This is indented with SP HT SP. - echo " foo();" > x && + echo " foo();" >x && git diff --check | grep "space before tab in indent" - ' test_expect_success 'check mixed tabs and spaces in indent' ' - # This is indented with HT SP HT. - echo " foo();" > x && + echo " foo();" >x && git diff --check | grep "space before tab in indent" - ' test_expect_success 'check with no whitespace errors' ' - git commit -m "snapshot" && - echo "foo();" > x && + echo "foo();" >x && git diff --check - ' test_expect_success 'check with trailing whitespace' ' - - echo "foo(); " > x && + echo "foo(); " >x && test_must_fail git diff --check - ' test_expect_success 'check with space before tab in indent' ' - # indent has space followed by hard tab - echo " foo();" > x && + echo " foo();" >x && test_must_fail git diff --check - ' test_expect_success '--check and --exit-code are not exclusive' ' - git checkout x && git diff --check --exit-code - ' test_expect_success '--check and --quiet are not exclusive' ' - git diff --check --quiet - ' test_expect_success 'check staged with no whitespace errors' ' - - echo "foo();" > x && + echo "foo();" >x && git add x && git diff --cached --check - ' test_expect_success 'check staged with trailing whitespace' ' - - echo "foo(); " > x && + echo "foo(); " >x && git add x && test_must_fail git diff --cached --check - ' test_expect_success 'check staged with space before tab in indent' ' - # indent has space followed by hard tab - echo " foo();" > x && + echo " foo();" >x && git add x && test_must_fail git diff --cached --check - ' test_expect_success 'check with no whitespace errors (diff-index)' ' - - echo "foo();" > x && + echo "foo();" >x && git add x && git diff-index --check HEAD - ' test_expect_success 'check with trailing whitespace (diff-index)' ' - - echo "foo(); " > x && + echo "foo(); " >x && git add x && test_must_fail git diff-index --check HEAD - ' test_expect_success 'check with space before tab in indent (diff-index)' ' - # indent has space followed by hard tab - echo " foo();" > x && + echo " foo();" >x && git add x && test_must_fail git diff-index --check HEAD - ' test_expect_success 'check staged with no whitespace errors (diff-index)' ' - - echo "foo();" > x && + echo "foo();" >x && git add x && git diff-index --cached --check HEAD - ' test_expect_success 'check staged with trailing whitespace (diff-index)' ' - - echo "foo(); " > x && + echo "foo(); " >x && git add x && test_must_fail git diff-index --cached --check HEAD - ' test_expect_success 'check staged with space before tab in indent (diff-index)' ' - # indent has space followed by hard tab - echo " foo();" > x && + echo " foo();" >x && git add x && test_must_fail git diff-index --cached --check HEAD - ' test_expect_success 'check with no whitespace errors (diff-tree)' ' - - echo "foo();" > x && + echo "foo();" >x && git commit -m "new commit" x && git diff-tree --check HEAD^ HEAD - ' test_expect_success 'check with trailing whitespace (diff-tree)' ' - - echo "foo(); " > x && + echo "foo(); " >x && git commit -m "another commit" x && test_must_fail git diff-tree --check HEAD^ HEAD - ' test_expect_success 'check with space before tab in indent (diff-tree)' ' - # indent has space followed by hard tab - echo " foo();" > x && + echo " foo();" >x && git commit -m "yet another" x && test_must_fail git diff-tree --check HEAD^ HEAD - ' test_expect_success 'check trailing whitespace (trailing-space: off)' ' - git config core.whitespace "-trailing-space" && - echo "foo (); " > x && + echo "foo (); " >x && git diff --check - ' test_expect_success 'check trailing whitespace (trailing-space: on)' ' - git config core.whitespace "trailing-space" && - echo "foo (); " > x && + echo "foo (); " >x && test_must_fail git diff --check - ' test_expect_success 'check space before tab in indent (space-before-tab: off)' ' - # indent contains space followed by HT git config core.whitespace "-space-before-tab" && - echo " foo ();" > x && + echo " foo ();" >x && git diff --check - ' test_expect_success 'check space before tab in indent (space-before-tab: on)' ' - # indent contains space followed by HT git config core.whitespace "space-before-tab" && - echo " foo (); " > x && + echo " foo (); " >x && test_must_fail git diff --check - ' test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' ' - git config core.whitespace "-indent-with-non-tab" && - echo " foo ();" > x && + echo " foo ();" >x && git diff --check - ' test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' ' - git config core.whitespace "indent-with-non-tab" && - echo " foo ();" > x && + echo " foo ();" >x && test_must_fail git diff --check - ' test_expect_success 'ditto, but tabwidth=9' ' - git config core.whitespace "indent-with-non-tab,tabwidth=9" && git diff --check - ' test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' ' - git config core.whitespace "indent-with-non-tab" && - echo " foo ();" > x && + echo " foo ();" >x && test_must_fail git diff --check - ' test_expect_success 'ditto, but tabwidth=10' ' - git config core.whitespace "indent-with-non-tab,tabwidth=10" && test_must_fail git diff --check - ' test_expect_success 'ditto, but tabwidth=20' ' - git config core.whitespace "indent-with-non-tab,tabwidth=20" && git diff --check - ' test_expect_success 'check tabs as indentation (tab-in-indent: off)' ' - git config core.whitespace "-tab-in-indent" && - echo " foo ();" > x && + echo " foo ();" >x && git diff --check - ' test_expect_success 'check tabs as indentation (tab-in-indent: on)' ' - git config core.whitespace "tab-in-indent" && - echo " foo ();" > x && + echo " foo ();" >x && test_must_fail git diff --check - ' test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' ' - git config core.whitespace "tab-in-indent" && - echo " foo ();" > x && + echo " foo ();" >x && test_must_fail git diff --check - ' test_expect_success 'ditto, but tabwidth=1 (must be irrelevant)' ' - git config core.whitespace "tab-in-indent,tabwidth=1" && test_must_fail git diff --check - ' test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' ' - git config core.whitespace "tab-in-indent,indent-with-non-tab" && - echo "foo ();" > x && + echo "foo ();" >x && test_must_fail git diff --check - ' test_expect_success 'check tab-in-indent excluded from wildcard whitespace attribute' ' - git config --unset core.whitespace && - echo "x whitespace" > .gitattributes && - echo " foo ();" > x && + echo "x whitespace" >.gitattributes && + echo " foo ();" >x && git diff --check && rm -f .gitattributes - ' test_expect_success 'line numbers in --check output are correct' ' - - echo "" > x && - echo "foo(); " >> x && + echo "" >x && + echo "foo(); " >>x && git diff --check | grep "x:2:" - ' test_expect_success 'checkdiff detects new trailing blank lines (1)' ' @@ -878,26 +812,27 @@ test_expect_success 'setup diff colors' ' git config color.diff.commit yellow && git config color.diff.whitespace "normal red" && - git config core.autocrlf false + git config core.autocrlf false && + + cat >expected <<-\EOF + diff --git a/x b/x + index 9daeafb..2874b91 100644 + --- a/x + +++ b/x + @@ -1 +1,4 @@ + test + +{ + + + +} + EOF ' -cat >expected <<\EOF -diff --git a/x b/x -index 9daeafb..2874b91 100644 ---- a/x -+++ b/x -@@ -1 +1,4 @@ - test -+{ -+ -+} -EOF test_expect_success 'diff that introduces a line with only tabs' ' git config core.whitespace blank-at-eol && git reset --hard && - echo "test" > x && + echo "test" >x && git commit -m "initial" x && - echo "{NTN}" | tr "NT" "\n\t" >> x && + echo "{NTN}" | tr "NT" "\n\t" >>x && git -c color.diff=always diff | test_decode_color >current && test_cmp expected current ' -- cgit v1.2.1 From 0ad782f2406fa13f626653a001b5f01a9f3fa40f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 26 May 2015 11:43:08 -0700 Subject: t4015: separate common setup and per-test expectation The last two tests in the script were to - set up color.diff.* slots - set up an expectation for a single test - run that test and check the result but split in a wrong way. It did the first two in the first test and the third one in the second test. The latter two belong to each other. This matters when you plan to add more of these tests that share the common coloring. While at it, make sure we use a color different from old, which is also red. Signed-off-by: Junio C Hamano --- t/t4015-diff-whitespace.sh | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 0bfc7ffac8..4da30e5a1e 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -810,11 +810,20 @@ test_expect_success 'setup diff colors' ' git config color.diff.old red && git config color.diff.new green && git config color.diff.commit yellow && - git config color.diff.whitespace "normal red" && + git config color.diff.whitespace blue && - git config core.autocrlf false && + git config core.autocrlf false +' + +test_expect_success 'diff that introduces a line with only tabs' ' + git config core.whitespace blank-at-eol && + git reset --hard && + echo "test" >x && + git commit -m "initial" x && + echo "{NTN}" | tr "NT" "\n\t" >>x && + git -c color.diff=always diff | test_decode_color >current && - cat >expected <<-\EOF + cat >expected <<-\EOF && diff --git a/x b/x index 9daeafb..2874b91 100644 --- a/x @@ -822,18 +831,10 @@ test_expect_success 'setup diff colors' ' @@ -1 +1,4 @@ test +{ - + + + +} EOF -' -test_expect_success 'diff that introduces a line with only tabs' ' - git config core.whitespace blank-at-eol && - git reset --hard && - echo "test" >x && - git commit -m "initial" x && - echo "{NTN}" | tr "NT" "\n\t" >>x && - git -c color.diff=always diff | test_decode_color >current && test_cmp expected current ' -- cgit v1.2.1 From 0e383e185ae57a8ee6ba015a43749f6d34fe3c9a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 26 May 2015 09:56:33 -0700 Subject: diff.c: add emit_del_line() and emit_context_line() Traditionally, we only had emit_add_line() helper, which knows how to find and paint whitespace breakages on the given line, because we only care about whitespace breakages introduced in new lines. The context lines and old (i.e. deleted) lines are emitted with a simpler emit_line_0() that paints the entire line in plain or old colors. Identify callers of emit_line_0() that show deleted lines and context lines, have them call new helpers, emit_del_line() and emit_context_line(), so that we can later tweak what is done to these two classes of lines. Signed-off-by: Junio C Hamano --- diff.c | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/diff.c b/diff.c index d1bd534cae..c575c452f1 100644 --- a/diff.c +++ b/diff.c @@ -498,6 +498,24 @@ static void emit_add_line(const char *reset, } } +static void emit_del_line(const char *reset, + struct emit_callback *ecbdata, + const char *line, int len) +{ + const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_OLD); + + emit_line_0(ecbdata->opt, set, reset, '-', line, len); +} + +static void emit_context_line(const char *reset, + struct emit_callback *ecbdata, + const char *line, int len) +{ + const char *set = diff_get_color(ecbdata->color_diff, DIFF_PLAIN); + + emit_line_0(ecbdata->opt, set, reset, ' ', line, len); +} + static void emit_hunk_header(struct emit_callback *ecbdata, const char *line, int len) { @@ -603,7 +621,6 @@ static void emit_rewrite_lines(struct emit_callback *ecb, { const char *endp = NULL; static const char *nneof = " No newline at end of file\n"; - const char *old = diff_get_color(ecb->color_diff, DIFF_FILE_OLD); const char *reset = diff_get_color(ecb->color_diff, DIFF_RESET); while (0 < size) { @@ -613,8 +630,7 @@ static void emit_rewrite_lines(struct emit_callback *ecb, len = endp ? (endp - data + 1) : size; if (prefix != '+') { ecb->lno_in_preimage++; - emit_line_0(ecb->opt, old, reset, '-', - data, len); + emit_del_line(reset, ecb, data, len); } else { ecb->lno_in_postimage++; emit_add_line(reset, ecb, data, len); @@ -1250,17 +1266,27 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) return; } - if (line[0] != '+') { - const char *color = - diff_get_color(ecbdata->color_diff, - line[0] == '-' ? DIFF_FILE_OLD : DIFF_PLAIN); - ecbdata->lno_in_preimage++; - if (line[0] == ' ') - ecbdata->lno_in_postimage++; - emit_line(ecbdata->opt, color, reset, line, len); - } else { + switch (line[0]) { + case '+': ecbdata->lno_in_postimage++; emit_add_line(reset, ecbdata, line + 1, len - 1); + break; + case '-': + ecbdata->lno_in_preimage++; + emit_del_line(reset, ecbdata, line + 1, len - 1); + break; + case ' ': + ecbdata->lno_in_postimage++; + ecbdata->lno_in_preimage++; + emit_context_line(reset, ecbdata, line + 1, len - 1); + break; + default: + /* incomplete line at the end */ + ecbdata->lno_in_preimage++; + emit_line(ecbdata->opt, + diff_get_color(ecbdata->color_diff, DIFF_PLAIN), + reset, line, len); + break; } } -- cgit v1.2.1 From b8767f791c15f119554c1466af60e4f2433ae971 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 26 May 2015 10:11:28 -0700 Subject: diff.c: --ws-error-highlight= option Traditionally, we only cared about whitespace breakages introduced in new lines. Some people want to paint whitespace breakages on old lines, too. When they see a whitespace breakage on a new line, they can spot the same kind of whitespace breakage on the corresponding old line and want to say "Ah, those breakages are there but they were inherited from the original, so let's not touch them for now." Introduce `--ws-error-highlight=` option, that lets them pass a comma separated list of `old`, `new`, and `context` to specify what lines to highlight whitespace errors on. Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 10 +++++ diff.c | 84 +++++++++++++++++++++++++++++------- diff.h | 5 +++ t/t4015-diff-whitespace.sh | 96 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 16 deletions(-) diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 6cb083aae5..85a6547774 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -278,6 +278,16 @@ ifndef::git-format-patch[] initial indent of the line are considered whitespace errors. Exits with non-zero status if problems are found. Not compatible with --exit-code. + +--ws-error-highlight=:: + Highlight whitespace errors on lines specified by + in the color specified by `color.diff.whitespace`. + is a comma separated list of `old`, `new`, `context`. When + this option is not given, only whitespace errors in `new` + lines are highlighted. E.g. `--ws-error-highlight=new,old` + highlights whitespace errors on both deleted and added lines. + `all` can be used as a short-hand for `old,new,context`. + endif::git-format-patch[] --full-index:: diff --git a/diff.c b/diff.c index c575c452f1..34012b4b63 100644 --- a/diff.c +++ b/diff.c @@ -478,42 +478,57 @@ static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line return ws_blank_line(line, len, ecbdata->ws_rule); } -static void emit_add_line(const char *reset, - struct emit_callback *ecbdata, - const char *line, int len) +static void emit_line_checked(const char *reset, + struct emit_callback *ecbdata, + const char *line, int len, + enum color_diff color, + unsigned ws_error_highlight, + char sign) { - const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE); - const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW); + const char *set = diff_get_color(ecbdata->color_diff, color); + const char *ws = NULL; - if (!*ws) - emit_line_0(ecbdata->opt, set, reset, '+', line, len); - else if (new_blank_line_at_eof(ecbdata, line, len)) + if (ecbdata->opt->ws_error_highlight & ws_error_highlight) { + ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE); + if (!*ws) + ws = NULL; + } + + if (!ws) + emit_line_0(ecbdata->opt, set, reset, sign, line, len); + else if (sign == '+' && new_blank_line_at_eof(ecbdata, line, len)) /* Blank line at EOF - paint '+' as well */ - emit_line_0(ecbdata->opt, ws, reset, '+', line, len); + emit_line_0(ecbdata->opt, ws, reset, sign, line, len); else { /* Emit just the prefix, then the rest. */ - emit_line_0(ecbdata->opt, set, reset, '+', "", 0); + emit_line_0(ecbdata->opt, set, reset, sign, "", 0); ws_check_emit(line, len, ecbdata->ws_rule, ecbdata->opt->file, set, reset, ws); } } -static void emit_del_line(const char *reset, +static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len) { - const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_OLD); + emit_line_checked(reset, ecbdata, line, len, + DIFF_FILE_NEW, WSEH_NEW, '+'); +} - emit_line_0(ecbdata->opt, set, reset, '-', line, len); +static void emit_del_line(const char *reset, + struct emit_callback *ecbdata, + const char *line, int len) +{ + emit_line_checked(reset, ecbdata, line, len, + DIFF_FILE_OLD, WSEH_OLD, '-'); } static void emit_context_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len) { - const char *set = diff_get_color(ecbdata->color_diff, DIFF_PLAIN); - - emit_line_0(ecbdata->opt, set, reset, ' ', line, len); + emit_line_checked(reset, ecbdata, line, len, + DIFF_PLAIN, WSEH_CONTEXT, ' '); } static void emit_hunk_header(struct emit_callback *ecbdata, @@ -3250,6 +3265,7 @@ void diff_setup(struct diff_options *options) options->rename_limit = -1; options->dirstat_permille = diff_dirstat_permille_default; options->context = diff_context_default; + options->ws_error_highlight = WSEH_NEW; DIFF_OPT_SET(options, RENAME_EMPTY); /* pathchange left =NULL by default */ @@ -3636,6 +3652,40 @@ static void enable_patch_output(int *fmt) { *fmt |= DIFF_FORMAT_PATCH; } +static int parse_one_token(const char **arg, const char *token) +{ + return skip_prefix(*arg, token, arg) && (!**arg || **arg == ','); +} + +static int parse_ws_error_highlight(struct diff_options *opt, const char *arg) +{ + const char *orig_arg = arg; + unsigned val = 0; + while (*arg) { + if (parse_one_token(&arg, "none")) + val = 0; + else if (parse_one_token(&arg, "default")) + val = WSEH_NEW; + else if (parse_one_token(&arg, "all")) + val = WSEH_NEW | WSEH_OLD | WSEH_CONTEXT; + else if (parse_one_token(&arg, "new")) + val |= WSEH_NEW; + else if (parse_one_token(&arg, "old")) + val |= WSEH_OLD; + else if (parse_one_token(&arg, "context")) + val |= WSEH_CONTEXT; + else { + error("unknown value after ws-error-highlight=%.*s", + (int)(arg - orig_arg), orig_arg); + return 0; + } + if (*arg) + arg++; + } + opt->ws_error_highlight = val; + return 1; +} + int diff_opt_parse(struct diff_options *options, const char **av, int ac) { const char *arg = av[0]; @@ -3833,6 +3883,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, SUBMODULE_LOG); else if (skip_prefix(arg, "--submodule=", &arg)) return parse_submodule_opt(options, arg); + else if (skip_prefix(arg, "--ws-error-highlight=", &arg)) + return parse_ws_error_highlight(options, arg); /* misc options */ else if (!strcmp(arg, "-z")) diff --git a/diff.h b/diff.h index b4a624d235..90c7cd61f5 100644 --- a/diff.h +++ b/diff.h @@ -137,6 +137,11 @@ struct diff_options { int dirstat_permille; int setup; int abbrev; +/* white-space error highlighting */ +#define WSEH_NEW 1 +#define WSEH_CONTEXT 2 +#define WSEH_OLD 4 + unsigned ws_error_highlight; const char *prefix; int prefix_length; const char *stat_sep; diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 4da30e5a1e..2434157aa7 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -838,4 +838,100 @@ test_expect_success 'diff that introduces a line with only tabs' ' test_cmp expected current ' +test_expect_success 'diff that introduces and removes ws breakages' ' + git reset --hard && + { + echo "0. blank-at-eol " && + echo "1. blank-at-eol " + } >x && + git commit -a --allow-empty -m preimage && + { + echo "0. blank-at-eol " && + echo "1. still-blank-at-eol " && + echo "2. and a new line " + } >x && + + git -c color.diff=always diff | + test_decode_color >current && + + cat >expected <<-\EOF && + diff --git a/x b/x + index d0233a2..700886e 100644 + --- a/x + +++ b/x + @@ -1,2 +1,3 @@ + 0. blank-at-eol + -1. blank-at-eol + +1. still-blank-at-eol + +2. and a new line + EOF + + test_cmp expected current +' + +test_expect_success 'the same with --ws-error-highlight' ' + git reset --hard && + { + echo "0. blank-at-eol " && + echo "1. blank-at-eol " + } >x && + git commit -a --allow-empty -m preimage && + { + echo "0. blank-at-eol " && + echo "1. still-blank-at-eol " && + echo "2. and a new line " + } >x && + + git -c color.diff=always diff --ws-error-highlight=default,old | + test_decode_color >current && + + cat >expected <<-\EOF && + diff --git a/x b/x + index d0233a2..700886e 100644 + --- a/x + +++ b/x + @@ -1,2 +1,3 @@ + 0. blank-at-eol + -1. blank-at-eol + +1. still-blank-at-eol + +2. and a new line + EOF + + test_cmp expected current && + + git -c color.diff=always diff --ws-error-highlight=all | + test_decode_color >current && + + cat >expected <<-\EOF && + diff --git a/x b/x + index d0233a2..700886e 100644 + --- a/x + +++ b/x + @@ -1,2 +1,3 @@ + 0. blank-at-eol + -1. blank-at-eol + +1. still-blank-at-eol + +2. and a new line + EOF + + test_cmp expected current && + + git -c color.diff=always diff --ws-error-highlight=none | + test_decode_color >current && + + cat >expected <<-\EOF && + diff --git a/x b/x + index d0233a2..700886e 100644 + --- a/x + +++ b/x + @@ -1,2 +1,3 @@ + 0. blank-at-eol + -1. blank-at-eol + +1. still-blank-at-eol + +2. and a new line + EOF + + test_cmp expected current +' + test_done -- cgit v1.2.1