{"thread":{"id":"20948","subject":"[PATCH 0/4] Colouring whitespace errors in diff -B output","startedAt":"2009-09-15T06:15:02Z","lastAt":"2009-09-15T20:12:54Z","messageCount":7,"participants":["Junio C Hamano","Nanako Shiraishi"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"123208","messageId":"1252995306-32329-1-git-send-email-gitster@pobox.com","threadId":"20948","inReplyTo":null,"subject":"[PATCH 0/4] Colouring whitespace errors in diff -B output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-15T06:15:02Z","receivedAt":"2009-09-15T06:15:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Here is a 4-patch miniseries to teach \"diff -B\" output routines to detect\nand colour whitespace errors like we do for normal patches.\n\nThe first three patches are only about moving code around without changing\nanything.\n\nThe last one hooks \"diff -B\" logic to the per-line output routines in a\nway that mimicks how the normal patches are fed to them better, in order\nto take advantage of all the existing whitespace error detection and\ncolouring logic.\n\nJunio C Hamano (4):\n      diff.c: shuffling code around\n      diff.c: split emit_line() from the first char and the rest of the line\n      diff.c: emit_add_line() takes only the rest of the line\n      diff -B: colour whitespace errors\n\n diff.c |  327 +++++++++++++++++++++++++++++++++++-----------------------------\n 1 files changed, 180 insertions(+), 147 deletions(-)\n"},{"id":"123209","messageId":"1252995306-32329-2-git-send-email-gitster@pobox.com","threadId":"20948","inReplyTo":"1252995306-32329-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/4] diff.c: shuffling code around","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-15T06:15:03Z","receivedAt":"2009-09-15T06:15:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Move function, type, and structure definitions for fill_mmfile(),\ncount_trailing_blank(), check_blank_at_eof(), emit_line(),\nnew_blank_line_at_eof(), emit_add_line(), sane_truncate_fn, and\nemit_callback up in the file, so that they can be refactored into helper\nfunctions and reused by codepath for emitting rewrite patches.\n\nThis only moves the lines around to make the next two patches easier to\nread.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * This obviously comes on top of the earlier fix to the \"blank lines at\n   eof\" breakage.\n\n diff.c |  250 ++++++++++++++++++++++++++++++++--------------------------------\n 1 files changed, 125 insertions(+), 125 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 63a3bfc..7548966 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -241,6 +241,23 @@ static struct diff_tempfile {\n \tchar tmp_path[PATH_MAX];\n } diff_temp[2];\n \n+typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);\n+\n+struct emit_callback {\n+\tstruct xdiff_emit_state xm;\n+\tint color_diff;\n+\tunsigned ws_rule;\n+\tint blank_at_eof_in_preimage;\n+\tint blank_at_eof_in_postimage;\n+\tint lno_in_preimage;\n+\tint lno_in_postimage;\n+\tsane_truncate_fn truncate;\n+\tconst char **label_path;\n+\tstruct diff_words_data *diff_words;\n+\tint *found_changesp;\n+\tFILE *file;\n+};\n+\n static int count_lines(const char *data, int size)\n {\n \tint count, ch, completely_empty = 1, nl_just_seen = 0;\n@@ -301,6 +318,114 @@ static void copy_file_with_prefix(FILE *file,\n \t\tfprintf(file, \"%s\\n\\\\ No newline at end of file\\n\", reset);\n }\n \n+static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)\n+{\n+\tif (!DIFF_FILE_VALID(one)) {\n+\t\tmf->ptr = (char *)\"\"; /* does not matter */\n+\t\tmf->size = 0;\n+\t\treturn 0;\n+\t}\n+\telse if (diff_populate_filespec(one, 0))\n+\t\treturn -1;\n+\tmf->ptr = one->data;\n+\tmf->size = one->size;\n+\treturn 0;\n+}\n+\n+static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)\n+{\n+\tchar *ptr = mf->ptr;\n+\tlong size = mf->size;\n+\tint cnt = 0;\n+\n+\tif (!size)\n+\t\treturn cnt;\n+\tptr += size - 1; /* pointing at the very end */\n+\tif (*ptr != '\\n')\n+\t\t; /* incomplete line */\n+\telse\n+\t\tptr--; /* skip the last LF */\n+\twhile (mf->ptr < ptr) {\n+\t\tchar *prev_eol;\n+\t\tfor (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--)\n+\t\t\tif (*prev_eol == '\\n')\n+\t\t\t\tbreak;\n+\t\tif (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule))\n+\t\t\tbreak;\n+\t\tcnt++;\n+\t\tptr = prev_eol - 1;\n+\t}\n+\treturn cnt;\n+}\n+\n+static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,\n+\t\t\t       struct emit_callback *ecbdata)\n+{\n+\tint l1, l2, at;\n+\tunsigned ws_rule = ecbdata->ws_rule;\n+\tl1 = count_trailing_blank(mf1, ws_rule);\n+\tl2 = count_trailing_blank(mf2, ws_rule);\n+\tif (l2 <= l1) {\n+\t\tecbdata->blank_at_eof_in_preimage = 0;\n+\t\tecbdata->blank_at_eof_in_postimage = 0;\n+\t\treturn;\n+\t}\n+\tat = count_lines(mf1->ptr, mf1->size);\n+\tecbdata->blank_at_eof_in_preimage = (at - l1) + 1;\n+\n+\tat = count_lines(mf2->ptr, mf2->size);\n+\tecbdata->blank_at_eof_in_postimage = (at - l2) + 1;\n+}\n+\n+static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)\n+{\n+\tint has_trailing_newline, has_trailing_carriage_return;\n+\n+\thas_trailing_newline = (len > 0 && line[len-1] == '\\n');\n+\tif (has_trailing_newline)\n+\t\tlen--;\n+\thas_trailing_carriage_return = (len > 0 && line[len-1] == '\\r');\n+\tif (has_trailing_carriage_return)\n+\t\tlen--;\n+\n+\tfputs(set, file);\n+\tfwrite(line, len, 1, file);\n+\tfputs(reset, file);\n+\tif (has_trailing_carriage_return)\n+\t\tfputc('\\r', file);\n+\tif (has_trailing_newline)\n+\t\tfputc('\\n', file);\n+}\n+\n+static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)\n+{\n+\tif (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&\n+\t      ecbdata->blank_at_eof_in_preimage &&\n+\t      ecbdata->blank_at_eof_in_postimage &&\n+\t      ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&\n+\t      ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))\n+\t\treturn 0;\n+\treturn ws_blank_line(line + 1, len - 1, ecbdata->ws_rule);\n+}\n+\n+static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)\n+{\n+\tconst char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);\n+\tconst char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);\n+\n+\tif (!*ws)\n+\t\temit_line(ecbdata->file, set, reset, line, len);\n+\telse if (new_blank_line_at_eof(ecbdata, line, len))\n+\t\t/* Blank line at EOF - paint '+' as well */\n+\t\temit_line(ecbdata->file, ws, reset, line, len);\n+\telse {\n+\t\t/* Emit just the prefix, then the rest. */\n+\t\temit_line(ecbdata->file, set, reset, line, 1);\n+\t\tws_check_emit(line + 1, len - 1, ecbdata->ws_rule,\n+\t\t\t      ecbdata->file, set, reset, ws);\n+\t}\n+}\n+\n static void emit_rewrite_diff(const char *name_a,\n \t\t\t      const char *name_b,\n \t\t\t      struct diff_filespec *one,\n@@ -345,20 +470,6 @@ static void emit_rewrite_diff(const char *name_a,\n \t\tcopy_file_with_prefix(o->file, '+', two->data, two->size, new, reset);\n }\n \n-static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)\n-{\n-\tif (!DIFF_FILE_VALID(one)) {\n-\t\tmf->ptr = (char *)\"\"; /* does not matter */\n-\t\tmf->size = 0;\n-\t\treturn 0;\n-\t}\n-\telse if (diff_populate_filespec(one, 0))\n-\t\treturn -1;\n-\tmf->ptr = one->data;\n-\tmf->size = one->size;\n-\treturn 0;\n-}\n-\n struct diff_words_buffer {\n \tmmfile_t text;\n \tlong alloc;\n@@ -485,23 +596,6 @@ static void diff_words_show(struct diff_words_data *diff_words)\n \t}\n }\n \n-typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);\n-\n-struct emit_callback {\n-\tstruct xdiff_emit_state xm;\n-\tint color_diff;\n-\tunsigned ws_rule;\n-\tint blank_at_eof_in_preimage;\n-\tint blank_at_eof_in_postimage;\n-\tint lno_in_preimage;\n-\tint lno_in_postimage;\n-\tsane_truncate_fn truncate;\n-\tconst char **label_path;\n-\tstruct diff_words_data *diff_words;\n-\tint *found_changesp;\n-\tFILE *file;\n-};\n-\n static void free_diff_words_data(struct emit_callback *ecbdata)\n {\n \tif (ecbdata->diff_words) {\n@@ -524,55 +618,6 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix)\n \treturn \"\";\n }\n \n-static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)\n-{\n-\tint has_trailing_newline, has_trailing_carriage_return;\n-\n-\thas_trailing_newline = (len > 0 && line[len-1] == '\\n');\n-\tif (has_trailing_newline)\n-\t\tlen--;\n-\thas_trailing_carriage_return = (len > 0 && line[len-1] == '\\r');\n-\tif (has_trailing_carriage_return)\n-\t\tlen--;\n-\n-\tfputs(set, file);\n-\tfwrite(line, len, 1, file);\n-\tfputs(reset, file);\n-\tif (has_trailing_carriage_return)\n-\t\tfputc('\\r', file);\n-\tif (has_trailing_newline)\n-\t\tfputc('\\n', file);\n-}\n-\n-static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)\n-{\n-\tif (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&\n-\t      ecbdata->blank_at_eof_in_preimage &&\n-\t      ecbdata->blank_at_eof_in_postimage &&\n-\t      ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&\n-\t      ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))\n-\t\treturn 0;\n-\treturn ws_blank_line(line + 1, len - 1, ecbdata->ws_rule);\n-}\n-\n-static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)\n-{\n-\tconst char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);\n-\tconst char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);\n-\n-\tif (!*ws)\n-\t\temit_line(ecbdata->file, set, reset, line, len);\n-\telse if (new_blank_line_at_eof(ecbdata, line, len))\n-\t\t/* Blank line at EOF - paint '+' as well */\n-\t\temit_line(ecbdata->file, ws, reset, line, len);\n-\telse {\n-\t\t/* Emit just the prefix, then the rest. */\n-\t\temit_line(ecbdata->file, set, reset, line, 1);\n-\t\tws_check_emit(line + 1, len - 1, ecbdata->ws_rule,\n-\t\t\t      ecbdata->file, set, reset, ws);\n-\t}\n-}\n-\n static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)\n {\n \tconst char *cp;\n@@ -1464,51 +1509,6 @@ static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_fi\n \treturn NULL;\n }\n \n-static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)\n-{\n-\tchar *ptr = mf->ptr;\n-\tlong size = mf->size;\n-\tint cnt = 0;\n-\n-\tif (!size)\n-\t\treturn cnt;\n-\tptr += size - 1; /* pointing at the very end */\n-\tif (*ptr != '\\n')\n-\t\t; /* incomplete line */\n-\telse\n-\t\tptr--; /* skip the last LF */\n-\twhile (mf->ptr < ptr) {\n-\t\tchar *prev_eol;\n-\t\tfor (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--)\n-\t\t\tif (*prev_eol == '\\n')\n-\t\t\t\tbreak;\n-\t\tif (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule))\n-\t\t\tbreak;\n-\t\tcnt++;\n-\t\tptr = prev_eol - 1;\n-\t}\n-\treturn cnt;\n-}\n-\n-static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,\n-\t\t\t       struct emit_callback *ecbdata)\n-{\n-\tint l1, l2, at;\n-\tunsigned ws_rule = ecbdata->ws_rule;\n-\tl1 = count_trailing_blank(mf1, ws_rule);\n-\tl2 = count_trailing_blank(mf2, ws_rule);\n-\tif (l2 <= l1) {\n-\t\tecbdata->blank_at_eof_in_preimage = 0;\n-\t\tecbdata->blank_at_eof_in_postimage = 0;\n-\t\treturn;\n-\t}\n-\tat = count_lines(mf1->ptr, mf1->size);\n-\tecbdata->blank_at_eof_in_preimage = (at - l1) + 1;\n-\n-\tat = count_lines(mf2->ptr, mf2->size);\n-\tecbdata->blank_at_eof_in_postimage = (at - l2) + 1;\n-}\n-\n static void builtin_diff(const char *name_a,\n \t\t\t const char *name_b,\n \t\t\t struct diff_filespec *one,\n-- \n1.6.5.rc1.54.g4aad\n"},{"id":"123212","messageId":"1252995306-32329-3-git-send-email-gitster@pobox.com","threadId":"20948","inReplyTo":"1252995306-32329-1-git-send-email-gitster@pobox.com","subject":"[PATCH 2/4] diff.c: split emit_line() from the first char and the rest of the line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-15T06:15:04Z","receivedAt":"2009-09-15T06:15:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A new helper function emit_line_0() takes the first line of diff output\n(typically \"-\", \" \", or \"+\") separately from the remainder of the line.\nNo other functional changes.\n\nThis change will make it easier to reuse the logic when emitting the\nrewrite diff, as we do not want to copy a line only to add \"+\"/\"-\"/\" \"\nimmediately before its first character when we produce rewrite diff\noutput.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff.c |   10 +++++++++-\n 1 files changed, 9 insertions(+), 1 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 7548966..b5c2574 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -377,7 +377,8 @@ static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,\n \tecbdata->blank_at_eof_in_postimage = (at - l2) + 1;\n }\n \n-static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)\n+static void emit_line_0(FILE *file, const char *set, const char *reset,\n+\t\t\tint first, const char *line, int len)\n {\n \tint has_trailing_newline, has_trailing_carriage_return;\n \n@@ -389,6 +390,7 @@ static void emit_line(FILE *file, const char *set, const char *reset, const char\n \t\tlen--;\n \n \tfputs(set, file);\n+\tfputc(first, file);\n \tfwrite(line, len, 1, file);\n \tfputs(reset, file);\n \tif (has_trailing_carriage_return)\n@@ -397,6 +399,12 @@ static void emit_line(FILE *file, const char *set, const char *reset, const char\n \t\tfputc('\\n', file);\n }\n \n+static void emit_line(FILE *file, const char *set, const char *reset,\n+\t\t      const char *line, int len)\n+{\n+\temit_line_0(file, set, reset, line[0], line+1, len-1);\n+}\n+\n static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)\n {\n \tif (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&\n-- \n1.6.5.rc1.54.g4aad\n"},{"id":"123211","messageId":"1252995306-32329-4-git-send-email-gitster@pobox.com","threadId":"20948","inReplyTo":"1252995306-32329-1-git-send-email-gitster@pobox.com","subject":"[PATCH 3/4] diff.c: emit_add_line() takes only the rest of the line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-15T06:15:05Z","receivedAt":"2009-09-15T06:15:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"As the first character on the line that is fed to this function is always\n\"+\", it is pointless to send that along with the rest of the line.\n\nThis change will make it easier to reuse the logic when emitting the\nrewrite diff, as we do not want to copy a line only to add \"+\"/\"-\"/\" \"\nimmediately before its first character when we produce rewrite diff\noutput.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff.c |   14 ++++++++------\n 1 files changed, 8 insertions(+), 6 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex b5c2574..baf46ab 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -416,20 +416,22 @@ static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line\n \treturn ws_blank_line(line + 1, len - 1, ecbdata->ws_rule);\n }\n \n-static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)\n+static void emit_add_line(const char *reset,\n+\t\t\t  struct emit_callback *ecbdata,\n+\t\t\t  const char *line, int len)\n {\n \tconst char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);\n \tconst char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);\n \n \tif (!*ws)\n-\t\temit_line(ecbdata->file, set, reset, line, len);\n+\t\temit_line_0(ecbdata->file, set, reset, '+', line, len);\n \telse if (new_blank_line_at_eof(ecbdata, line, len))\n \t\t/* Blank line at EOF - paint '+' as well */\n-\t\temit_line(ecbdata->file, ws, reset, line, len);\n+\t\temit_line_0(ecbdata->file, ws, reset, '+', line, len);\n \telse {\n \t\t/* Emit just the prefix, then the rest. */\n-\t\temit_line(ecbdata->file, set, reset, line, 1);\n-\t\tws_check_emit(line + 1, len - 1, ecbdata->ws_rule,\n+\t\temit_line_0(ecbdata->file, set, reset, '+', \"\", 0);\n+\t\tws_check_emit(line, len, ecbdata->ws_rule,\n \t\t\t      ecbdata->file, set, reset, ws);\n \t}\n }\n@@ -726,7 +728,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)\n \t\temit_line(ecbdata->file, color, reset, line, len);\n \t} else {\n \t\tecbdata->lno_in_postimage++;\n-\t\temit_add_line(reset, ecbdata, line, len);\n+\t\temit_add_line(reset, ecbdata, line + 1, len - 1);\n \t}\n }\n \n-- \n1.6.5.rc1.54.g4aad\n"},{"id":"123210","messageId":"1252995306-32329-5-git-send-email-gitster@pobox.com","threadId":"20948","inReplyTo":"1252995306-32329-1-git-send-email-gitster@pobox.com","subject":"[PATCH 4/4] diff -B: colour whitespace errors","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-15T06:15:06Z","receivedAt":"2009-09-15T06:15:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"We used to send the old and new contents more or less straight out to the\noutput with only the original \"old is red, new is green\" colouring.  Now\nall the necessary support routines have been prepared, call them with a\nline of data at a time from the output code and have them check and color\nwhitespace errors in exactly the same way as they are called from the low\nlevel diff callback routines.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff.c |   75 +++++++++++++++++++++++++++++++++++++++++----------------------\n 1 files changed, 49 insertions(+), 26 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex baf46ab..b6d40d7 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -296,28 +296,6 @@ static void print_line_count(FILE *file, int count)\n \t}\n }\n \n-static void copy_file_with_prefix(FILE *file,\n-\t\t\t\t  int prefix, const char *data, int size,\n-\t\t\t\t  const char *set, const char *reset)\n-{\n-\tint ch, nl_just_seen = 1;\n-\twhile (0 < size--) {\n-\t\tch = *data++;\n-\t\tif (nl_just_seen) {\n-\t\t\tfputs(set, file);\n-\t\t\tputc(prefix, file);\n-\t\t}\n-\t\tif (ch == '\\n') {\n-\t\t\tnl_just_seen = 1;\n-\t\t\tfputs(reset, file);\n-\t\t} else\n-\t\t\tnl_just_seen = 0;\n-\t\tputc(ch, file);\n-\t}\n-\tif (!nl_just_seen)\n-\t\tfprintf(file, \"%s\\n\\\\ No newline at end of file\\n\", reset);\n-}\n-\n static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)\n {\n \tif (!DIFF_FILE_VALID(one)) {\n@@ -436,6 +414,38 @@ static void emit_add_line(const char *reset,\n \t}\n }\n \n+static void emit_rewrite_lines(struct emit_callback *ecb,\n+\t\t\t       int prefix, const char *data, int size)\n+{\n+\tconst char *endp = NULL;\n+\tstatic const char *nneof = \" No newline at end of file\\n\";\n+\tconst char *old = diff_get_color(ecb->color_diff, DIFF_FILE_OLD);\n+\tconst char *reset = diff_get_color(ecb->color_diff, DIFF_RESET);\n+\n+\twhile (0 < size) {\n+\t\tint len;\n+\n+\t\tendp = memchr(data, '\\n', size);\n+\t\tlen = endp ? (endp - data + 1) : size;\n+\t\tif (prefix != '+') {\n+\t\t\tecb->lno_in_preimage++;\n+\t\t\temit_line_0(ecb->file, old, reset, '-',\n+\t\t\t\t    data, len);\n+\t\t} else {\n+\t\t\tecb->lno_in_postimage++;\n+\t\t\temit_add_line(reset, ecb, data, len);\n+\t\t}\n+\t\tsize -= len;\n+\t\tdata += len;\n+\t}\n+\tif (!endp) {\n+\t\tconst char *plain = diff_get_color(ecb->color_diff,\n+\t\t\t\t\t\t   DIFF_PLAIN);\n+\t\temit_line_0(ecb->file, plain, reset, '\\\\',\n+\t\t\t    nneof, strlen(nneof));\n+\t}\n+}\n+\n static void emit_rewrite_diff(const char *name_a,\n \t\t\t      const char *name_b,\n \t\t\t      struct diff_filespec *one,\n@@ -447,10 +457,23 @@ static void emit_rewrite_diff(const char *name_a,\n \tconst char *name_a_tab, *name_b_tab;\n \tconst char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);\n \tconst char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);\n-\tconst char *old = diff_get_color(color_diff, DIFF_FILE_OLD);\n-\tconst char *new = diff_get_color(color_diff, DIFF_FILE_NEW);\n \tconst char *reset = diff_get_color(color_diff, DIFF_RESET);\n \tstatic struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;\n+\tstruct emit_callback ecbdata;\n+\n+\tmemset(&ecbdata, 0, sizeof(ecbdata));\n+\tecbdata.color_diff = color_diff;\n+\tecbdata.found_changesp = &o->found_changes;\n+\tecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);\n+\tecbdata.file = o->file;\n+\tif (ecbdata.ws_rule & WS_BLANK_AT_EOF) {\n+\t\tmmfile_t mf1, mf2;\n+\t\tfill_mmfile(&mf1, one);\n+\t\tfill_mmfile(&mf2, two);\n+\t\tcheck_blank_at_eof(&mf1, &mf2, &ecbdata);\n+\t}\n+\tecbdata.lno_in_preimage = 1;\n+\tecbdata.lno_in_postimage = 1;\n \n \tname_a += (*name_a == '/');\n \tname_b += (*name_b == '/');\n@@ -475,9 +498,9 @@ static void emit_rewrite_diff(const char *name_a,\n \tprint_line_count(o->file, lc_b);\n \tfprintf(o->file, \" @@%s\\n\", reset);\n \tif (lc_a)\n-\t\tcopy_file_with_prefix(o->file, '-', one->data, one->size, old, reset);\n+\t\temit_rewrite_lines(&ecbdata, '-', one->data, one->size);\n \tif (lc_b)\n-\t\tcopy_file_with_prefix(o->file, '+', two->data, two->size, new, reset);\n+\t\temit_rewrite_lines(&ecbdata, '+', two->data, two->size);\n }\n \n struct diff_words_buffer {\n-- \n1.6.5.rc1.54.g4aad\n"},{"id":"123214","messageId":"20090915155209.6117@nanako3.lavabit.com","threadId":"20948","inReplyTo":"1252995306-32329-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 0/4] Colouring whitespace errors in diff -B output","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2009-09-15T06:52:09Z","receivedAt":"2009-09-15T06:52:09Z","isPatch":true,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Quoting Junio C Hamano <gitster@pobox.com>\n\n> Here is a 4-patch miniseries to teach \"diff -B\" output routines to detect\n> and colour whitespace errors like we do for normal patches.\n>\n> The first three patches are only about moving code around without changing\n> anything.\n>\n> The last one hooks \"diff -B\" logic to the per-line output routines in a\n> way that mimicks how the normal patches are fed to them better, in order\n> to take advantage of all the existing whitespace error detection and\n> colouring logic.\n>\n> Junio C Hamano (4):\n>       diff.c: shuffling code around\n>       diff.c: split emit_line() from the first char and the rest of the line\n>       diff.c: emit_add_line() takes only the rest of the line\n>       diff -B: colour whitespace errors\n>\n>  diff.c |  327 +++++++++++++++++++++++++++++++++++-----------------------------\n>  1 files changed, 180 insertions(+), 147 deletions(-)\n\nSorry, but I don't seem to be able to apply these patches anywhere.\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"123279","messageId":"7vab0w55mh.fsf@alter.siamese.dyndns.org","threadId":"20948","inReplyTo":"20090915155209.6117@nanako3.lavabit.com","subject":"Re: [PATCH 0/4] Colouring whitespace errors in diff -B output","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-15T20:12:54Z","receivedAt":"2009-09-15T20:12:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nanako Shiraishi <nanako3@lavabit.com> writes:\n\n> Quoting Junio C Hamano <gitster@pobox.com>\n>\n>> The last one hooks \"diff -B\" logic to the per-line output routines in a\n>> way that mimicks how the normal patches are fed to them better, in order\n>> to take advantage of all the existing whitespace error detection and\n>> colouring logic.\n>>\n>> Junio C Hamano (4):\n>>       diff.c: shuffling code around\n>>       diff.c: split emit_line() from the first char and the rest of the line\n>>       diff.c: emit_add_line() takes only the rest of the line\n>>       diff -B: colour whitespace errors\n>>\n>>  diff.c |  327 +++++++++++++++++++++++++++++++++++-----------------------------\n>>  1 files changed, 180 insertions(+), 147 deletions(-)\n>\n> Sorry, but I don't seem to be able to apply these patches anywhere.\n\nThere is a subtle bug in \"split emit_line()\" patch I sent out, but later I\nnoticed the problem and fixed it in my tree, so please use the updated one\ninstead from my tree.\n\nThe series applies cleanly at the tip of jc/maint-1.6.0-blank-at-eof, but\nthe result of applying them will have large conflicts whether you are\nmerging that into 'maint', 'master', or 'next'.  It's probably easier to\nuse the merge I've prepared to resolve them in my tree.\n\nI have these two topics:\n\n - jc/maint-1.6.0-blank-at-eof forks from old 1.6.0 codebase to contain\n   the above fixes (and the ones that are already in 'next'); and\n\n - jc/maint-blank-at-eof that forks from 1.6.4 codebase and merges the\n   above branch.  This branch does not have any commit on its own, but\n   does a rather nasty conflict resolution.\n\nI'll push out the result, merging the latter to 'next' (and 'pu'),\nsometime in the next few hours.\n"}]}