Subject: [PATCH v7 12/17] merge-ort: make `path_messages` a strmap to a string_list

From: "Johannes Schindelin via GitGitGadget" <[email-masked]>
Date: Sat, 18 Jun 2022 00:20:55 +0000

From: Johannes Schindelin <[email-masked]>

This allows us once again to get away with less data copying.

Signed-off-by: Johannes Schindelin <[email-masked]>
Signed-off-by: Elijah Newren <[email-masked]>
---
 diff.c      | 27 ++++++++++++++++++++-------
 merge-ort.c | 34 +---------------------------------
 merge-ort.h |  2 +-
 3 files changed, 22 insertions(+), 41 deletions(-)

diff --git a/diff.c b/diff.c
index e71cf758861..2214ae49e4b 100644
--- a/diff.c
+++ b/diff.c
@@ -3362,23 +3362,23 @@ struct userdiff_driver *get_textconv(struct repository *r,
 	return userdiff_get_textconv(r, one->driver);
 }
 
-static struct strbuf *additional_headers(struct diff_options *o,
-					 const char *path)
+static struct string_list *additional_headers(struct diff_options *o,
+					      const char *path)
 {
 	if (!o->additional_path_headers)
 		return NULL;
 	return strmap_get(o->additional_path_headers, path);
 }
 
-static void add_formatted_headers(struct strbuf *msg,
-				  struct strbuf *more_headers,
+static void add_formatted_header(struct strbuf *msg,
+				  const char *header,
 				  const char *line_prefix,
 				  const char *meta,
 				  const char *reset)
 {
-	char *next, *newline;
+	const char *next, *newline;
 
-	for (next = more_headers->buf; *next; next = newline) {
+	for (next = header; *next; next = newline) {
 		newline = strchrnul(next, '\n');
 		strbuf_addf(msg, "%s%s%.*s%s\n", line_prefix, meta,
 			    (int)(newline - next), next, reset);
@@ -3387,6 +3387,19 @@ static void add_formatted_headers(struct strbuf *msg,
 	}
 }
 
+static void add_formatted_headers(struct strbuf *msg,
+				  struct string_list *more_headers,
+				  const char *line_prefix,
+				  const char *meta,
+				  const char *reset)
+{
+	int i;
+
+	for (i = 0; i < more_headers->nr; i++)
+		add_formatted_header(msg, more_headers->items[i].string,
+				     line_prefix, meta, reset);
+}
+
 static void builtin_diff(const char *name_a,
 			 const char *name_b,
 			 struct diff_filespec *one,
@@ -4314,7 +4327,7 @@ static void fill_metainfo(struct strbuf *msg,
 	const char *set = diff_get_color(use_color, DIFF_METAINFO);
 	const char *reset = diff_get_color(use_color, DIFF_RESET);
 	const char *line_prefix = diff_line_prefix(o);
-	struct strbuf *more_headers = NULL;
+	struct string_list *more_headers = NULL;
 
 	*must_show_header = 1;
 	strbuf_init(msg, PATH_MAX * 2 + 300);
diff --git a/merge-ort.c b/merge-ort.c
index 668aec64f13..dfec08c88be 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -4370,8 +4370,6 @@ void merge_finalize(struct merge_options *opt,
 		    struct merge_result *result)
 {
 	struct merge_options_internal *opti = result->priv;
-	struct hashmap_iter iter;
-	struct strmap_entry *e;
 
 	if (opt->renormalize)
 		git_attr_set_direction(GIT_ATTR_CHECKIN);
@@ -4379,15 +4377,6 @@ void merge_finalize(struct merge_options *opt,
 
 	clear_or_reinit_internal_opts(opti, 0);
 	FREE_AND_NULL(opti);
-
-	/* Release and free each strbuf found in path_messages */
-	strmap_for_each_entry(result->path_messages, &iter, e) {
-		struct strbuf *buf = e->value;
-
-		strbuf_release(buf);
-	}
-	strmap_clear(result->path_messages, 1);
-	FREE_AND_NULL(result->path_messages);
 }
 
 /*** Function Grouping: helper functions for merge_incore_*() ***/
@@ -4611,8 +4600,6 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
 					    struct merge_result *result)
 {
 	struct object_id working_tree_oid;
-	struct hashmap_iter iter;
-	struct strmap_entry *e;
 
 	if (opt->subtree_shift) {
 		side2 = shift_tree_object(opt->repo, side1, side2,
@@ -4653,26 +4640,7 @@ redo:
 	trace2_region_leave("merge", "process_entries", opt->repo);
 
 	/* Set return values */
-	result->path_messages = xcalloc(1, sizeof(*result->path_messages));
-	strmap_init_with_options(result->path_messages, NULL, 0);
-	strmap_for_each_entry(&opt->priv->conflicts, &iter, e) {
-		const char *path = e->key;
-		struct strbuf *buf = strmap_get(result->path_messages, path);
-		struct string_list *conflicts = e->value;
-
-		if (!buf) {
-			buf = xcalloc(1, sizeof(*buf));
-			strbuf_init(buf, 0);
-			strmap_put(result->path_messages, path, buf);
-		}
-
-		for (int i = 0; i < conflicts->nr; i++) {
-			if (buf->len)
-				strbuf_addch(buf, '\n');
-			strbuf_addstr(buf, conflicts->items[i].string);
-			strbuf_trim_trailing_newline(buf);
-		}
-	}
+	result->path_messages = &opt->priv->conflicts;
 
 	result->tree = parse_tree_indirect(&working_tree_oid);
 	/* existence of conflicted entries implies unclean */
diff --git a/merge-ort.h b/merge-ort.h
index f9c536ed8c4..c4909bcbf96 100644
--- a/merge-ort.h
+++ b/merge-ort.h
@@ -28,7 +28,7 @@ struct merge_result {
 	/*
 	 * Special messages and conflict notices for various paths
 	 *
-	 * This is a map of pathnames to strbufs. It contains various
+	 * This is a map of pathnames to a string_list. It contains various
 	 * warning/conflict/notice messages (possibly multiple per path)
 	 * that callers may want to use.
 	 */
-- 
gitgitgadget