OSDN Git Service

merge-tree: drop generate_common strategy
authorJeff King <peff@peff.net>
Tue, 23 Feb 2016 06:06:55 +0000 (01:06 -0500)
committerJunio C Hamano <gitster@pobox.com>
Tue, 23 Feb 2016 06:36:07 +0000 (22:36 -0800)
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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
merge-blobs.c

index 7abb894..4f68537 100644 (file)
@@ -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);