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

[PATCH 2/3] merge-tree: drop generate_common strategy

From
Jeff King <peff@peff.net>
Date
Feb 23, 2016, 06:06 UTC
Message-ID
<20160223060655.GB3205@sigill.intra.peff.net>
In-Reply-To
<20160223060338.GA2912@sigill.intra.peff.net>

When merge_blobs sees an add/add conflict, it tries to create a virtual base object for the 3-way merge that consists of the common lines of each file. It inherited this strategy from merge-one-file in 0c79938 (Improved three-way blob merging code, 2006-06-28), and the point is to minimize the size of the conflict hunks. That commit talks about "if libxdiff were to ever grow a compatible three-way merge, it could probably be directly plugged in".

That has long since happened. So as with merge-one-file in the previous commit, this extra step is no longer necessary. Our 3-way merge code is smart enough to do the minimizing itself if we simply feed it an empty base, which is what the more modern merge-recursive strategy already does.

Not only does this let us drop some code, but it removes an overflow bug in generate_common_file(). We allocate a buffer as large as the smallest of the two blobs, under the assumption that there cannot be more common content than what is in the smaller blob. However, xdiff may feed us more: if neither file ends in a newline, it feeds us the "\nNo newline at end of file" marker as common content, and we write it into the output. If the differences between the files are small than that string, we overflow the output buffer. This patch solves it by simply dropping the buggy code entirely.

Signed-off-by: Jeff King <peff@peff.net>
---
 merge-blobs.c | 38 ++------------------------------------
 1 file changed, 2 insertions(+), 36 deletions(-)
diff --git a/merge-blobs.c b/merge-blobs.c
index ddca601..9b6eac2 100644
--- a/merge-blobs.c
+++ b/merge-blobs.c
@@ -48,40 +48,6 @@ static void *three_way_filemerge(const char *path, mmfile_t *base, mmfile_t *our
 	return res.ptr;
 }
 
-static int common_outf(void *priv_, mmbuffer_t *mb, int nbuf)
-{
-	int i;
-	mmfile_t *dst = priv_;
-
-	for (i = 0; i < nbuf; i++) {
-		memcpy(dst->ptr + dst->size, mb[i].ptr, mb[i].size);
-		dst->size += mb[i].size;
-	}
-	return 0;
-}
-
-static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
-{
-	unsigned long size = f1->size < f2->size ? f1->size : f2->size;
-	void *ptr = xmalloc(size);
-	xpparam_t xpp;
-	xdemitconf_t xecfg;
-	xdemitcb_t ecb;
-
-	memset(&xpp, 0, sizeof(xpp));
-	xpp.flags = 0;
-	memset(&xecfg, 0, sizeof(xecfg));
-	xecfg.ctxlen = 3;
-	xecfg.flags = XDL_EMIT_COMMON;
-	ecb.outf = common_outf;
-
-	res->ptr = ptr;
-	res->size = 0;
-
-	ecb.priv = res;
-	return xdi_diff(f1, f2, &xpp, &xecfg, &ecb);
-}
-
 void *merge_blobs(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
 {
 	void *res = NULL;
@@ -112,8 +78,8 @@ void *merge_blobs(const char *path, struct blob *base, struct blob *our, struct
 		if (fill_mmfile_blob(&common, base) < 0)
 			goto out_free_f2_f1;
 	} else {
-		if (generate_common_file(&common, &f1, &f2) < 0)
-			goto out_free_f2_f1;
+		common.ptr = xstrdup("");
+		common.size = 0;
 	}
 	res = three_way_filemerge(path, &common, &f1, &f2, size);
 	free_mmfile(&common);
-- 
2.7.2.645.g4e1306c
Previous: Jeff KingNext: Jeff King
Message 10 of 19 in “What's cooking in git.git (Feb 2016, #05; Wed, 17)”
  1. Junio C HamanoFeb 17, 2016
  2. Jeff KingFeb 17, 2016
  3. Junio C HamanoFeb 18, 2016
  4. whither merge-tree? (was: What's cooking in git.git (Feb 2016, #05; Wed, 17))Jeff King, Feb 22, 2016
  5. Junio C HamanoFeb 22, 2016
  6. Jeff KingFeb 23, 2016
  7. Jeff KingFeb 23, 2016
  8. Jeff KingFeb 23, 2016
  9. 1/3 merge-one-file: use empty blob for add/add baseJeff King, Feb 23, 2016
  10. 2/3 merge-tree: drop generate_common strategyJeff King, Feb 23, 2016
  11. 3/3 xdiff: drop XDL_EMIT_COMMONJeff King, Feb 23, 2016
  12. Junio C HamanoFeb 23, 2016
  13. Jeff KingFeb 23, 2016
  14. Stefan FrühwirthFeb 23, 2016
  15. Dennis KaarsemakerFeb 24, 2016
  16. Jeff KingFeb 24, 2016
  17. Jeff KingFeb 24, 2016
  18. Johannes SchindelinFeb 23, 2016
  19. Duy NguyenFeb 23, 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.