@matheusbsbs / matheus-bagliano / commits / d68fe26f3e
Fork 0

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