diff: highlight and error out on incomplete lines
Teach "git diff" to highlight "\ No newline at end of file" message as a whitespace error when incomplete-line whitespace error class is in effect. Thanks to the previous refactoring of complete rewrite code path, we can do this at a single place. Unlike whitespace errors in the payload where we need to annotate in line, possibly using colors, the line that has whitespace problems, we have a dedicated line already that can serve as the error message, so paint it as a whitespace error message. Also teach "git diff --check" to notice incomplete lines as whitespace errors and report when incomplete-line whitespace error class is in effect. Signed-off-by: Junio C Hamano <gitster@pobox.com>main
parent
9fb15a8e14
commit
ab2693cb52
29
diff.c
29
diff.c
|
|
@ -1370,7 +1370,11 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
|
||||||
emit_line(o, "", "", line, len);
|
emit_line(o, "", "", line, len);
|
||||||
break;
|
break;
|
||||||
case DIFF_SYMBOL_CONTEXT_INCOMPLETE:
|
case DIFF_SYMBOL_CONTEXT_INCOMPLETE:
|
||||||
set = diff_get_color_opt(o, DIFF_CONTEXT);
|
if ((flags & WS_INCOMPLETE_LINE) &&
|
||||||
|
(flags & o->ws_error_highlight))
|
||||||
|
set = diff_get_color_opt(o, DIFF_WHITESPACE);
|
||||||
|
else
|
||||||
|
set = diff_get_color_opt(o, DIFF_CONTEXT);
|
||||||
reset = diff_get_color_opt(o, DIFF_RESET);
|
reset = diff_get_color_opt(o, DIFF_RESET);
|
||||||
emit_line(o, set, reset, line, len);
|
emit_line(o, set, reset, line, len);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1666,8 +1670,14 @@ static void emit_context_line(struct emit_callback *ecbdata,
|
||||||
static void emit_incomplete_line_marker(struct emit_callback *ecbdata,
|
static void emit_incomplete_line_marker(struct emit_callback *ecbdata,
|
||||||
const char *line, int len)
|
const char *line, int len)
|
||||||
{
|
{
|
||||||
|
int last_line_kind = ecbdata->last_line_kind;
|
||||||
|
unsigned flags = (last_line_kind == '+'
|
||||||
|
? WSEH_NEW
|
||||||
|
: last_line_kind == '-'
|
||||||
|
? WSEH_OLD
|
||||||
|
: WSEH_CONTEXT) | ecbdata->ws_rule;
|
||||||
emit_diff_symbol(ecbdata->opt, DIFF_SYMBOL_CONTEXT_INCOMPLETE,
|
emit_diff_symbol(ecbdata->opt, DIFF_SYMBOL_CONTEXT_INCOMPLETE,
|
||||||
line, len, 0);
|
line, len, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_hunk_header(struct emit_callback *ecbdata,
|
static void emit_hunk_header(struct emit_callback *ecbdata,
|
||||||
|
|
@ -3254,6 +3264,7 @@ struct checkdiff_t {
|
||||||
struct diff_options *o;
|
struct diff_options *o;
|
||||||
unsigned ws_rule;
|
unsigned ws_rule;
|
||||||
unsigned status;
|
unsigned status;
|
||||||
|
int last_line_kind;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int is_conflict_marker(const char *line, int marker_size, unsigned long len)
|
static int is_conflict_marker(const char *line, int marker_size, unsigned long len)
|
||||||
|
|
@ -3292,6 +3303,7 @@ static void checkdiff_consume_hunk(void *priv,
|
||||||
static int checkdiff_consume(void *priv, char *line, unsigned long len)
|
static int checkdiff_consume(void *priv, char *line, unsigned long len)
|
||||||
{
|
{
|
||||||
struct checkdiff_t *data = priv;
|
struct checkdiff_t *data = priv;
|
||||||
|
int last_line_kind;
|
||||||
int marker_size = data->conflict_marker_size;
|
int marker_size = data->conflict_marker_size;
|
||||||
const char *ws = diff_get_color(data->o->use_color, DIFF_WHITESPACE);
|
const char *ws = diff_get_color(data->o->use_color, DIFF_WHITESPACE);
|
||||||
const char *reset = diff_get_color(data->o->use_color, DIFF_RESET);
|
const char *reset = diff_get_color(data->o->use_color, DIFF_RESET);
|
||||||
|
|
@ -3302,6 +3314,8 @@ static int checkdiff_consume(void *priv, char *line, unsigned long len)
|
||||||
assert(data->o);
|
assert(data->o);
|
||||||
line_prefix = diff_line_prefix(data->o);
|
line_prefix = diff_line_prefix(data->o);
|
||||||
|
|
||||||
|
last_line_kind = data->last_line_kind;
|
||||||
|
data->last_line_kind = line[0];
|
||||||
if (line[0] == '+') {
|
if (line[0] == '+') {
|
||||||
unsigned bad;
|
unsigned bad;
|
||||||
data->lineno++;
|
data->lineno++;
|
||||||
|
|
@ -3324,6 +3338,17 @@ static int checkdiff_consume(void *priv, char *line, unsigned long len)
|
||||||
data->o->file, set, reset, ws);
|
data->o->file, set, reset, ws);
|
||||||
} else if (line[0] == ' ') {
|
} else if (line[0] == ' ') {
|
||||||
data->lineno++;
|
data->lineno++;
|
||||||
|
} else if (line[0] == '\\') {
|
||||||
|
/* no newline at the end of the line */
|
||||||
|
if ((data->ws_rule & WS_INCOMPLETE_LINE) &&
|
||||||
|
(last_line_kind == '+')) {
|
||||||
|
unsigned bad = WS_INCOMPLETE_LINE;
|
||||||
|
data->status |= bad;
|
||||||
|
err = whitespace_error_string(bad);
|
||||||
|
fprintf(data->o->file, "%s%s:%d: %s.\n",
|
||||||
|
line_prefix, data->filename, data->lineno, err);
|
||||||
|
free(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,53 @@ do
|
||||||
'
|
'
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_expect_success "incomplete line in both pre- and post-image context" '
|
||||||
|
(echo foo && echo baz | tr -d "\012") >x &&
|
||||||
|
git add x &&
|
||||||
|
(echo bar && echo baz | tr -d "\012") >x &&
|
||||||
|
git diff x &&
|
||||||
|
git -c core.whitespace=incomplete diff --check x &&
|
||||||
|
git diff -R x &&
|
||||||
|
git -c core.whitespace=incomplete diff -R --check x
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success "incomplete lines on both pre- and post-image" '
|
||||||
|
# The interpretation taken here is "since you are touching
|
||||||
|
# the line anyway, you would better fix the incomplete line
|
||||||
|
# while you are at it." but this is debatable.
|
||||||
|
echo foo | tr -d "\012" >x &&
|
||||||
|
git add x &&
|
||||||
|
echo bar | tr -d "\012" >x &&
|
||||||
|
git diff x &&
|
||||||
|
test_must_fail git -c core.whitespace=incomplete diff --check x >error &&
|
||||||
|
test_grep "no newline at the end of file" error &&
|
||||||
|
git diff -R x &&
|
||||||
|
test_must_fail git -c core.whitespace=incomplete diff -R --check x >error &&
|
||||||
|
test_grep "no newline at the end of file" error
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success "fix incomplete line in pre-image" '
|
||||||
|
echo foo | tr -d "\012" >x &&
|
||||||
|
git add x &&
|
||||||
|
echo bar >x &&
|
||||||
|
git diff x &&
|
||||||
|
git -c core.whitespace=incomplete diff --check x &&
|
||||||
|
git diff -R x &&
|
||||||
|
test_must_fail git -c core.whitespace=incomplete diff -R --check x >error &&
|
||||||
|
test_grep "no newline at the end of file" error
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success "new incomplete line in post-image" '
|
||||||
|
echo foo >x &&
|
||||||
|
git add x &&
|
||||||
|
echo bar | tr -d "\012" >x &&
|
||||||
|
git diff x &&
|
||||||
|
test_must_fail git -c core.whitespace=incomplete diff --check x >error &&
|
||||||
|
test_grep "no newline at the end of file" error &&
|
||||||
|
git diff -R x &&
|
||||||
|
git -c core.whitespace=incomplete diff -R --check x
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success "Ray Lehtiniemi's example" '
|
test_expect_success "Ray Lehtiniemi's example" '
|
||||||
cat <<-\EOF >x &&
|
cat <<-\EOF >x &&
|
||||||
do {
|
do {
|
||||||
|
|
@ -1040,7 +1087,8 @@ test_expect_success 'ws-error-highlight test setup' '
|
||||||
{
|
{
|
||||||
echo "0. blank-at-eol " &&
|
echo "0. blank-at-eol " &&
|
||||||
echo "1. still-blank-at-eol " &&
|
echo "1. still-blank-at-eol " &&
|
||||||
echo "2. and a new line "
|
echo "2. and a new line " &&
|
||||||
|
printf "3. and more"
|
||||||
} >x &&
|
} >x &&
|
||||||
new_hash_x=$(git hash-object x) &&
|
new_hash_x=$(git hash-object x) &&
|
||||||
after=$(git rev-parse --short "$new_hash_x") &&
|
after=$(git rev-parse --short "$new_hash_x") &&
|
||||||
|
|
@ -1050,11 +1098,13 @@ test_expect_success 'ws-error-highlight test setup' '
|
||||||
<BOLD>index $before..$after 100644<RESET>
|
<BOLD>index $before..$after 100644<RESET>
|
||||||
<BOLD>--- a/x<RESET>
|
<BOLD>--- a/x<RESET>
|
||||||
<BOLD>+++ b/x<RESET>
|
<BOLD>+++ b/x<RESET>
|
||||||
<CYAN>@@ -1,2 +1,3 @@<RESET>
|
<CYAN>@@ -1,2 +1,4 @@<RESET>
|
||||||
0. blank-at-eol <RESET>
|
0. blank-at-eol <RESET>
|
||||||
<RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
|
<RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
|
||||||
<GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
|
<GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
|
||||||
<GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
|
<GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
|
||||||
|
<GREEN>+<RESET><GREEN>3. and more<RESET>
|
||||||
|
<BLUE>\ No newline at end of file<RESET>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat >expect.all <<-EOF &&
|
cat >expect.all <<-EOF &&
|
||||||
|
|
@ -1062,11 +1112,13 @@ test_expect_success 'ws-error-highlight test setup' '
|
||||||
<BOLD>index $before..$after 100644<RESET>
|
<BOLD>index $before..$after 100644<RESET>
|
||||||
<BOLD>--- a/x<RESET>
|
<BOLD>--- a/x<RESET>
|
||||||
<BOLD>+++ b/x<RESET>
|
<BOLD>+++ b/x<RESET>
|
||||||
<CYAN>@@ -1,2 +1,3 @@<RESET>
|
<CYAN>@@ -1,2 +1,4 @@<RESET>
|
||||||
<RESET>0. blank-at-eol<RESET><BLUE> <RESET>
|
<RESET>0. blank-at-eol<RESET><BLUE> <RESET>
|
||||||
<RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
|
<RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
|
||||||
<GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
|
<GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
|
||||||
<GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
|
<GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
|
||||||
|
<GREEN>+<RESET><GREEN>3. and more<RESET>
|
||||||
|
<BLUE>\ No newline at end of file<RESET>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat >expect.none <<-EOF
|
cat >expect.none <<-EOF
|
||||||
|
|
@ -1074,16 +1126,19 @@ test_expect_success 'ws-error-highlight test setup' '
|
||||||
<BOLD>index $before..$after 100644<RESET>
|
<BOLD>index $before..$after 100644<RESET>
|
||||||
<BOLD>--- a/x<RESET>
|
<BOLD>--- a/x<RESET>
|
||||||
<BOLD>+++ b/x<RESET>
|
<BOLD>+++ b/x<RESET>
|
||||||
<CYAN>@@ -1,2 +1,3 @@<RESET>
|
<CYAN>@@ -1,2 +1,4 @@<RESET>
|
||||||
0. blank-at-eol <RESET>
|
0. blank-at-eol <RESET>
|
||||||
<RED>-1. blank-at-eol <RESET>
|
<RED>-1. blank-at-eol <RESET>
|
||||||
<GREEN>+1. still-blank-at-eol <RESET>
|
<GREEN>+1. still-blank-at-eol <RESET>
|
||||||
<GREEN>+2. and a new line <RESET>
|
<GREEN>+2. and a new line <RESET>
|
||||||
|
<GREEN>+3. and more<RESET>
|
||||||
|
\ No newline at end of file<RESET>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'test --ws-error-highlight option' '
|
test_expect_success 'test --ws-error-highlight option' '
|
||||||
|
git config core.whitespace blank-at-eol,incomplete-line &&
|
||||||
|
|
||||||
git diff --color --ws-error-highlight=default,old >current.raw &&
|
git diff --color --ws-error-highlight=default,old >current.raw &&
|
||||||
test_decode_color <current.raw >current &&
|
test_decode_color <current.raw >current &&
|
||||||
|
|
@ -1100,6 +1155,7 @@ test_expect_success 'test --ws-error-highlight option' '
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'test diff.wsErrorHighlight config' '
|
test_expect_success 'test diff.wsErrorHighlight config' '
|
||||||
|
git config core.whitespace blank-at-eol,incomplete-line &&
|
||||||
|
|
||||||
git -c diff.wsErrorHighlight=default,old diff --color >current.raw &&
|
git -c diff.wsErrorHighlight=default,old diff --color >current.raw &&
|
||||||
test_decode_color <current.raw >current &&
|
test_decode_color <current.raw >current &&
|
||||||
|
|
@ -1116,6 +1172,7 @@ test_expect_success 'test diff.wsErrorHighlight config' '
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'option overrides diff.wsErrorHighlight' '
|
test_expect_success 'option overrides diff.wsErrorHighlight' '
|
||||||
|
git config core.whitespace blank-at-eol,incomplete-line &&
|
||||||
|
|
||||||
git -c diff.wsErrorHighlight=none \
|
git -c diff.wsErrorHighlight=none \
|
||||||
diff --color --ws-error-highlight=default,old >current.raw &&
|
diff --color --ws-error-highlight=default,old >current.raw &&
|
||||||
|
|
@ -1135,6 +1192,8 @@ test_expect_success 'option overrides diff.wsErrorHighlight' '
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'detect moved code, complete file' '
|
test_expect_success 'detect moved code, complete file' '
|
||||||
|
git config core.whitespace blank-at-eol &&
|
||||||
|
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
cat <<-\EOF >test.c &&
|
cat <<-\EOF >test.c &&
|
||||||
#include<stdio.h>
|
#include<stdio.h>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue