merge-file: handle empty files gracefully
[gitweb.git] / merge-file.c
index f32c6538250e560039de2d5262def7953915411d..2a939c9dd835a7e7946eb1548e4cf637ae3ca329 100644 (file)
@@ -3,62 +3,16 @@
 #include "xdiff-interface.h"
 #include "blob.h"
 
-static void rm_temp_file(const char *filename)
-{
-       unlink(filename);
-       free((void *)filename);
-}
-
-static const char *write_temp_file(mmfile_t *f)
-{
-       int fd;
-       const char *tmp = getenv("TMPDIR");
-       char *filename;
-
-       if (!tmp)
-               tmp = "/tmp";
-       filename = mkpath("%s/%s", tmp, "git-tmp-XXXXXX");
-       fd = mkstemp(filename);
-       if (fd < 0)
-               return NULL;
-       filename = strdup(filename);
-       if (f->size != xwrite(fd, f->ptr, f->size)) {
-               rm_temp_file(filename);
-               return NULL;
-       }
-       close(fd);
-       return filename;
-}
-
-static void *read_temp_file(const char *filename, unsigned long *size)
-{
-       struct stat st;
-       char *buf = NULL;
-       int fd = open(filename, O_RDONLY);
-       if (fd < 0)
-               return NULL;
-       if (!fstat(fd, &st)) {
-               *size = st.st_size;
-               buf = xmalloc(st.st_size);
-               if (st.st_size != xread(fd, buf, st.st_size)) {
-                       free(buf);
-                       buf = NULL;
-               }
-       }
-       close(fd);
-       return buf;
-}
-
 static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
 {
        void *buf;
        unsigned long size;
-       char type[20];
+       enum object_type type;
 
-       buf = read_sha1_file(obj->object.sha1, type, &size);
+       buf = read_sha1_file(obj->object.sha1, &type, &size);
        if (!buf)
                return -1;
-       if (strcmp(type, blob_type))
+       if (type != OBJ_BLOB)
                return -1;
        f->ptr = buf;
        f->size = size;
@@ -72,22 +26,19 @@ static void free_mmfile(mmfile_t *f)
 
 static void *three_way_filemerge(mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size)
 {
-       void *res;
-       const char *t1, *t2, *t3;
-
-       t1 = write_temp_file(base);
-       t2 = write_temp_file(our);
-       t3 = write_temp_file(their);
-       res = NULL;
-       if (t1 && t2 && t3) {
-               int code = run_command("merge", t2, t1, t3, NULL);
-               if (!code || code == -1)
-                       res = read_temp_file(t2, size);
-       }
-       rm_temp_file(t1);
-       rm_temp_file(t2);
-       rm_temp_file(t3);
-       return res;
+       mmbuffer_t res;
+       xpparam_t xpp;
+       int merge_status;
+
+       memset(&xpp, 0, sizeof(xpp));
+       merge_status = xdl_merge(base, our, ".our", their, ".their",
+               &xpp, XDL_MERGE_ZEALOUS, &res);
+
+       if (merge_status < 0)
+               return NULL;
+
+       *size = res.size;
+       return res.ptr;
 }
 
 static int common_outf(void *priv_, mmbuffer_t *mb, int nbuf)
@@ -111,6 +62,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
        xdemitcb_t ecb;
 
        xpp.flags = XDF_NEED_MINIMAL;
+       memset(&xecfg, 0, sizeof(xecfg));
        xecfg.ctxlen = 3;
        xecfg.flags = XDL_EMIT_COMMON;
        ecb.outf = common_outf;
@@ -119,7 +71,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
        res->size = 0;
 
        ecb.priv = res;
-       return xdl_diff(f1, f2, &xpp, &xecfg, &ecb);
+       return xdi_diff(f1, f2, &xpp, &xecfg, &ecb);
 }
 
 void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
@@ -135,12 +87,12 @@ void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsign
         * modified in the other branch!
         */
        if (!our || !their) {
-               char type[20];
+               enum object_type type;
                if (base)
                        return NULL;
                if (!our)
                        our = their;
-               return read_sha1_file(our->object.sha1, type, size);
+               return read_sha1_file(our->object.sha1, &type, size);
        }
 
        if (fill_mmfile_blob(&f1, our) < 0)