]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'js/merge-base-with-missing-commit'
authorJunio C Hamano <gitster@pobox.com>
Mon, 11 Mar 2024 21:12:30 +0000 (14:12 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 11 Mar 2024 21:12:30 +0000 (14:12 -0700)
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

12 files changed:
1  2 
builtin/fetch.c
builtin/merge-tree.c
builtin/merge.c
builtin/rebase.c
merge-ort.c
merge-recursive.c
object-name.c
remote.c
revision.c
sequencer.c
submodule.c
t/t4301-merge-tree-write-tree.sh

diff --cc builtin/fetch.c
Simple merge
Simple merge
diff --cc builtin/merge.c
Simple merge
Simple merge
diff --cc merge-ort.c
Simple merge
Simple merge
diff --cc object-name.c
Simple merge
diff --cc remote.c
Simple merge
diff --cc revision.c
index 6f8ebc762e8dcc214de6378d91c87529bf6f8bb0,60406f365a92b56b278489f6630f3cd89020a7b0..45893651c22f2669da8d5fe38a0b809e650d6f6d
@@@ -1971,31 -1961,11 +1971,31 @@@ static void add_pending_commit_list(str
        }
  }
  
 +static const char *lookup_other_head(struct object_id *oid)
 +{
 +      int i;
 +      static const char *const other_head[] = {
 +              "MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "REBASE_HEAD"
 +      };
 +
 +      for (i = 0; i < ARRAY_SIZE(other_head); i++)
 +              if (!read_ref_full(other_head[i],
 +                              RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
 +                              oid, NULL)) {
 +                      if (is_null_oid(oid))
 +                              die(_("%s exists but is a symbolic ref"), other_head[i]);
 +                      return other_head[i];
 +              }
 +
 +      die(_("--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD or REBASE_HEAD"));
 +}
 +
  static void prepare_show_merge(struct rev_info *revs)
  {
-       struct commit_list *bases;
+       struct commit_list *bases = NULL;
        struct commit *head, *other;
        struct object_id oid;
 +      const char *other_name;
        const char **prune = NULL;
        int i, prune_num = 1; /* counting terminating NULL */
        struct index_state *istate = revs->repo->index;
        if (repo_get_oid(the_repository, "HEAD", &oid))
                die("--merge without HEAD?");
        head = lookup_commit_or_die(&oid, "HEAD");
 -      if (repo_get_oid(the_repository, "MERGE_HEAD", &oid))
 -              die("--merge without MERGE_HEAD?");
 -      other = lookup_commit_or_die(&oid, "MERGE_HEAD");
 +      other_name = lookup_other_head(&oid);
 +      other = lookup_commit_or_die(&oid, other_name);
        add_pending_object(revs, &head->object, "HEAD");
 -      add_pending_object(revs, &other->object, "MERGE_HEAD");
 +      add_pending_object(revs, &other->object, other_name);
-       bases = repo_get_merge_bases(the_repository, head, other);
+       if (repo_get_merge_bases(the_repository, head, other, &bases) < 0)
+               exit(128);
        add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
        add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
        free_commit_list(bases);
diff --cc sequencer.c
Simple merge
diff --cc submodule.c
Simple merge
index d83c1d172dd2626578bb9b0918f6856f91d17ed4,eb02766c9a62e5bc9446ad0d71f7267e19d71180..29e9974cdfd421f6fb7dd17fa2bb12db8d5d6e04
@@@ -945,37 -945,16 +945,49 @@@ test_expect_success 'check the input fo
        test_cmp expect actual
  '
  
 +test_expect_success '--merge-base with tree OIDs' '
 +      git merge-tree --merge-base=side1^ side1 side3 >with-commits &&
 +      git merge-tree --merge-base=side1^^{tree} side1^{tree} side3^{tree} >with-trees &&
 +      test_cmp with-commits with-trees
 +'
 +
 +test_expect_success 'error out on missing tree objects' '
 +      git init --bare missing-tree.git &&
 +      git rev-list side3 >list &&
 +      git rev-parse side3^: >>list &&
 +      git pack-objects missing-tree.git/objects/pack/side3-tree-is-missing <list &&
 +      side3=$(git rev-parse side3) &&
 +      test_must_fail git --git-dir=missing-tree.git merge-tree $side3^ $side3 >actual 2>err &&
 +      test_grep "Could not read $(git rev-parse $side3:)" err &&
 +      test_must_be_empty actual
 +'
 +
 +test_expect_success 'error out on missing blob objects' '
 +      echo 1 | git hash-object -w --stdin >blob1 &&
 +      echo 2 | git hash-object -w --stdin >blob2 &&
 +      echo 3 | git hash-object -w --stdin >blob3 &&
 +      printf "100644 blob $(cat blob1)\tblob\n" | git mktree >tree1 &&
 +      printf "100644 blob $(cat blob2)\tblob\n" | git mktree >tree2 &&
 +      printf "100644 blob $(cat blob3)\tblob\n" | git mktree >tree3 &&
 +      git init --bare missing-blob.git &&
 +      cat blob1 blob3 tree1 tree2 tree3 |
 +      git pack-objects missing-blob.git/objects/pack/side1-whatever-is-missing &&
 +      test_must_fail git --git-dir=missing-blob.git >actual 2>err \
 +              merge-tree --merge-base=$(cat tree1) $(cat tree2) $(cat tree3) &&
 +      test_grep "unable to read blob object $(cat blob2)" err &&
 +      test_must_be_empty actual
 +'
 +
+ test_expect_success 'error out on missing commits as well' '
+       git init --bare missing-commit.git &&
+       git rev-list --objects side1 side3 >list-including-initial &&
+       grep -v ^$(git rev-parse side1^) <list-including-initial >list &&
+       git pack-objects missing-commit.git/objects/pack/missing-initial <list &&
+       side1=$(git rev-parse side1) &&
+       side3=$(git rev-parse side3) &&
+       test_must_fail git --git-dir=missing-commit.git \
+               merge-tree --allow-unrelated-histories $side1 $side3 >actual &&
+       test_must_be_empty actual
+ '
  test_done