]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs/reftable: don't fail empty transactions in repo without HEAD
authorPatrick Steinhardt <ps@pks.im>
Tue, 27 Feb 2024 14:27:39 +0000 (15:27 +0100)
committerJunio C Hamano <gitster@pobox.com>
Tue, 27 Feb 2024 21:53:39 +0000 (13:53 -0800)
Under normal circumstances, it shouldn't ever happen that a repository
has no HEAD reference. In fact, git-update-ref(1) would fail any request
to delete the HEAD reference, and a newly initialized repository always
pre-creates it, too.

We have however changed git-clone(1) to partially initialize the
refdb just up to the point where remote helpers can find the
repository. With that change, we are going to run into a situation
where repositories have no refs at all.

Now there is a very particular edge case in this situation: when
preparing an empty ref transacton, we end up returning whatever value
`read_ref_without_reload()` returned to the caller. Under normal
conditions this would be fine: "HEAD" should usually exist, and thus the
function would return `0`. But if "HEAD" doesn't exist, the function
returns a positive value which we end up returning to the caller.

Fix this bug by resetting the return code to `0` and add a test.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs/reftable-backend.c
t/t0610-reftable-basics.sh

index a14f2ad7f4545230887b433dd72712b30a38fd40..45568818f063c4e6e9597259188f804280fe7116 100644 (file)
@@ -821,6 +821,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
                                      &head_referent, &head_type);
        if (ret < 0)
                goto done;
+       ret = 0;
 
        for (i = 0; i < transaction->nr; i++) {
                struct ref_update *u = transaction->updates[i];
index 6a131e40b8157dc3fefea53704ad2377b7ce5c3a..c5f4d23433d88b5d4a5e9b92d2c986042b849bd3 100755 (executable)
@@ -328,6 +328,19 @@ test_expect_success 'ref transaction: writes are synced' '
        EOF
 '
 
+test_expect_success 'ref transaction: empty transaction in empty repo' '
+       test_when_finished "rm -rf repo" &&
+       git init repo &&
+       test_commit -C repo --no-tag A &&
+       COMMIT=$(git -C repo rev-parse HEAD) &&
+       git -C repo update-ref -d refs/heads/main &&
+       test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD &&
+       git -C repo update-ref --stdin <<-EOF
+       prepare
+       commit
+       EOF
+'
+
 test_expect_success 'pack-refs: compacts tables' '
        test_when_finished "rm -rf repo" &&
        git init repo &&