[PATCH v2 3/5] diff.c: Fix --color-words showing trailing deleted words at another line

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



With --color-words, following example will show deleted word "bar" at
another line. (<r> represents red)
------------------
$ git diff
- foo bar
+ foo
$ git diff --color-words
foo
<r>bar</r>
------------------

This wrong behaviour is a bug in fn_out_diff_words_aux which always
outputs a newline after handling the diff line beginning with "+" and
ending with a newline.

Instead, we always supress the newline when using print_word, and in
fn_out_diff_words_aux, a newline is shown only in following cases:

  - true minus.suppressed_newline followd by a line beginning with
    '-', ' ' or '@' (i.e. not '+')
  - true plus.suppressed_newline followd by a line beginning with
    '+', ' ' or '@' (i.e. not '-')

Signed-off-by: Ping Yin <pkufranky@xxxxxxxxx>
---
 diff.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/diff.c b/diff.c
index b5f7141..11316fe 100644
--- a/diff.c
+++ b/diff.c
@@ -409,6 +409,7 @@ static void print_word(FILE *file, struct diff_words_buffer *buffer, int len, in
 static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
 {
 	struct diff_words_data *diff_words;
+	char cm;
 	struct diff_words_buffer *dm, *dp;
 	FILE *df;
 
@@ -417,10 +418,11 @@ static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
 	dp = &(diff_words->plus);
 	df = diff_words->file;
 
-	if (dm->suppressed_newline) {
-		if (line[0] != '+')
-			putc('\n', df);
+	if ((dm->suppressed_newline && line[0] != '+') ||
+			(dp->suppressed_newline && line[0] != '-')) {
+		putc('\n', df);
 		dm->suppressed_newline = 0;
+		dp->suppressed_newline = 0;
 	}
 
 	len--;
@@ -429,11 +431,14 @@ static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
 			print_word(df, dm, len, DIFF_FILE_OLD, 1);
 			break;
 		case '+':
-			print_word(df, dp, len, DIFF_FILE_NEW, 0);
+			print_word(df, dp, len, DIFF_FILE_NEW, 1);
 			break;
 		case ' ':
-			print_word(df, dp, len, DIFF_PLAIN, 0);
+			cm = dm->text.ptr[dm->current + len - 1];
+			print_word(df, dp, len, DIFF_PLAIN, 1);
 			dm->current += len;
+			if (cm == '\n')
+				dm->suppressed_newline = 1;
 			break;
 	}
 }
@@ -475,9 +480,11 @@ static void diff_words_show(struct diff_words_data *diff_words)
 	free(plus.ptr);
 	diff_words->minus.text.size = diff_words->plus.text.size = 0;
 
-	if (diff_words->minus.suppressed_newline) {
+	if (diff_words->minus.suppressed_newline ||
+			diff_words->plus.suppressed_newline) {
 		putc('\n', diff_words->file);
 		diff_words->minus.suppressed_newline = 0;
+		diff_words->plus.suppressed_newline = 0;
 	}
 }
 
-- 
1.5.5.1.121.g26b3

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux