git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC/PATCH 13/17] diff.c: convert word diffing to use emit_line_*

From
Stefan Beller <sbeller@google.com>
Date
Sep 13, 2016, 04:46 UTC
Message-ID
<20160913044613.1037-14-sbeller@google.com>
In-Reply-To
<20160913044613.1037-1-sbeller@google.com>

In a later patch, I want to propose an option to detect&color moved lines in a diff, which cannot be done in a one-pass over the diff. Instead we need to go over the whole diff twice, because we cannot detect the first line of the two corresponding lines (+ and -) that got moved.

So to prepare the diff machinery for two pass algorithms (i.e. buffer it all up and then operate on the result), move all emissions to places, such that the only emitting function is emit_line_0.

This covers all code related to diffing words.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 diff.c | 56 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/diff.c b/diff.c
index 00a5a4e..3940f79 100644
--- a/diff.c
+++ b/diff.c
@@ -828,37 +828,38 @@ struct diff_words_data {
 	struct diff_words_style *style;
 };
 
-static int fn_out_diff_words_write_helper(FILE *fp,
+static int fn_out_diff_words_write_helper(struct diff_options *o,
 					  struct diff_words_style_elem *st_el,
 					  const char *newline,
 					  size_t count, const char *buf,
 					  const char *line_prefix)
 {
-	int print = 0;
+	struct strbuf sb = STRBUF_INIT;
 
 	while (count) {
 		char *p = memchr(buf, '\n', count);
-		if (print)
-			fputs(line_prefix, fp);
+
 		if (p != buf) {
-			if (st_el->color && fputs(st_el->color, fp) < 0)
-				return -1;
-			if (fputs(st_el->prefix, fp) < 0 ||
-			    fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
-			    fputs(st_el->suffix, fp) < 0)
-				return -1;
-			if (st_el->color && *st_el->color
-			    && fputs(GIT_COLOR_RESET, fp) < 0)
-				return -1;
+			if (st_el->color)
+				strbuf_addstr(&sb, st_el->color);
+			strbuf_addstr(&sb, st_el->prefix);
+			strbuf_add(&sb, buf, p ? p - buf : count);
+			strbuf_addstr(&sb, st_el->suffix);
+			if (st_el->color && *st_el->color)
+			    strbuf_addstr(&sb, GIT_COLOR_RESET);
 		}
 		if (!p)
-			return 0;
-		if (fputs(newline, fp) < 0)
-			return -1;
+			goto out;
+		strbuf_addstr(&sb, newline);
+		emit_line_0(o, 0, 0, 0, sb.buf, sb.len);
+		strbuf_reset(&sb);
 		count -= p + 1 - buf;
 		buf = p + 1;
-		print = 1;
 	}
+out:
+	if (sb.len)
+		emit_line_0(o, 0, 0, 0, sb.buf, sb.len);
+	strbuf_release(&sb);
 	return 0;
 }
 
@@ -936,25 +937,25 @@ static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
 	} else
 		plus_begin = plus_end = diff_words->plus.orig[plus_first].end;
 
-	if (color_words_output_graph_prefix(diff_words)) {
-		fputs(line_prefix, diff_words->opt->file);
-	}
+	if (color_words_output_graph_prefix(diff_words))
+		emit_line_0(diff_words->opt, 0, 0, 0, "", 0);
+
 	if (diff_words->current_plus != plus_begin) {
-		fn_out_diff_words_write_helper(diff_words->opt->file,
+		fn_out_diff_words_write_helper(diff_words->opt,
 				&style->ctx, style->newline,
 				plus_begin - diff_words->current_plus,
 				diff_words->current_plus, line_prefix);
 		if (*(plus_begin - 1) == '\n')
-			fputs(line_prefix, diff_words->opt->file);
+			emit_line_0(diff_words->opt, 0, 0, 0, "", 0);
 	}
 	if (minus_begin != minus_end) {
-		fn_out_diff_words_write_helper(diff_words->opt->file,
+		fn_out_diff_words_write_helper(diff_words->opt,
 				&style->old, style->newline,
 				minus_end - minus_begin, minus_begin,
 				line_prefix);
 	}
 	if (plus_begin != plus_end) {
-		fn_out_diff_words_write_helper(diff_words->opt->file,
+		fn_out_diff_words_write_helper(diff_words->opt,
 				&style->new, style->newline,
 				plus_end - plus_begin, plus_begin,
 				line_prefix);
@@ -1050,8 +1051,7 @@ static void diff_words_show(struct diff_words_data *diff_words)
 
 	/* special case: only removal */
 	if (!diff_words->plus.text.size) {
-		fputs(line_prefix, diff_words->opt->file);
-		fn_out_diff_words_write_helper(diff_words->opt->file,
+		fn_out_diff_words_write_helper(diff_words->opt,
 			&style->old, style->newline,
 			diff_words->minus.text.size,
 			diff_words->minus.text.ptr, line_prefix);
@@ -1077,8 +1077,8 @@ static void diff_words_show(struct diff_words_data *diff_words)
 	if (diff_words->current_plus != diff_words->plus.text.ptr +
 			diff_words->plus.text.size) {
 		if (color_words_output_graph_prefix(diff_words))
-			fputs(line_prefix, diff_words->opt->file);
-		fn_out_diff_words_write_helper(diff_words->opt->file,
+			emit_line_0(diff_words->opt, 0, 0, 0, "", 0);
+		fn_out_diff_words_write_helper(diff_words->opt,
 			&style->ctx, style->newline,
 			diff_words->plus.text.ptr + diff_words->plus.text.size
 			- diff_words->current_plus, diff_words->current_plus,
-- 
2.10.0.21.g1da280f.dirty
Previous: Stefan BellerNext: Stefan Beller
Message 15 of 28 in “[RFC/PATCH 00/17]”
  1. 00/17 Stefan Beller, Sep 13, 2016
  2. 01/17 diff: move line ending check into emit_hunk_headerStefan Beller, Sep 13, 2016
  3. René ScharfeSep 13, 2016
  4. Stefan BellerSep 13, 2016
  5. 02/17 diff: emit_{add, del, context}_line to increase {pre,post}image line countStefan Beller, Sep 13, 2016
  6. 03/17 diff.c: drop tautologous condition in emit_line_0Stefan Beller, Sep 13, 2016
  7. 04/17 diff.c: factor out diff_flush_patch_all_file_pairsStefan Beller, Sep 13, 2016
  8. 05/17 diff.c: emit_line_0 can handle no color settingStefan Beller, Sep 13, 2016
  9. Junio C HamanoSep 13, 2016
  10. 08/17 diff.c: convert emit_rewrite_diff to use emit_line_*Stefan Beller, Sep 13, 2016
  11. 07/17 diff.c: convert builtin_diff to use emit_line_*Stefan Beller, Sep 13, 2016
  12. 06/17 diff.c: convert fn_out_consume to use emit_line_*Stefan Beller, Sep 13, 2016
  13. Junio C HamanoSep 13, 2016
  14. 09/17 diff.c: convert emit_rewrite_lines to use emit_line_*Stefan Beller, Sep 13, 2016
  15. 13/17 diff.c: convert word diffing to use emit_line_*Stefan Beller, Sep 13, 2016
  16. 12/17 diff.c: convert show_stats to use emit_line_*Stefan Beller, Sep 13, 2016
  17. 10/17 submodule.c: convert show_submodule_summary to use emit_line_fmtStefan Beller, Sep 13, 2016
  18. Junio C HamanoSep 13, 2016
  19. Stefan BellerSep 13, 2016
  20. 14/17 diff.c: convert diff_flush to use emit_line_*Stefan Beller, Sep 13, 2016
  21. 17/17 diff.c: color moved lines differentlyStefan Beller, Sep 13, 2016
  22. 11/17 diff.c: convert emit_binary_diff_body to use emit_line_*Stefan Beller, Sep 13, 2016
  23. 16/17 diff: buffer output in emit_line_0Stefan Beller, Sep 13, 2016
  24. Junio C HamanoSep 13, 2016
  25. Stefan BellerSep 13, 2016
  26. Junio C HamanoSep 13, 2016
  27. Stefan BellerSep 13, 2016
  28. 15/17 diff.c: convert diff_summary to use emit_line_*Stefan Beller, Sep 13, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.