]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs: use transaction in `refs_create_symref()`
authorKarthik Nayak <karthik.188@gmail.com>
Tue, 7 May 2024 12:58:57 +0000 (14:58 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 7 May 2024 15:51:50 +0000 (08:51 -0700)
The `refs_create_symref()` function updates a symref to a given new
target. To do this, it uses a ref-backend specific function
`create_symref()`.

In the previous commits, we introduced symref support in transactions.
This means we can now use transactions to perform symref updates and
don't have to resort to `create_symref()`. Doing this allows us to
remove and cleanup `create_symref()`, which we will do in the following
commit.

Modify the expected error message for a test in
't/t0610-reftable-basics.sh', since the error is now thrown from
'refs.c'. This is because in transactional updates, F/D conflicts are
caught before we're in the reference backend.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs.c
t/t0610-reftable-basics.sh
t/t1416-ref-transaction-hooks.sh

diff --git a/refs.c b/refs.c
index d0ea7573d853af9085e38fb0dec169414008489a..507f5f0525f3f1313a9de842a2231a2ee73f0d2b 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2289,14 +2289,24 @@ int refs_create_symref(struct ref_store *refs,
                       const char *refs_heads_master,
                       const char *logmsg)
 {
-       char *msg;
-       int retval;
+       struct ref_transaction *transaction;
+       struct strbuf err = STRBUF_INIT;
+       int ret = 0;
 
-       msg = normalize_reflog_message(logmsg);
-       retval = refs->be->create_symref(refs, ref_target, refs_heads_master,
-                                        msg);
-       free(msg);
-       return retval;
+       transaction = ref_store_transaction_begin(refs, &err);
+       if (!transaction ||
+           ref_transaction_update(transaction, ref_target, NULL, NULL,
+                                  refs_heads_master, NULL, REF_NO_DEREF,
+                                  logmsg, &err) ||
+           ref_transaction_commit(transaction, &err)) {
+               ret = error("%s", err.buf);
+       }
+
+       strbuf_release(&err);
+       if (transaction)
+               ref_transaction_free(transaction);
+
+       return ret;
 }
 
 int create_symref(const char *ref_target, const char *refs_heads_master,
index 931d888bbbcbc426dcf51a0478842fd4787bee1d..01758fc5654a7aec998e10bf2c32463c0544150b 100755 (executable)
@@ -255,7 +255,7 @@ test_expect_success 'ref transaction: creating symbolic ref fails with F/D confl
        git init repo &&
        test_commit -C repo A &&
        cat >expect <<-EOF &&
-       error: unable to write symref for refs/heads: file/directory conflict
+       error: ${SQ}refs/heads/main${SQ} exists; cannot create ${SQ}refs/heads${SQ}
        EOF
        test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
        test_cmp expect err
index 2092488090de5624103f277b8ad3d44030ce3767..067fd57290c375a90cee03eed02c08d99d9aed68 100755 (executable)
@@ -134,4 +134,27 @@ test_expect_success 'interleaving hook calls succeed' '
        test_cmp expect target-repo.git/actual
 '
 
+test_expect_success 'hook captures git-symbolic-ref updates' '
+       test_when_finished "rm actual" &&
+
+       test_hook reference-transaction <<-\EOF &&
+               echo "$*" >>actual
+               while read -r line
+               do
+                       printf "%s\n" "$line"
+               done >>actual
+       EOF
+
+       git symbolic-ref refs/heads/symref refs/heads/main &&
+
+       cat >expect <<-EOF &&
+       prepared
+       $ZERO_OID ref:refs/heads/main refs/heads/symref
+       committed
+       $ZERO_OID ref:refs/heads/main refs/heads/symref
+       EOF
+
+       test_cmp expect actual
+'
+
 test_done