diff options
Diffstat (limited to 'merge-recursive.c')
-rw-r--r-- | merge-recursive.c | 142 |
1 files changed, 74 insertions, 68 deletions
diff --git a/merge-recursive.c b/merge-recursive.c index cb53b01c19..656e769b44 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -136,16 +136,10 @@ static void output_commit_title(struct merge_options *o, struct commit *commit) if (parse_commit(commit) != 0) printf("(bad commit)\n"); else { - const char *s; - int len; - for (s = commit->buffer; *s; s++) - if (*s == '\n' && s[1] == '\n') { - s += 2; - break; - } - for (len = 0; s[len] && '\n' != s[len]; len++) - ; /* do nothing */ - printf("%.*s\n", len, s); + const char *title; + int len = find_commit_subject(commit->buffer, &title); + if (len) + printf("%.*s\n", len, title); } } } @@ -185,7 +179,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(); + set_porcelain_error_msgs(opts.msgs, "merge"); init_tree_desc_from_tree(t+0, common); init_tree_desc_from_tree(t+1, head); @@ -238,9 +232,9 @@ static int save_files_dirs(const unsigned char *sha1, newpath[baselen + len] = '\0'; if (S_ISDIR(mode)) - string_list_insert(newpath, &o->current_directory_set); + string_list_insert(&o->current_directory_set, newpath); else - string_list_insert(newpath, &o->current_file_set); + string_list_insert(&o->current_file_set, newpath); free(newpath); return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0); @@ -271,7 +265,7 @@ static struct stage_data *insert_stage_data(const char *path, e->stages[2].sha, &e->stages[2].mode); get_tree_entry(b->object.sha1, path, e->stages[3].sha, &e->stages[3].mode); - item = string_list_insert(path, entries); + item = string_list_insert(entries, path); item->util = e; return e; } @@ -294,9 +288,9 @@ static struct string_list *get_unmerged(void) if (!ce_stage(ce)) continue; - item = string_list_lookup(ce->name, unmerged); + item = string_list_lookup(unmerged, ce->name); if (!item) { - item = string_list_insert(ce->name, unmerged); + item = string_list_insert(unmerged, ce->name); item->util = xcalloc(1, sizeof(struct stage_data)); } e = item->util; @@ -356,20 +350,20 @@ static struct string_list *get_renames(struct merge_options *o, re = xmalloc(sizeof(*re)); re->processed = 0; re->pair = pair; - item = string_list_lookup(re->pair->one->path, entries); + item = string_list_lookup(entries, re->pair->one->path); if (!item) re->src_entry = insert_stage_data(re->pair->one->path, o_tree, a_tree, b_tree, entries); else re->src_entry = item->util; - item = string_list_lookup(re->pair->two->path, entries); + item = string_list_lookup(entries, re->pair->two->path); if (!item) re->dst_entry = insert_stage_data(re->pair->two->path, o_tree, a_tree, b_tree, entries); else re->dst_entry = item->util; - item = string_list_insert(pair->one->path, renames); + item = string_list_insert(renames, pair->one->path); item->util = re; } opts.output_format = DIFF_FORMAT_NO_OUTPUT; @@ -409,7 +403,7 @@ static int remove_file(struct merge_options *o, int clean, return -1; } if (update_working_directory) { - if (remove_path(path) && errno != ENOENT) + if (remove_path(path)) return -1; } return 0; @@ -432,7 +426,7 @@ static char *unique_path(struct merge_options *o, const char *path, const char * lstat(newpath, &st) == 0) sprintf(p, "_%d", suffix++); - string_list_insert(newpath, &o->current_file_set); + string_list_insert(&o->current_file_set, newpath); return newpath; } @@ -599,23 +593,6 @@ struct merge_file_info merge:1; }; -static void fill_mm(const unsigned char *sha1, mmfile_t *mm) -{ - unsigned long size; - enum object_type type; - - if (!hashcmp(sha1, null_sha1)) { - mm->ptr = xstrdup(""); - mm->size = 0; - return; - } - - mm->ptr = read_sha1_file(sha1, &type, &size); - if (!mm->ptr || type != OBJ_BLOB) - die("unable to read blob object %s", sha1_to_hex(sha1)); - mm->size = size; -} - static int merge_3way(struct merge_options *o, mmbuffer_t *result_buf, struct diff_filespec *one, @@ -625,7 +602,7 @@ static int merge_3way(struct merge_options *o, const char *branch2) { mmfile_t orig, src1, src2; - char *name1, *name2; + char *base_name, *name1, *name2; int merge_status; int favor; @@ -645,19 +622,24 @@ static int merge_3way(struct merge_options *o, } } - if (strcmp(a->path, b->path)) { + if (strcmp(a->path, b->path) || + (o->ancestor != NULL && strcmp(a->path, one->path) != 0)) { + base_name = o->ancestor == NULL ? NULL : + xstrdup(mkpath("%s:%s", o->ancestor, one->path)); name1 = xstrdup(mkpath("%s:%s", branch1, a->path)); name2 = xstrdup(mkpath("%s:%s", branch2, b->path)); } else { + base_name = o->ancestor == NULL ? NULL : + xstrdup(mkpath("%s", o->ancestor)); name1 = xstrdup(mkpath("%s", branch1)); name2 = xstrdup(mkpath("%s", branch2)); } - fill_mm(one->sha1, &orig); - fill_mm(a->sha1, &src1); - fill_mm(b->sha1, &src2); + read_mmblob(&orig, one->sha1); + read_mmblob(&src1, a->sha1); + read_mmblob(&src2, b->sha1); - merge_status = ll_merge(result_buf, a->path, &orig, + merge_status = ll_merge(result_buf, a->path, &orig, base_name, &src1, name1, &src2, name2, (!!o->call_depth) | (favor << 1)); @@ -818,17 +800,18 @@ static int process_renames(struct merge_options *o, struct string_list *b_renames) { int clean_merge = 1, i, j; - struct string_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0}; + struct string_list a_by_dst = STRING_LIST_INIT_NODUP; + struct string_list b_by_dst = STRING_LIST_INIT_NODUP; const struct rename *sre; for (i = 0; i < a_renames->nr; i++) { sre = a_renames->items[i].util; - string_list_insert(sre->pair->two->path, &a_by_dst)->util + string_list_insert(&a_by_dst, sre->pair->two->path)->util = sre->dst_entry; } for (i = 0; i < b_renames->nr; i++) { sre = b_renames->items[i].util; - string_list_insert(sre->pair->two->path, &b_by_dst)->util + string_list_insert(&b_by_dst, sre->pair->two->path)->util = sre->dst_entry; } @@ -1000,7 +983,7 @@ static int process_renames(struct merge_options *o, 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))) { + } else if ((item = string_list_lookup(renames2Dst, ren1_dst))) { ren2 = item->util; clean_merge = 0; ren2->processed = 1; @@ -1190,26 +1173,48 @@ static int process_entry(struct merge_options *o, return clean_merge; } -struct unpack_trees_error_msgs get_porcelain_error_msgs(void) +void set_porcelain_error_msgs(const char **msgs, const char *cmd) { - 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; + const char *msg; + char *tmp; + const char *cmd2 = strcmp(cmd, "checkout") ? cmd : "switch branches"; + if (advice_commit_before_merge) + msg = "Your local changes to the following files would be overwritten by %s:\n%%s" + "Please, commit your changes or stash them before you can %s."; + else + msg = "Your local changes to the following files would be overwritten by %s:\n%%s"; + tmp = xmalloc(strlen(msg) + strlen(cmd) + strlen(cmd2) - 2); + sprintf(tmp, msg, cmd, cmd2); + msgs[ERROR_WOULD_OVERWRITE] = tmp; + msgs[ERROR_NOT_UPTODATE_FILE] = tmp; + + msgs[ERROR_NOT_UPTODATE_DIR] = + "Updating the following directories would lose untracked files in it:\n%s"; + + if (advice_commit_before_merge) + msg = "The following untracked working tree files would be %s by %s:\n%%s" + "Please move or remove them before you can %s."; + else + msg = "The following untracked working tree files would be %s by %s:\n%%s"; + tmp = xmalloc(strlen(msg) + strlen(cmd) + strlen("removed") + strlen(cmd2) - 4); + sprintf(tmp, msg, "removed", cmd, cmd2); + msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] = tmp; + tmp = xmalloc(strlen(msg) + strlen(cmd) + strlen("overwritten") + strlen(cmd2) - 4); + sprintf(tmp, msg, "overwritten", cmd, cmd2); + msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] = tmp; + + /* + * Special case: ERROR_BIND_OVERLAP refers to a pair of paths, we + * cannot easily display it as a list. + */ + msgs[ERROR_BIND_OVERLAP] = "Entry '%s' overlaps with '%s'. Cannot bind."; + + msgs[ERROR_SPARSE_NOT_UPTODATE_FILE] = + "Cannot update sparse checkout: the following entries are not up-to-date:\n%s"; + msgs[ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN] = + "The following Working tree files would be overwritten by sparse checkout update:\n%s"; + msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] = + "The following Working tree files would be removed by sparse checkout update:\n%s"; } int merge_trees(struct merge_options *o, @@ -1226,7 +1231,7 @@ int merge_trees(struct merge_options *o, } if (sha_eq(common->object.sha1, merge->object.sha1)) { - output(o, 0, "Already uptodate!"); + output(o, 0, "Already up-to-date!"); *result = head; return 1; } @@ -1359,6 +1364,7 @@ int merge_recursive(struct merge_options *o, if (!o->call_depth) read_cache(); + o->ancestor = "merged common ancestors"; clean = merge_trees(o, h1->tree, h2->tree, merged_common_ancestors->tree, &mrtree); |