Merge branch 'js/merge-base-with-missing-commit'
Make sure failure return from merge_bases_many() is properly caught. * js/merge-base-with-missing-commit: merge-ort/merge-recursive: do report errors in `merge_submodule()` merge-recursive: prepare for `merge_submodule()` to report errors commit-reach(repo_get_merge_bases_many_dirty): pass on errors commit-reach(repo_get_merge_bases_many): pass on "missing commits" errors commit-reach(get_octopus_merge_bases): pass on "missing commits" errors commit-reach(repo_get_merge_bases): pass on "missing commits" errors commit-reach(get_merge_bases_many_0): pass on "missing commits" errors commit-reach(merge_bases_many): pass on "missing commits" errors commit-reach(paint_down_to_common): start reporting errors commit-reach(paint_down_to_common): prepare for handling shallow commits commit-reach(repo_in_merge_bases_many): report missing commits commit-reach(repo_in_merge_bases_many): optionally expect missing commits commit-reach(paint_down_to_common): plug two memory leaks
This commit is contained in:
@ -1140,7 +1140,13 @@ 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)
|
||||
add_object_array(o, NULL, &merges);
|
||||
}
|
||||
reset_revision_walk();
|
||||
@ -1155,9 +1161,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1193,7 +1207,7 @@ static int merge_submodule(struct merge_options *opt,
|
||||
const struct object_id *b)
|
||||
{
|
||||
struct repository subrepo;
|
||||
int ret = 0;
|
||||
int ret = 0, ret2;
|
||||
struct commit *commit_base, *commit_a, *commit_b;
|
||||
int parent_count;
|
||||
struct object_array merges;
|
||||
@ -1230,14 +1244,32 @@ static int merge_submodule(struct merge_options *opt,
|
||||
}
|
||||
|
||||
/* check whether both changes are forward */
|
||||
if (!repo_in_merge_bases(&subrepo, commit_base, commit_a) ||
|
||||
!repo_in_merge_bases(&subrepo, commit_base, commit_b)) {
|
||||
ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_a);
|
||||
if (ret2 < 0) {
|
||||
output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (ret2 > 0)
|
||||
ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_b);
|
||||
if (ret2 < 0) {
|
||||
output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (!ret2) {
|
||||
output(opt, 1, _("Failed to merge submodule %s (commits don't follow merge-base)"), path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (ret2) {
|
||||
oidcpy(result, b);
|
||||
if (show(opt, 3)) {
|
||||
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
|
||||
@ -1250,7 +1282,13 @@ 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) {
|
||||
output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (ret2) {
|
||||
oidcpy(result, a);
|
||||
if (show(opt, 3)) {
|
||||
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
|
||||
@ -1279,6 +1317,10 @@ static int merge_submodule(struct merge_options *opt,
|
||||
parent_count = find_first_merges(&subrepo, &merges, path,
|
||||
commit_a, commit_b);
|
||||
switch (parent_count) {
|
||||
case -1:
|
||||
output(opt, 1,_("Failed to merge submodule %s (repository corrupt)"), path);
|
||||
ret = -1;
|
||||
break;
|
||||
case 0:
|
||||
output(opt, 1, _("Failed to merge submodule %s (merge following commits not found)"), path);
|
||||
break;
|
||||
@ -1393,11 +1435,14 @@ static int merge_mode_and_contents(struct merge_options *opt,
|
||||
/* FIXME: bug, what if modes didn't match? */
|
||||
result->clean = (merge_status == 0);
|
||||
} else if (S_ISGITLINK(a->mode)) {
|
||||
result->clean = merge_submodule(opt, &result->blob.oid,
|
||||
o->path,
|
||||
&o->oid,
|
||||
&a->oid,
|
||||
&b->oid);
|
||||
int clean = merge_submodule(opt, &result->blob.oid,
|
||||
o->path,
|
||||
&o->oid,
|
||||
&a->oid,
|
||||
&b->oid);
|
||||
if (clean < 0)
|
||||
return -1;
|
||||
result->clean = clean;
|
||||
} else if (S_ISLNK(a->mode)) {
|
||||
switch (opt->recursive_variant) {
|
||||
case MERGE_VARIANT_NORMAL:
|
||||
@ -3598,7 +3643,9 @@ static int merge_recursive_internal(struct merge_options *opt,
|
||||
}
|
||||
|
||||
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)
|
||||
return -1;
|
||||
merge_bases = reverse_commit_list(merge_bases);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user