X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=merge-recursive.c;h=cd3628c4d9b1831c73e752b3b49c9d88b9e23098;hb=34f3999206e8ea41b9e4cf48e30ab1149e01d8a5;hp=9bf5cc71754df1df29057822cf16bbfe51579d37;hpb=891182f9141326fd6833d3651b89860a0b41f153;p=git.git diff --git a/merge-recursive.c b/merge-recursive.c index 9bf5cc717..cd3628c4d 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" @@ -38,7 +39,7 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two) * A virtual commit has (const char *)commit->util set to the name. */ -struct commit *make_virtual_commit(struct tree *tree, const char *comment) +static struct commit *make_virtual_commit(struct tree *tree, const char *comment) { struct commit *commit = xcalloc(1, sizeof(struct commit)); commit->tree = tree; @@ -181,6 +182,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); @@ -438,7 +440,7 @@ static void flush_buffer(int fd, const char *buf, unsigned long size) /* Ignore epipe */ if (errno == EPIPE) break; - die("merge-recursive: %s", strerror(errno)); + die_errno("merge-recursive"); } else if (!ret) { die("merge-recursive: disk full?"); } @@ -520,8 +522,12 @@ static void update_file_flags(struct merge_options *o, unsigned long size; if (S_ISGITLINK(mode)) - die("cannot read object %s '%s': It is a submodule!", - sha1_to_hex(sha), path); + /* + * We may later decide to recursively descend into + * the submodule directory and update its index + * and/or work tree, but we do not do that now. + */ + goto update_index; buf = read_sha1_file(sha, &type, &size); if (!buf) @@ -550,7 +556,7 @@ static void update_file_flags(struct merge_options *o, mode = 0666; fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); if (fd < 0) - die("failed to open %s: %s", path, strerror(errno)); + die_errno("failed to open '%s'", path); flush_buffer(fd, buf, size); close(fd); } else if (S_ISLNK(mode)) { @@ -558,7 +564,7 @@ static void update_file_flags(struct merge_options *o, safe_create_leading_directories_const(path); unlink(path); if (symlink(lnk, path)) - die("failed to symlink %s: %s", path, strerror(errno)); + die_errno("failed to symlink '%s'", path); free(lnk); } else die("do not know what to do with %06o %s '%s'", @@ -618,8 +624,13 @@ static int merge_3way(struct merge_options *o, char *name1, *name2; int merge_status; - name1 = xstrdup(mkpath("%s:%s", branch1, a->path)); - name2 = xstrdup(mkpath("%s:%s", branch2, b->path)); + if (strcmp(a->path, b->path)) { + name1 = xstrdup(mkpath("%s:%s", branch1, a->path)); + name2 = xstrdup(mkpath("%s:%s", branch2, b->path)); + } else { + name1 = xstrdup(mkpath("%s", branch1)); + name2 = xstrdup(mkpath("%s", branch2)); + } fill_mm(one->sha1, &orig); fill_mm(a->sha1, &src1); @@ -801,22 +812,19 @@ static int process_renames(struct merge_options *o, } for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) { - int compare; char *src; - struct string_list *renames1, *renames2, *renames2Dst; + struct string_list *renames1, *renames2Dst; struct rename *ren1 = NULL, *ren2 = NULL; const char *branch1, *branch2; const char *ren1_src, *ren1_dst; if (i >= a_renames->nr) { - compare = 1; ren2 = b_renames->items[j++].util; } else if (j >= b_renames->nr) { - compare = -1; ren1 = a_renames->items[i++].util; } else { - compare = strcmp(a_renames->items[i].string, - b_renames->items[j].string); + int compare = strcmp(a_renames->items[i].string, + b_renames->items[j].string); if (compare <= 0) ren1 = a_renames->items[i++].util; if (compare >= 0) @@ -826,14 +834,12 @@ static int process_renames(struct merge_options *o, /* TODO: refactor, so that 1/2 are not needed */ if (ren1) { renames1 = a_renames; - renames2 = b_renames; renames2Dst = &b_by_dst; branch1 = o->branch1; branch2 = o->branch2; } else { struct rename *tmp; renames1 = b_renames; - renames2 = a_renames; renames2Dst = &a_by_dst; branch1 = o->branch2; branch2 = o->branch1; @@ -934,11 +940,12 @@ static int process_renames(struct merge_options *o, ren1_src, ren1_dst, branch1, branch2); update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst); - update_stages(ren1_dst, NULL, - branch1 == o->branch1 ? - ren1->pair->two : NULL, - branch1 == o->branch1 ? - NULL : ren1->pair->two, 1); + if (!o->call_depth) + update_stages(ren1_dst, NULL, + branch1 == o->branch1 ? + ren1->pair->two : NULL, + branch1 == o->branch1 ? + NULL : ren1->pair->two, 1); } else if (!sha_eq(dst_other.sha1, null_sha1)) { const char *new_path; clean_merge = 0; @@ -947,9 +954,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; @@ -1140,6 +1169,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, @@ -1161,10 +1212,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;