diff options
Diffstat (limited to '')
-rw-r--r-- | merge-ort.c | 149 |
1 files changed, 115 insertions, 34 deletions
diff --git a/merge-ort.c b/merge-ort.c index 6491070..eaede6c 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -18,8 +18,8 @@ #include "merge-ort.h" #include "alloc.h" +#include "advice.h" #include "attr.h" -#include "blob.h" #include "cache-tree.h" #include "commit.h" #include "commit-reach.h" @@ -39,11 +39,10 @@ #include "path.h" #include "promisor-remote.h" #include "read-cache-ll.h" +#include "refs.h" #include "revision.h" #include "sparse-index.h" #include "strmap.h" -#include "submodule-config.h" -#include "submodule.h" #include "trace2.h" #include "tree.h" #include "unpack-trees.h" @@ -544,6 +543,7 @@ enum conflict_and_info_types { CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, CONFLICT_SUBMODULE_NULL_MERGE_BASE, + CONFLICT_SUBMODULE_CORRUPT, /* Keep this entry _last_ in the list */ NB_CONFLICT_TYPES, @@ -596,7 +596,9 @@ static const char *type_short_descriptions[] = { [CONFLICT_SUBMODULE_MAY_HAVE_REWINDS] = "CONFLICT (submodule may have rewinds)", [CONFLICT_SUBMODULE_NULL_MERGE_BASE] = - "CONFLICT (submodule lacks merge base)" + "CONFLICT (submodule lacks merge base)", + [CONFLICT_SUBMODULE_CORRUPT] = + "CONFLICT (submodule corrupt)" }; struct logical_conflict_info { @@ -1659,12 +1661,14 @@ static int collect_merge_info(struct merge_options *opt, info.data = opt; info.show_all_errors = 1; - parse_tree(merge_base); - parse_tree(side1); - parse_tree(side2); - init_tree_desc(t + 0, merge_base->buffer, merge_base->size); - init_tree_desc(t + 1, side1->buffer, side1->size); - init_tree_desc(t + 2, side2->buffer, side2->size); + if (parse_tree(merge_base) < 0 || + parse_tree(side1) < 0 || + parse_tree(side2) < 0) + return -1; + init_tree_desc(t + 0, &merge_base->object.oid, + merge_base->buffer, merge_base->size); + init_tree_desc(t + 1, &side1->object.oid, side1->buffer, side1->size); + init_tree_desc(t + 2, &side2->object.oid, side2->buffer, side2->size); trace2_region_enter("merge", "traverse_trees", opt->repo); ret = traverse_trees(NULL, 3, t, &info); @@ -1710,7 +1714,14 @@ static int find_first_merges(struct repository *repo, die("revision walk setup failed"); while ((commit = get_revision(&revs)) != NULL) { struct object *o = &(commit->object); - if (repo_in_merge_bases(repo, b, commit)) + int ret = repo_in_merge_bases(repo, b, commit); + + if (ret < 0) { + object_array_clear(&merges); + release_revisions(&revs); + return ret; + } + if (ret > 0) add_object_array(o, NULL, &merges); } reset_revision_walk(); @@ -1725,9 +1736,17 @@ static int find_first_merges(struct repository *repo, contains_another = 0; for (j = 0; j < merges.nr; j++) { struct commit *m2 = (struct commit *) merges.objects[j].item; - if (i != j && repo_in_merge_bases(repo, m2, m1)) { - contains_another = 1; - break; + if (i != j) { + int ret = repo_in_merge_bases(repo, m2, m1); + if (ret < 0) { + object_array_clear(&merges); + release_revisions(&revs); + return ret; + } + if (ret > 0) { + contains_another = 1; + break; + } } } @@ -1749,7 +1768,7 @@ static int merge_submodule(struct merge_options *opt, { struct repository subrepo; struct strbuf sb = STRBUF_INIT; - int ret = 0; + int ret = 0, ret2; struct commit *commit_o, *commit_a, *commit_b; int parent_count; struct object_array merges; @@ -1796,8 +1815,28 @@ static int merge_submodule(struct merge_options *opt, } /* check whether both changes are forward */ - if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) || - !repo_in_merge_bases(&subrepo, commit_o, commit_b)) { + ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_a); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (ret2 > 0) + ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_b); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (!ret2) { path_msg(opt, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, 0, path, NULL, NULL, NULL, _("Failed to merge submodule %s " @@ -1807,7 +1846,17 @@ static int merge_submodule(struct merge_options *opt, } /* Case #1: a is contained in b or vice versa */ - if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) { + ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (ret2 > 0) { oidcpy(result, b); path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1, path, NULL, NULL, NULL, @@ -1816,7 +1865,17 @@ static int merge_submodule(struct merge_options *opt, ret = 1; goto cleanup; } - if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) { + ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (ret2 > 0) { oidcpy(result, a); path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1, path, NULL, NULL, NULL, @@ -1841,6 +1900,14 @@ static int merge_submodule(struct merge_options *opt, parent_count = find_first_merges(&subrepo, path, commit_a, commit_b, &merges); switch (parent_count) { + case -1: + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + break; case 0: path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE, 0, path, NULL, NULL, NULL, @@ -1958,7 +2025,7 @@ static int merge_3way(struct merge_options *opt, mmbuffer_t *result_buf) { mmfile_t orig, src1, src2; - struct ll_merge_options ll_opts = {0}; + struct ll_merge_options ll_opts = LL_MERGE_OPTIONS_INIT; char *base, *name1, *name2; enum ll_merge_result merge_status; @@ -1968,6 +2035,7 @@ static int merge_3way(struct merge_options *opt, ll_opts.renormalize = opt->renormalize; ll_opts.extra_marker_size = extra_marker_size; ll_opts.xdl_opts = opt->xdl_opts; + ll_opts.conflict_style = opt->conflict_style; if (opt->priv->call_depth) { ll_opts.virtual_ancestor = 1; @@ -2644,7 +2712,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt, oidcpy(&ci->stages[i].oid, null_oid()); } - // Now we want to focus on new_ci, so reassign ci to it + /* Now we want to focus on new_ci, so reassign ci to it. */ ci = new_ci; } @@ -4378,10 +4446,12 @@ static int checkout(struct merge_options *opt, unpack_opts.verbose_update = (opt->verbosity > 2); unpack_opts.fn = twoway_merge; unpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */ - parse_tree(prev); - init_tree_desc(&trees[0], prev->buffer, prev->size); - parse_tree(next); - init_tree_desc(&trees[1], next->buffer, next->size); + if (parse_tree(prev) < 0) + return -1; + init_tree_desc(&trees[0], &prev->object.oid, prev->buffer, prev->size); + if (parse_tree(next) < 0) + return -1; + init_tree_desc(&trees[1], &next->object.oid, next->buffer, next->size); ret = unpack_trees(2, trees, &unpack_opts); clear_unpack_trees_porcelain(&unpack_opts); @@ -4558,7 +4628,7 @@ static void print_submodule_conflict_suggestion(struct string_list *csub) { " - commit the resulting index in the superproject\n"), tmp.buf, subs.buf); - printf("%s", msg.buf); + advise_if_enabled(ADVICE_SUBMODULE_MERGE_CONFLICT, "%s", msg.buf); strbuf_release(&subs); strbuf_release(&tmp); @@ -4662,9 +4732,6 @@ void merge_switch_to_result(struct merge_options *opt, { assert(opt->priv == NULL); if (result->clean >= 0 && update_worktree_and_index) { - const char *filename; - FILE *fp; - trace2_region_enter("merge", "checkout", opt->repo); if (checkout(opt, head, result->tree)) { /* failure to function */ @@ -4690,10 +4757,17 @@ void merge_switch_to_result(struct merge_options *opt, trace2_region_leave("merge", "record_conflicted", opt->repo); trace2_region_enter("merge", "write_auto_merge", opt->repo); - filename = git_path_auto_merge(opt->repo); - fp = xfopen(filename, "w"); - fprintf(fp, "%s\n", oid_to_hex(&result->tree->object.oid)); - fclose(fp); + if (refs_update_ref(get_main_ref_store(opt->repo), "", "AUTO_MERGE", + &result->tree->object.oid, NULL, REF_NO_DEREF, + UPDATE_REFS_MSG_ON_ERR)) { + /* failure to function */ + opt->priv = NULL; + result->clean = -1; + merge_finalize(opt, result); + trace2_region_leave("merge", "write_auto_merge", + opt->repo); + return; + } trace2_region_leave("merge", "write_auto_merge", opt->repo); } if (display_update_msgs) @@ -4980,6 +5054,9 @@ redo: if (result->clean >= 0) { result->tree = parse_tree_indirect(&working_tree_oid); + if (!result->tree) + die(_("unable to read tree (%s)"), + oid_to_hex(&working_tree_oid)); /* existence of conflicted entries implies unclean */ result->clean &= strmap_empty(&opt->priv->conflicted); } @@ -5005,7 +5082,11 @@ static void merge_ort_internal(struct merge_options *opt, struct strbuf merge_base_abbrev = STRBUF_INIT; if (!merge_bases) { - merge_bases = repo_get_merge_bases(the_repository, h1, h2); + if (repo_get_merge_bases(the_repository, h1, h2, + &merge_bases) < 0) { + result->clean = -1; + return; + } /* See merge-ort.h:merge_incore_recursive() declaration NOTE */ merge_bases = reverse_commit_list(merge_bases); } |