diff --whitespace: fix blank lines at end
The earlier logic tried to colour any and all blank lines that were added beyond the last blank line in the original, but this was very wrong. If you added 96 blank lines, a non-blank line, and then 3 blank lines at the end, only the last 3 lines should trigger the error, not the earlier 96 blank lines. We need to also make sure that the lines are after the last non-blank line in the postimage as well before deciding to paint them. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Sep 14, 2009 at 22:05 UTC
d68fe26f3e03b230ac9bbbcf002a9acdc4bebde9
2 files changed
+54
-22
diff.c
+53
-21
@@ -491,8 +491,10 @@ struct emit_callback {
491
struct xdiff_emit_state xm;
492
int color_diff;
493
unsigned ws_rule;
494
- int blank_at_eof;
494
+ int blank_at_eof_in_preimage;
495
+ int blank_at_eof_in_postimage;
496
int lno_in_preimage;
497
+ int lno_in_postimage;
498
sane_truncate_fn truncate;
499
const char **label_path;
500
struct diff_words_data *diff_words;
@@ -542,6 +544,17 @@ static void emit_line(FILE *file, const char *set, const char *reset, const char
544
fputc('\n', file);
545
}
546
547
+static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)
548
+{
549
+ if (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
550
+ ecbdata->blank_at_eof_in_preimage &&
551
+ ecbdata->blank_at_eof_in_postimage &&
552
+ ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&
553
+ ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))
554
+ return 0;
555
+ return ws_blank_line(line + 1, len - 1, ecbdata->ws_rule);
556
+}
557
+
558
static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
559
{
560
const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
@@ -549,11 +562,8 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons
562
563
if (!*ws)
564
emit_line(ecbdata->file, set, reset, line, len);
552
- else if ((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
553
- ecbdata->blank_at_eof &&
554
- (ecbdata->blank_at_eof <= ecbdata->lno_in_preimage) &&
555
- ws_blank_line(line + 1, len - 1, ecbdata->ws_rule))
556
- /* Blank line at EOF */
565
+ else if (new_blank_line_at_eof(ecbdata, line, len))
566
+ /* Blank line at EOF - paint '+' as well */
567
emit_line(ecbdata->file, ws, reset, line, len);
568
else {
569
/* Emit just the prefix, then the rest. */
@@ -581,12 +591,19 @@ static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, u
591
return allot - l;
592
}
593
584
-static int find_preimage_lno(const char *line)
594
+static void find_lno(const char *line, struct emit_callback *ecbdata)
595
{
586
- char *p = strchr(line, '-');
596
+ const char *p;
597
+ ecbdata->lno_in_preimage = 0;
598
+ ecbdata->lno_in_postimage = 0;
599
+ p = strchr(line, '-');
600
if (!p)
588
- return 0; /* should not happen */
589
- return strtol(p+1, NULL, 10);
601
+ return; /* cannot happen */
602
+ ecbdata->lno_in_preimage = strtol(p + 1, NULL, 10);
603
+ p = strchr(p, '+');
604
+ if (!p)
605
+ return; /* cannot happen */
606
+ ecbdata->lno_in_postimage = strtol(p + 1, NULL, 10);
607
}
608
609
static void fn_out_consume(void *priv, char *line, unsigned long len)
@@ -613,7 +630,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
630
631
if (line[0] == '@') {
632
len = sane_truncate_line(ecbdata, line, len);
616
- ecbdata->lno_in_preimage = find_preimage_lno(line);
633
+ find_lno(line, ecbdata);
634
emit_line(ecbdata->file,
635
diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO),
636
reset, line, len);
@@ -651,10 +668,13 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
668
diff_get_color(ecbdata->color_diff,
669
line[0] == '-' ? DIFF_FILE_OLD : DIFF_PLAIN);
670
ecbdata->lno_in_preimage++;
671
+ if (line[0] == ' ')
672
+ ecbdata->lno_in_postimage++;
673
emit_line(ecbdata->file, color, reset, line, len);
655
- return;
674
+ } else {
675
+ ecbdata->lno_in_postimage++;
676
+ emit_add_line(reset, ecbdata, line, len);
677
}
657
- emit_add_line(reset, ecbdata, line, len);
678
}
679
680
static char *pprint_rename(const char *a, const char *b)
@@ -1470,16 +1490,23 @@ static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
1490
return cnt;
1491
}
1492
1473
-static int adds_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2, unsigned ws_rule)
1493
+static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
1494
+ struct emit_callback *ecbdata)
1495
{
1496
int l1, l2, at;
1497
+ unsigned ws_rule = ecbdata->ws_rule;
1498
l1 = count_trailing_blank(mf1, ws_rule);
1499
l2 = count_trailing_blank(mf2, ws_rule);
1478
- if (l2 <= l1)
1479
- return 0;
1480
- /* starting where? */
1500
+ if (l2 <= l1) {
1501
+ ecbdata->blank_at_eof_in_preimage = 0;
1502
+ ecbdata->blank_at_eof_in_postimage = 0;
1503
+ return;
1504
+ }
1505
at = count_lines(mf1->ptr, mf1->size);
1482
- return (at - l1) + 1; /* the line number counts from 1 */
1506
+ ecbdata->blank_at_eof_in_preimage = (at - l1) + 1;
1507
+
1508
+ at = count_lines(mf2->ptr, mf2->size);
1509
+ ecbdata->blank_at_eof_in_postimage = (at - l2) + 1;
1510
}
1511
1512
static void builtin_diff(const char *name_a,
@@ -1572,8 +1599,7 @@ static void builtin_diff(const char *name_a,
1599
ecbdata.found_changesp = &o->found_changes;
1600
ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
1601
if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
1575
- ecbdata.blank_at_eof =
1576
- adds_blank_at_eof(&mf1, &mf2, ecbdata.ws_rule);
1602
+ check_blank_at_eof(&mf1, &mf2, &ecbdata);
1603
ecbdata.file = o->file;
1604
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
1605
xecfg.ctxlen = o->context;
@@ -1699,7 +1725,13 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
1725
xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
1726
1727
if (data.ws_rule & WS_BLANK_AT_EOF) {
1702
- int blank_at_eof = adds_blank_at_eof(&mf1, &mf2, data.ws_rule);
1728
+ struct emit_callback ecbdata;
1729
+ int blank_at_eof;
1730
+
1731
+ ecbdata.ws_rule = data.ws_rule;
1732
+ check_blank_at_eof(&mf1, &mf2, &ecbdata);
1733
+ blank_at_eof = ecbdata.blank_at_eof_in_preimage;
1734
+
1735
if (blank_at_eof) {
1736
static char *err;
1737
if (!err)
t/t4019-diff-wserror.sh
+1
-1
@@ -193,7 +193,7 @@ test_expect_success 'do not color trailing cr in context' '
193
test_expect_success 'color new trailing blank lines' '
194
{ echo a; echo b; echo; echo; } >x &&
195
git add x &&
196
- { echo a; echo; echo; echo; echo; } >x &&
196
+ { echo a; echo; echo; echo; echo c; echo; echo; echo; echo; } >x &&
197
git diff --color x >output &&
198
cnt=$(grep "${blue_grep}" output | wc -l) &&
199
test $cnt = 2