X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=merge-recursive.c;h=cb53b01c19159e66ef265bde7feceabebab42232;hb=cab1b013e6f7cc52806926a792c6798f4c7ac4be;hp=d415c4188d181fbdc765fff90fbbc4897ced53ad;hpb=00d3278c8534a8244ae3447189401111e017fd5d;p=git.git diff --git a/merge-recursive.c b/merge-recursive.c index d415c4188..cb53b01c1 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -3,6 +3,7 @@ * Fredrik Kuivinen. * The thieves were Alex Riesen and Johannes Schindelin, in June/July 2006 */ +#include "advice.h" #include "cache.h" #include "cache-tree.h" #include "commit.h" @@ -20,15 +21,17 @@ #include "merge-recursive.h" #include "dir.h" -static struct tree *shift_tree_object(struct tree *one, struct tree *two) +static struct tree *shift_tree_object(struct tree *one, struct tree *two, + const char *subtree_shift) { unsigned char shifted[20]; - /* - * NEEDSWORK: this limits the recursion depth to hardcoded - * value '2' to avoid excessive overhead. - */ - shift_tree(one->object.sha1, two->object.sha1, shifted, 2); + if (!*subtree_shift) { + shift_tree(one->object.sha1, two->object.sha1, shifted, 0); + } else { + shift_tree_by(one->object.sha1, two->object.sha1, shifted, + subtree_shift); + } if (!hashcmp(two->object.sha1, shifted)) return two; return lookup_tree(shifted); @@ -86,6 +89,7 @@ static void flush_output(struct merge_options *o) } } +__attribute__((format (printf, 3, 4))) static void output(struct merge_options *o, int v, const char *fmt, ...) { int len; @@ -181,6 +185,7 @@ static int git_merge_trees(int index_only, opts.fn = threeway_merge; opts.src_index = &the_index; opts.dst_index = &the_index; + opts.msgs = get_porcelain_error_msgs(); init_tree_desc_from_tree(t+0, common); init_tree_desc_from_tree(t+1, head); @@ -197,13 +202,14 @@ struct tree *write_tree_from_memory(struct merge_options *o) if (unmerged_cache()) { int i; - output(o, 0, "There are unmerged index entries:"); + fprintf(stderr, "BUG: There are unmerged index entries:\n"); for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; if (ce_stage(ce)) - output(o, 0, "%d %.*s", ce_stage(ce), ce_namelen(ce), ce->name); + fprintf(stderr, "BUG: %d %.*s", ce_stage(ce), + (int)ce_namelen(ce), ce->name); } - return NULL; + die("Bug in merge-recursive.c"); } if (!active_cache_tree) @@ -621,6 +627,23 @@ static int merge_3way(struct merge_options *o, mmfile_t orig, src1, src2; char *name1, *name2; int merge_status; + int favor; + + if (o->call_depth) + favor = 0; + else { + switch (o->recursive_variant) { + case MERGE_RECURSIVE_OURS: + favor = XDL_MERGE_FAVOR_OURS; + break; + case MERGE_RECURSIVE_THEIRS: + favor = XDL_MERGE_FAVOR_THEIRS; + break; + default: + favor = 0; + break; + } + } if (strcmp(a->path, b->path)) { name1 = xstrdup(mkpath("%s:%s", branch1, a->path)); @@ -636,7 +659,7 @@ static int merge_3way(struct merge_options *o, merge_status = ll_merge(result_buf, a->path, &orig, &src1, name1, &src2, name2, - o->call_depth); + (!!o->call_depth) | (favor << 1)); free(name1); free(name2); @@ -952,9 +975,31 @@ static int process_renames(struct merge_options *o, "%s added in %s", ren1_src, ren1_dst, branch1, ren1_dst, branch2); - new_path = unique_path(o, ren1_dst, branch2); - output(o, 1, "Adding as %s instead", new_path); - update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); + if (o->call_depth) { + struct merge_file_info mfi; + struct diff_filespec one, a, b; + + one.path = a.path = b.path = + (char *)ren1_dst; + hashcpy(one.sha1, null_sha1); + one.mode = 0; + hashcpy(a.sha1, ren1->pair->two->sha1); + a.mode = ren1->pair->two->mode; + hashcpy(b.sha1, dst_other.sha1); + b.mode = dst_other.mode; + mfi = merge_file(o, &one, &a, &b, + branch1, + branch2); + output(o, 1, "Adding merged %s", ren1_dst); + update_file(o, 0, + mfi.sha, + mfi.mode, + ren1_dst); + } else { + new_path = unique_path(o, ren1_dst, branch2); + output(o, 1, "Adding as %s instead", new_path); + update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); + } } else if ((item = string_list_lookup(ren1_dst, renames2Dst))) { ren2 = item->util; clean_merge = 0; @@ -1145,6 +1190,28 @@ static int process_entry(struct merge_options *o, return clean_merge; } +struct unpack_trees_error_msgs get_porcelain_error_msgs(void) +{ + struct unpack_trees_error_msgs msgs = { + /* would_overwrite */ + "Your local changes to '%s' would be overwritten by merge. Aborting.", + /* not_uptodate_file */ + "Your local changes to '%s' would be overwritten by merge. Aborting.", + /* not_uptodate_dir */ + "Updating '%s' would lose untracked files in it. Aborting.", + /* would_lose_untracked */ + "Untracked working tree file '%s' would be %s by merge. Aborting", + /* bind_overlap -- will not happen here */ + NULL, + }; + if (advice_commit_before_merge) { + msgs.would_overwrite = msgs.not_uptodate_file = + "Your local changes to '%s' would be overwritten by merge. Aborting.\n" + "Please, commit your changes or stash them before you can merge."; + } + return msgs; +} + int merge_trees(struct merge_options *o, struct tree *head, struct tree *merge, @@ -1153,9 +1220,9 @@ int merge_trees(struct merge_options *o, { int code, clean; - if (o->subtree_merge) { - merge = shift_tree_object(head, merge); - common = shift_tree_object(head, common); + if (o->subtree_shift) { + merge = shift_tree_object(head, merge, o->subtree_shift); + common = shift_tree_object(head, common, o->subtree_shift); } if (sha_eq(common->object.sha1, merge->object.sha1)) { @@ -1166,10 +1233,14 @@ int merge_trees(struct merge_options *o, code = git_merge_trees(o->call_depth, common, head, merge); - if (code != 0) - die("merging of trees %s and %s failed", - sha1_to_hex(head->object.sha1), - sha1_to_hex(merge->object.sha1)); + if (code != 0) { + if (show(o, 4) || o->call_depth) + die("merging of trees %s and %s failed", + sha1_to_hex(head->object.sha1), + sha1_to_hex(merge->object.sha1)); + else + exit(128); + } if (unmerged_cache()) { struct string_list *entries, *re_head, *re_merge;