X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=merge-recursive.c;h=bac16f577c95937a76738dce5d659cff71bd03ab;hb=2eff14259ea4035dc5f8a18f5998e88dd4da207e;hp=9d53bcd5d626834f103ddcff2b59767579e69051;hpb=8042ed1cebd37419ff38f540482355c0f1d30936;p=git.git diff --git a/merge-recursive.c b/merge-recursive.c index 9d53bcd5d..bac16f577 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -3,13 +3,6 @@ * Fredrik Kuivinen. * The thieves were Alex Riesen and Johannes Schindelin, in June/July 2006 */ -#include -#include -#include -#include -#include -#include -#include #include "cache.h" #include "cache-tree.h" #include "commit.h" @@ -610,6 +603,12 @@ static void fill_mm(const unsigned char *sha1, mmfile_t *mm) unsigned long size; char type[20]; + if (!hashcmp(sha1, null_sha1)) { + mm->ptr = xstrdup(""); + mm->size = 0; + return; + } + mm->ptr = read_sha1_file(sha1, type, &size); if (!mm->ptr || strcmp(type, blob_type)) die("unable to read blob object %s", sha1_to_hex(sha1)); @@ -650,8 +649,8 @@ static struct merge_file_info merge_file(struct diff_filespec *o, char *name1, *name2; int merge_status; - name1 = xstrdup(mkpath("%s/%s", branch1, a->path)); - name2 = xstrdup(mkpath("%s/%s", branch2, b->path)); + name1 = xstrdup(mkpath("%s:%s", branch1, a->path)); + name2 = xstrdup(mkpath("%s:%s", branch2, b->path)); fill_mm(o->sha1, &orig); fill_mm(a->sha1, &src1); @@ -873,7 +872,7 @@ static int process_renames(struct path_list *a_renames, struct diff_filespec src_other, dst_other; int try_merge, stage = a_renames == renames1 ? 3: 2; - remove_file(1, ren1_src, 1); + remove_file(1, ren1_src, index_only); hashcpy(src_other.sha1, ren1->src_entry->stages[stage].sha); src_other.mode = ren1->src_entry->stages[stage].mode; @@ -1045,38 +1044,17 @@ static int process_entry(const char *path, struct stage_data *entry, output("Adding %s", path); update_file(1, sha, mode, path); } - } else if (!o_sha && a_sha && b_sha) { - /* Case C: Added in both (check for same permissions). */ - if (sha_eq(a_sha, b_sha)) { - if (a_mode != b_mode) { - clean_merge = 0; - output("CONFLICT: File %s added identically in both branches, " - "but permissions conflict %06o->%06o", - path, a_mode, b_mode); - output("CONFLICT: adding with permission: %06o", a_mode); - update_file(0, a_sha, a_mode, path); - } else { - /* This case is handled by git-read-tree */ - assert(0 && "This case must be handled by git-read-tree"); - } - } else { - const char *new_path1, *new_path2; - clean_merge = 0; - new_path1 = unique_path(path, branch1); - new_path2 = unique_path(path, branch2); - output("CONFLICT (add/add): File %s added non-identically " - "in both branches. Adding as %s and %s instead.", - path, new_path1, new_path2); - remove_file(0, path, 0); - update_file(0, a_sha, a_mode, new_path1); - update_file(0, b_sha, b_mode, new_path2); - } - - } else if (o_sha && a_sha && b_sha) { + } else if (a_sha && b_sha) { + /* Case C: Added in both (check for same permissions) and */ /* case D: Modified in both, but differently. */ + const char *reason = "content"; struct merge_file_info mfi; struct diff_filespec o, a, b; + if (!o_sha) { + reason = "add/add"; + o_sha = (unsigned char *)null_sha1; + } output("Auto-merging %s", path); o.path = a.path = b.path = (char *)path; hashcpy(o.sha1, o_sha); @@ -1093,7 +1071,8 @@ static int process_entry(const char *path, struct stage_data *entry, update_file(1, mfi.sha, mfi.mode, path); else { clean_merge = 0; - output("CONFLICT (content): Merge conflict in %s", path); + output("CONFLICT (%s): Merge conflict in %s", + reason, path); if (index_only) update_file(0, mfi.sha, mfi.mode, path); @@ -1269,6 +1248,18 @@ static int merge(struct commit *h1, return clean; } +static const char *better_branch_name(const char *branch) +{ + static char githead_env[8 + 40 + 1]; + char *name; + + if (strlen(branch) != 40) + return branch; + sprintf(githead_env, "GITHEAD_%s", branch); + name = getenv(githead_env); + return name ? name : branch; +} + static struct commit *get_ref(const char *ref) { unsigned char sha1[20]; @@ -1277,6 +1268,9 @@ static struct commit *get_ref(const char *ref) if (get_sha1(ref, sha1)) die("Could not resolve ref '%s'", ref); object = deref_tag(parse_object(sha1), ref, strlen(ref)); + if (object->type == OBJ_TREE) + return make_virtual_commit((struct tree*)object, + better_branch_name(ref)); if (object->type != OBJ_COMMIT) return NULL; if (parse_commit((struct commit *)object)) @@ -1293,7 +1287,7 @@ int main(int argc, char *argv[]) struct commit *result, *h1, *h2; git_config(git_default_config); /* core.filemode */ - original_index_file = getenv("GIT_INDEX_FILE"); + original_index_file = getenv(INDEX_ENVIRONMENT); if (!original_index_file) original_index_file = xstrdup(git_path("index")); @@ -1314,11 +1308,14 @@ int main(int argc, char *argv[]) branch1 = argv[++i]; branch2 = argv[++i]; - printf("Merging %s with %s\n", branch1, branch2); h1 = get_ref(branch1); h2 = get_ref(branch2); + branch1 = better_branch_name(branch1); + branch2 = better_branch_name(branch2); + printf("Merging %s with %s\n", branch1, branch2); + if (bases_count == 1) { struct commit *ancestor = get_ref(bases[0]); clean = merge(h1, h2, branch1, branch2, 0, ancestor, &result);