X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=merge-tree.c;h=9dcaab7a85fdb63b2140923a95b216917bfc0993;hb=fd7e9fb7ae206a64b87c7faecfc88716e98a7577;hp=0d6d43403bbd54e5d8582004e5927783c0b004d3;hpb=492e0759bfe4ff238b80ab80c27291ab99e4512b;p=git.git diff --git a/merge-tree.c b/merge-tree.c index 0d6d4340..9dcaab7a 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -1,51 +1,11 @@ #include "cache.h" -#include "diff.h" +#include "tree-walk.h" static const char merge_tree_usage[] = "git-merge-tree "; static int resolve_directories = 1; static void merge_trees(struct tree_desc t[3], const char *base); -static void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) -{ - unsigned long size = 0; - void *buf = NULL; - - if (sha1) { - buf = read_object_with_reference(sha1, "tree", &size, NULL); - if (!buf) - die("unable to read tree %s", sha1_to_hex(sha1)); - } - desc->size = size; - desc->buf = buf; - return buf; -} - -struct name_entry { - const unsigned char *sha1; - const char *path; - unsigned int mode; - int pathlen; -}; - -static void entry_clear(struct name_entry *a) -{ - memset(a, 0, sizeof(*a)); -} - -static int entry_compare(struct name_entry *a, struct name_entry *b) -{ - return base_name_compare( - a->path, a->pathlen, a->mode, - b->path, b->pathlen, b->mode); -} - -static void entry_extract(struct tree_desc *t, struct name_entry *a) -{ - a->sha1 = tree_entry_extract(t, &a->path, &a->mode); - a->pathlen = strlen(a->path); -} - /* An empty entry never compares same, not even to another empty entry */ static int same_entry(struct name_entry *a, struct name_entry *b) { @@ -55,9 +15,24 @@ static int same_entry(struct name_entry *a, struct name_entry *b) a->mode == b->mode; } -static void resolve(const char *base, struct name_entry *result) +static const char *sha1_to_hex_zero(const unsigned char *sha1) { - printf("0 %06o %s %s%s\n", result->mode, sha1_to_hex(result->sha1), base, result->path); + if (sha1) + return sha1_to_hex(sha1); + return "0000000000000000000000000000000000000000"; +} + +static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result) +{ + /* If it's already branch1, don't bother showing it */ + if (!branch1) + return; + + printf("0 %06o->%06o %s->%s %s%s\n", + branch1->mode, result->mode, + sha1_to_hex_zero(branch1->sha1), + sha1_to_hex_zero(result->sha1), + base, result->path); } static int unresolved_directory(const char *base, struct name_entry n[3]) @@ -100,9 +75,12 @@ static void unresolved(const char *base, struct name_entry n[3]) { if (unresolved_directory(base, n)) return; - printf("1 %06o %s %s%s\n", n[0].mode, sha1_to_hex(n[0].sha1), base, n[0].path); - printf("2 %06o %s %s%s\n", n[1].mode, sha1_to_hex(n[1].sha1), base, n[1].path); - printf("3 %06o %s %s%s\n", n[2].mode, sha1_to_hex(n[2].sha1), base, n[2].path); + if (n[0].sha1) + printf("1 %06o %s %s%s\n", n[0].mode, sha1_to_hex(n[0].sha1), base, n[0].path); + if (n[1].sha1) + printf("2 %06o %s %s%s\n", n[1].mode, sha1_to_hex(n[1].sha1), base, n[1].path); + if (n[2].sha1) + printf("3 %06o %s %s%s\n", n[2].mode, sha1_to_hex(n[2].sha1), base, n[2].path); } /* @@ -124,7 +102,7 @@ static void unresolved(const char *base, struct name_entry n[3]) * "0 mode sha1 filename" * NOTE NOTE NOTE! FIXME! We really really need to walk the index * in parallel with this too! - * + * * - conflict: * "1 mode sha1 filename" * "2 mode sha1 filename" @@ -134,76 +112,36 @@ 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 merge_trees(struct tree_desc t[3], const char *base) +static void threeway_callback(int n, unsigned long mask, struct name_entry *entry, const char *base) { - for (;;) { - struct name_entry entry[3]; - unsigned int mask = 0; - int i, last; - - last = -1; - for (i = 0; i < 3; i++) { - if (!t[i].size) - continue; - entry_extract(t+i, entry+i); - if (last >= 0) { - int cmp = entry_compare(entry+i, entry+last); - - /* - * Is the new name bigger than the old one? - * Ignore it - */ - if (cmp > 0) - continue; - /* - * Is the new name smaller than the old one? - * Ignore all old ones - */ - if (cmp < 0) - mask = 0; - } - mask |= 1u << i; - last = i; - } - if (!mask) - break; - - /* - * Update the tree entries we've walked, and clear - * all the unused name-entries. - */ - for (i = 0; i < 3; i++) { - if (mask & (1u << i)) { - update_tree_entry(t+i); - continue; - } - entry_clear(entry + i); + /* Same in both? */ + if (same_entry(entry+1, entry+2)) { + if (entry[0].sha1) { + resolve(base, NULL, entry+1); + return; } + } - /* Same in both? */ - if (same_entry(entry+1, entry+2)) { - if (entry[0].sha1) { - resolve(base, entry+1); - continue; - } + if (same_entry(entry+0, entry+1)) { + if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) { + resolve(base, entry+1, entry+2); + return; } + } - if (same_entry(entry+0, entry+1)) { - if (entry[2].sha1) { - resolve(base, entry+2); - continue; - } + if (same_entry(entry+0, entry+2)) { + if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) { + resolve(base, NULL, entry+1); + return; } + } - if (same_entry(entry+0, entry+2)) { - if (entry[1].sha1) { - resolve(base, entry+1); - continue; - } - } + unresolved(base, entry); +} - unresolved(base, entry); - } +static void merge_trees(struct tree_desc t[3], const char *base) +{ + traverse_trees(3, t, base, threeway_callback); } static void *get_tree_descriptor(struct tree_desc *desc, const char *rev) @@ -211,7 +149,7 @@ static void *get_tree_descriptor(struct tree_desc *desc, const char *rev) unsigned char sha1[20]; void *buf; - if (get_sha1(rev, sha1) < 0) + if (get_sha1(rev, sha1)) die("unknown rev %s", rev); buf = fill_tree_descriptor(desc, sha1); if (!buf)