]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs: add create_only option to refs_update_symref_extended
authorBence Ferdinandy <bence@ferdinandy.com>
Fri, 22 Nov 2024 12:28:49 +0000 (13:28 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Nov 2024 02:46:36 +0000 (11:46 +0900)
Allow the caller to specify that it only wants to update the symref if
it does not already exist. Silently ignore the error from the
transaction API if the symref already exists.

Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/remote.c
refs.c
refs.h

index 6d659d63ca889b1a6fd62e6acbf196149851b014..3dc1135b5cef44a19b4ee99309cd472fc4a76415 100644 (file)
@@ -1476,7 +1476,7 @@ static int set_head(int argc, const char **argv, const char *prefix)
                goto cleanup;
        }
        was_detached = refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
-                       "remote set-head", &b_local_head);
+                       "remote set-head", &b_local_head, 0);
        if (was_detached == -1) {
                result |= error(_("Could not set up %s"), b_head.buf);
                goto cleanup;
diff --git a/refs.c b/refs.c
index d80efd58f0aab1b3877324fe7bf62a883f577a2d..2efa6bcc5c802bbcdf96afecfaf50a70a4b520c4 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2116,26 +2116,38 @@ int peel_iterated_oid(struct repository *r, const struct object_id *base, struct
 int refs_update_symref(struct ref_store *refs, const char *ref,
                       const char *target, const char *logmsg)
 {
-       return refs_update_symref_extended(refs, ref, target, logmsg, NULL);
+       return refs_update_symref_extended(refs, ref, target, logmsg, NULL, 0);
 }
 
 int refs_update_symref_extended(struct ref_store *refs, const char *ref,
                       const char *target, const char *logmsg,
-                      struct strbuf *referent)
+                      struct strbuf *referent, int create_only)
 {
        struct ref_transaction *transaction;
        struct strbuf err = STRBUF_INIT;
-       int ret = 0;
+       int ret = 0, prepret = 0;
 
        transaction = ref_store_transaction_begin(refs, &err);
-       if (!transaction ||
-           ref_transaction_update(transaction, ref, NULL, NULL,
-                                  target, NULL, REF_NO_DEREF,
-                                  logmsg, &err) ||
-           ref_transaction_prepare(transaction, &err)) {
+       if (!transaction) {
+       error_return:
                ret = error("%s", err.buf);
                goto cleanup;
        }
+       if (create_only) {
+               if (ref_transaction_create(transaction, ref, NULL, target,
+                                          REF_NO_DEREF, logmsg, &err))
+                       goto error_return;
+               prepret = ref_transaction_prepare(transaction, &err);
+               if (prepret && prepret != TRANSACTION_CREATE_EXISTS)
+                       goto error_return;
+       } else {
+               if (ref_transaction_update(transaction, ref, NULL, NULL,
+                                          target, NULL, REF_NO_DEREF,
+                                          logmsg, &err) ||
+                       ref_transaction_prepare(transaction, &err))
+                       goto error_return;
+       }
+
        if (referent && refs_read_symbolic_ref(refs, ref, referent) == NOT_A_SYMREF) {
                struct object_id oid;
                if (!refs_read_ref(refs, ref, &oid)) {
@@ -2144,8 +2156,11 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref,
                }
        }
 
+       if (prepret == TRANSACTION_CREATE_EXISTS)
+               goto cleanup;
+
        if (ref_transaction_commit(transaction, &err))
-               ret = error("%s", err.buf);
+               goto error_return;
 
 cleanup:
        strbuf_release(&err);
diff --git a/refs.h b/refs.h
index b243739e4b4f1a3f8a2074fd192376015b4a0858..be38377b1f6d2a56636a99125e493e3115b1b78c 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -586,7 +586,7 @@ int refs_update_symref(struct ref_store *refs, const char *refname,
 
 int refs_update_symref_extended(struct ref_store *refs, const char *refname,
                       const char *target, const char *logmsg,
-                      struct strbuf *referent);
+                      struct strbuf *referent, int create_only);
 
 enum action_on_err {
        UPDATE_REFS_MSG_ON_ERR,