Code

Merge branch 'sp/maint-index-pack' into maint
[git.git] / merge-tree.c
index 7cf00be6d51b17ca60979a9c856e67405906d9a7..02fc10f7e622ba1c53065e7cf4563ff10af0c41f 100644 (file)
@@ -57,11 +57,11 @@ extern void *merge_file(struct blob *, struct blob *, struct blob *, unsigned lo
 
 static void *result(struct merge_list *entry, unsigned long *size)
 {
-       char type[20];
+       enum object_type type;
        struct blob *base, *our, *their;
 
        if (!entry->stage)
-               return read_sha1_file(entry->blob->object.sha1, type, size);
+               return read_sha1_file(entry->blob->object.sha1, &type, size);
        base = NULL;
        if (entry->stage == 1) {
                base = entry->blob;
@@ -80,10 +80,10 @@ static void *result(struct merge_list *entry, unsigned long *size)
 
 static void *origin(struct merge_list *entry, unsigned long *size)
 {
-       char type[20];
+       enum object_type type;
        while (entry) {
                if (entry->stage == 2)
-                       return read_sha1_file(entry->blob->object.sha1, type, size);
+                       return read_sha1_file(entry->blob->object.sha1, &type, size);
                entry = entry->link;
        }
        return NULL;
@@ -106,8 +106,8 @@ static void show_diff(struct merge_list *entry)
        xdemitcb_t ecb;
 
        xpp.flags = XDF_NEED_MINIMAL;
+       memset(&xecfg, 0, sizeof(xecfg));
        xecfg.ctxlen = 3;
-       xecfg.flags = 0;
        ecb.outf = show_outf;
        ecb.priv = NULL;
 
@@ -119,7 +119,7 @@ static void show_diff(struct merge_list *entry)
        if (!dst.ptr)
                size = 0;
        dst.size = size;
-       xdl_diff(&src, &dst, &xpp, &xecfg, &ecb);
+       xdi_diff(&src, &dst, &xpp, &xecfg, &ecb);
        free(src.ptr);
        free(dst.ptr);
 }
@@ -152,7 +152,7 @@ static int same_entry(struct name_entry *a, struct name_entry *b)
 {
        return  a->sha1 &&
                b->sha1 &&
-               !memcmp(a->sha1, b->sha1, 20) &&
+               !hashcmp(a->sha1, b->sha1) &&
                a->mode == b->mode;
 }
 
@@ -168,7 +168,13 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsi
        return res;
 }
 
-static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result)
+static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
+{
+       char *path = xmalloc(traverse_path_len(info, n) + 1);
+       return make_traverse_path(path, info, n);
+}
+
+static void resolve(const struct traverse_info *info, struct name_entry *branch1, struct name_entry *result)
 {
        struct merge_list *orig, *final;
        const char *path;
@@ -177,7 +183,7 @@ static void resolve(const char *base, struct name_entry *branch1, struct name_en
        if (!branch1)
                return;
 
-       path = strdup(mkpath("%s%s", base, result->path));
+       path = traverse_path(info, result);
        orig = create_entry(2, branch1->mode, branch1->sha1, path);
        final = create_entry(0, result->mode, result->sha1, path);
 
@@ -186,9 +192,8 @@ static void resolve(const char *base, struct name_entry *branch1, struct name_en
        add_merge_entry(final);
 }
 
-static int unresolved_directory(const char *base, struct name_entry n[3])
+static int unresolved_directory(const struct traverse_info *info, struct name_entry n[3])
 {
-       int baselen;
        char *newbase;
        struct name_entry *p;
        struct tree_desc t[3];
@@ -204,12 +209,7 @@ static int unresolved_directory(const char *base, struct name_entry n[3])
        }
        if (!S_ISDIR(p->mode))
                return 0;
-       baselen = strlen(base);
-       newbase = xmalloc(baselen + p->pathlen + 2);
-       memcpy(newbase, base, baselen);
-       memcpy(newbase + baselen, p->path, p->pathlen);
-       memcpy(newbase + baselen + p->pathlen, "/", 2);
-
+       newbase = traverse_path(info, p);
        buf0 = fill_tree_descriptor(t+0, n[0].sha1);
        buf1 = fill_tree_descriptor(t+1, n[1].sha1);
        buf2 = fill_tree_descriptor(t+2, n[2].sha1);
@@ -223,7 +223,7 @@ static int unresolved_directory(const char *base, struct name_entry n[3])
 }
 
 
-static struct merge_list *link_entry(unsigned stage, const char *base, struct name_entry *n, struct merge_list *entry)
+static struct merge_list *link_entry(unsigned stage, const struct traverse_info *info, struct name_entry *n, struct merge_list *entry)
 {
        const char *path;
        struct merge_list *link;
@@ -233,17 +233,17 @@ static struct merge_list *link_entry(unsigned stage, const char *base, struct na
        if (entry)
                path = entry->path;
        else
-               path = strdup(mkpath("%s%s", base, n->path));
+               path = traverse_path(info, n);
        link = create_entry(stage, n->mode, n->sha1, path);
        link->link = entry;
        return link;
 }
 
-static void unresolved(const char *base, struct name_entry n[3])
+static void unresolved(const struct traverse_info *info, struct name_entry n[3])
 {
        struct merge_list *entry = NULL;
 
-       if (unresolved_directory(base, n))
+       if (unresolved_directory(info, n))
                return;
 
        /*
@@ -251,9 +251,9 @@ static void unresolved(const char *base, struct name_entry n[3])
         * list has the stages in order - link_entry adds new
         * links at the front.
         */
-       entry = link_entry(3, base, n + 2, entry);
-       entry = link_entry(2, base, n + 1, entry);
-       entry = link_entry(1, base, n + 0, entry);
+       entry = link_entry(3, info, n + 2, entry);
+       entry = link_entry(2, info, n + 1, entry);
+       entry = link_entry(1, info, n + 0, entry);
 
        add_merge_entry(entry);
 }
@@ -287,36 +287,41 @@ static void unresolved(const char *base, struct name_entry n[3])
  * The successful merge rules are the same as for the three-way merge
  * in git-read-tree.
  */
-static void threeway_callback(int n, unsigned long mask, struct name_entry *entry, const char *base)
+static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *info)
 {
        /* Same in both? */
        if (same_entry(entry+1, entry+2)) {
                if (entry[0].sha1) {
-                       resolve(base, NULL, entry+1);
-                       return;
+                       resolve(info, NULL, entry+1);
+                       return mask;
                }
        }
 
        if (same_entry(entry+0, entry+1)) {
                if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) {
-                       resolve(base, entry+1, entry+2);
-                       return;
+                       resolve(info, entry+1, entry+2);
+                       return mask;
                }
        }
 
        if (same_entry(entry+0, entry+2)) {
                if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) {
-                       resolve(base, NULL, entry+1);
-                       return;
+                       resolve(info, NULL, entry+1);
+                       return mask;
                }
        }
 
-       unresolved(base, entry);
+       unresolved(info, entry);
+       return mask;
 }
 
 static void merge_trees(struct tree_desc t[3], const char *base)
 {
-       traverse_trees(3, t, base, threeway_callback);
+       struct traverse_info info;
+
+       setup_traverse_info(&info, base);
+       info.fn = threeway_callback;
+       traverse_trees(3, t, &info);
 }
 
 static void *get_tree_descriptor(struct tree_desc *desc, const char *rev)
@@ -337,9 +342,11 @@ int main(int argc, char **argv)
        struct tree_desc t[3];
        void *buf1, *buf2, *buf3;
 
-       if (argc < 4)
+       if (argc != 4)
                usage(merge_tree_usage);
 
+       setup_git_directory();
+
        buf1 = get_tree_descriptor(t+0, argv[1]);
        buf2 = get_tree_descriptor(t+1, argv[2]);
        buf3 = get_tree_descriptor(t+2, argv[3]);