]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs: accept symref values in `ref_transaction_update()`
authorKarthik Nayak <karthik.188@gmail.com>
Tue, 7 May 2024 12:58:52 +0000 (14:58 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 7 May 2024 15:51:49 +0000 (08:51 -0700)
The function `ref_transaction_update()` obtains ref information and
flags to create a `ref_update` and add them to the transaction at hand.

To extend symref support in transactions, we need to also accept the
old and new ref targets and process it. This commit adds the required
parameters to the function and modifies all call sites.

The two parameters added are `new_target` and `old_target`. The
`new_target` is used to denote what the reference should point to when
the transaction is applied. Some functions allow this parameter to be
NULL, meaning that the reference is not changed.

The `old_target` denotes the value the reference must have before the
update. Some functions allow this parameter to be NULL, meaning that the
old value of the reference is not checked.

We also update the internal function `ref_transaction_add_update()`
similarly to take the two new parameters.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
14 files changed:
branch.c
builtin/fast-import.c
builtin/fetch.c
builtin/receive-pack.c
builtin/replace.c
builtin/tag.c
builtin/update-ref.c
refs.c
refs.h
refs/files-backend.c
refs/refs-internal.h
refs/reftable-backend.c
sequencer.c
walker.c

index 621019fcf4bde0a0568dbae2a1055e12cf8df030..3ebcfdca654b36f98c80701caae5284035869935 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -627,7 +627,7 @@ void create_branch(struct repository *r,
        if (!transaction ||
                ref_transaction_update(transaction, ref.buf,
                                        &oid, forcing ? NULL : null_oid(),
-                                       0, msg, &err) ||
+                                       NULL, NULL, 0, msg, &err) ||
                ref_transaction_commit(transaction, &err))
                die("%s", err.buf);
        ref_transaction_free(transaction);
index 782bda007c29e7f23393d1d5543dc47497ee2d14..6a0b39de32571c5dd37d0c7af39a167c34c42a00 100644 (file)
@@ -1634,7 +1634,7 @@ static int update_branch(struct branch *b)
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_update(transaction, b->name, &b->oid, &old_oid,
-                                  0, msg, &err) ||
+                                  NULL, NULL, 0, msg, &err) ||
            ref_transaction_commit(transaction, &err)) {
                ref_transaction_free(transaction);
                error("%s", err.buf);
@@ -1675,7 +1675,8 @@ static void dump_tags(void)
                strbuf_addf(&ref_name, "refs/tags/%s", t->name);
 
                if (ref_transaction_update(transaction, ref_name.buf,
-                                          &t->oid, NULL, 0, msg, &err)) {
+                                          &t->oid, NULL, NULL, NULL,
+                                          0, msg, &err)) {
                        failure |= error("%s", err.buf);
                        goto cleanup;
                }
index 46a793411a437969b53c4f14d941df27358d00ed..2b45778ab8f733f35d8cf197a483ba851460168f 100644 (file)
@@ -667,7 +667,7 @@ static int s_update_ref(const char *action,
 
        ret = ref_transaction_update(transaction, ref->name, &ref->new_oid,
                                     check_old ? &ref->old_oid : NULL,
-                                    0, msg, &err);
+                                    NULL, NULL, 0, msg, &err);
        if (ret) {
                ret = STORE_REF_ERROR_OTHER;
                goto out;
index 56d8a77ed75f65c1bcf47bd580e8e4e7cbbc32d9..ebea1747cba5fc952829cf7c7434a8b9799daea4 100644 (file)
@@ -1595,6 +1595,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
                if (ref_transaction_update(transaction,
                                           namespaced_name,
                                           new_oid, old_oid,
+                                          NULL, NULL,
                                           0, "push",
                                           &err)) {
                        rp_error("%s", err.buf);
index da59600ad22fda16155a278a210478fb55d0d94e..7690687b0ed645d7138701bdb05e2f208777d93d 100644 (file)
@@ -201,7 +201,7 @@ static int replace_object_oid(const char *object_ref,
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_update(transaction, ref.buf, repl, &prev,
-                                  0, NULL, &err) ||
+                                  NULL, NULL, 0, NULL, &err) ||
            ref_transaction_commit(transaction, &err))
                res = error("%s", err.buf);
 
index 9a33cb50b4557317bfad8904e189a6909a4490c0..40a65fdebce1f6c77f7247ed1748e8a169ad7761 100644 (file)
@@ -660,6 +660,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_update(transaction, ref.buf, &object, &prev,
+                                  NULL, NULL,
                                   create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
                                   reflog_msg.buf, &err) ||
            ref_transaction_commit(transaction, &err)) {
index e46afbc46d950df6f98dccc1908602470976618c..21fdbf6ac8a4a45138205f98454bc3d4c52ba8d0 100644 (file)
@@ -204,6 +204,7 @@ static void parse_cmd_update(struct ref_transaction *transaction,
 
        if (ref_transaction_update(transaction, refname,
                                   &new_oid, have_old ? &old_oid : NULL,
+                                  NULL, NULL,
                                   update_flags | create_reflog_flag,
                                   msg, &err))
                die("%s", err.buf);
diff --git a/refs.c b/refs.c
index 55d2e0b2cb9e959443e98eb329fdf97eff9073a9..e7b7c48d92cb49e18946caf478aa13a84098cbec 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1228,6 +1228,7 @@ struct ref_update *ref_transaction_add_update(
                const char *refname, unsigned int flags,
                const struct object_id *new_oid,
                const struct object_id *old_oid,
+               const char *new_target, const char *old_target,
                const char *msg)
 {
        struct ref_update *update;
@@ -1235,6 +1236,11 @@ struct ref_update *ref_transaction_add_update(
        if (transaction->state != REF_TRANSACTION_OPEN)
                BUG("update called for transaction that is not open");
 
+       if (old_oid && old_target)
+               BUG("only one of old_oid and old_target should be non NULL");
+       if (new_oid && new_target)
+               BUG("only one of new_oid and new_target should be non NULL");
+
        FLEX_ALLOC_STR(update, refname, refname);
        ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
        transaction->updates[transaction->nr++] = update;
@@ -1253,6 +1259,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
                           const char *refname,
                           const struct object_id *new_oid,
                           const struct object_id *old_oid,
+                          const char *new_target,
+                          const char *old_target,
                           unsigned int flags, const char *msg,
                           struct strbuf *err)
 {
@@ -1280,7 +1288,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
        flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
 
        ref_transaction_add_update(transaction, refname, flags,
-                                  new_oid, old_oid, msg);
+                                  new_oid, old_oid, new_target,
+                                  old_target, msg);
        return 0;
 }
 
@@ -1295,7 +1304,8 @@ int ref_transaction_create(struct ref_transaction *transaction,
                return 1;
        }
        return ref_transaction_update(transaction, refname, new_oid,
-                                     null_oid(), flags, msg, err);
+                                     null_oid(), NULL, NULL, flags,
+                                     msg, err);
 }
 
 int ref_transaction_delete(struct ref_transaction *transaction,
@@ -1308,7 +1318,8 @@ int ref_transaction_delete(struct ref_transaction *transaction,
                BUG("delete called with old_oid set to zeros");
        return ref_transaction_update(transaction, refname,
                                      null_oid(), old_oid,
-                                     flags, msg, err);
+                                     NULL, NULL, flags,
+                                     msg, err);
 }
 
 int ref_transaction_verify(struct ref_transaction *transaction,
@@ -1321,6 +1332,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,
                BUG("verify called with old_oid set to NULL");
        return ref_transaction_update(transaction, refname,
                                      NULL, old_oid,
+                                     NULL, NULL,
                                      flags, NULL, err);
 }
 
@@ -1335,8 +1347,8 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
 
        t = ref_store_transaction_begin(refs, &err);
        if (!t ||
-           ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
-                                  &err) ||
+           ref_transaction_update(t, refname, new_oid, old_oid, NULL, NULL,
+                                  flags, msg, &err) ||
            ref_transaction_commit(t, &err)) {
                ret = 1;
                ref_transaction_free(t);
diff --git a/refs.h b/refs.h
index d278775e086bfa7990999c226ad1db2f488e890d..c7851bf587390e3b1269d352ebb9db6bfa1560fa 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -648,6 +648,16 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err);
  *         before the update. A copy of this value is made in the
  *         transaction.
  *
+ *     new_target -- the target reference that the reference will be
+ *         updated to point to. If the reference is a regular reference,
+ *         it will be converted to a symbolic reference. Cannot be set
+ *         together with `new_oid`. A copy of this value is made in the
+ *         transaction.
+ *
+ *     old_target -- the reference that the reference must be pointing to.
+ *         Canont be set together with `old_oid`. A copy of this value is
+ *         made in the transaction.
+ *
  *     flags -- flags affecting the update, passed to
  *         update_ref_lock(). Possible flags: REF_NO_DEREF,
  *         REF_FORCE_CREATE_REFLOG. See those constants for more
@@ -713,7 +723,11 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err);
  * beforehand. The old value is checked after the lock is taken to
  * prevent races. If the old value doesn't agree with old_oid, the
  * whole transaction fails. If old_oid is NULL, then the previous
- * value is not checked.
+ * value is not checked. If `old_target` is not NULL, treat the reference
+ * as a symbolic ref and validate that its target before the update is
+ * `old_target`. If the `new_target` is not NULL, then the reference
+ * will be updated to a symbolic ref which targets `new_target`.
+ * Together, these allow us to update between regular refs and symrefs.
  *
  * See the above comment "Reference transaction updates" for more
  * information.
@@ -722,6 +736,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
                           const char *refname,
                           const struct object_id *new_oid,
                           const struct object_id *old_oid,
+                          const char *new_target,
+                          const char *old_target,
                           unsigned int flags, const char *msg,
                           struct strbuf *err);
 
index a098d14ea00ed6db449e5d3cc8dff28594228977..e4d0aa3d41fd77eeacf7efad08f8510fc1333631 100644 (file)
@@ -1198,7 +1198,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
        ref_transaction_add_update(
                        transaction, r->name,
                        REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,
-                       null_oid(), &r->oid, NULL);
+                       null_oid(), &r->oid, NULL, NULL, NULL);
        if (ref_transaction_commit(transaction, &err))
                goto cleanup;
 
@@ -1292,7 +1292,7 @@ static int files_pack_refs(struct ref_store *ref_store,
                 * packed-refs transaction:
                 */
                if (ref_transaction_update(transaction, iter->refname,
-                                          iter->oid, NULL,
+                                          iter->oid, NULL, NULL, NULL,
                                           REF_NO_DEREF, NULL, &err))
                        die("failure preparing to create packed reference %s: %s",
                            iter->refname, err.buf);
@@ -2309,7 +2309,7 @@ static int split_head_update(struct ref_update *update,
                        transaction, "HEAD",
                        update->flags | REF_LOG_ONLY | REF_NO_DEREF,
                        &update->new_oid, &update->old_oid,
-                       update->msg);
+                       NULL, NULL, update->msg);
 
        /*
         * Add "HEAD". This insertion is O(N) in the transaction
@@ -2372,7 +2372,7 @@ static int split_symref_update(struct ref_update *update,
        new_update = ref_transaction_add_update(
                        transaction, referent, new_flags,
                        &update->new_oid, &update->old_oid,
-                       update->msg);
+                       NULL, NULL, update->msg);
 
        new_update->parent_update = update;
 
@@ -2763,7 +2763,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
                                        packed_transaction, update->refname,
                                        REF_HAVE_NEW | REF_NO_DEREF,
                                        &update->new_oid, NULL,
-                                       NULL);
+                                       NULL, NULL, NULL);
                }
        }
 
@@ -3048,7 +3048,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
                ref_transaction_add_update(packed_transaction, update->refname,
                                           update->flags & ~REF_HAVE_OLD,
                                           &update->new_oid, &update->old_oid,
-                                          NULL);
+                                          NULL, NULL, NULL);
        }
 
        if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
index 56641aa57a138da17037307d37e1ca28baa2a1ee..108f4ec419993d9493a438f07290a8b7cd6d0ff2 100644 (file)
@@ -124,6 +124,19 @@ struct ref_update {
         */
        struct object_id old_oid;
 
+       /*
+        * If set, point the reference to this value. This can also be
+        * used to convert regular references to become symbolic refs.
+        * Cannot be set together with `new_oid`.
+        */
+       const char *new_target;
+
+       /*
+        * If set, check that the reference previously pointed to this
+        * value. Cannot be set together with `old_oid`.
+        */
+       const char *old_target;
+
        /*
         * One or more of REF_NO_DEREF, REF_FORCE_CREATE_REFLOG,
         * REF_HAVE_NEW, REF_HAVE_OLD, or backend-specific flags.
@@ -173,6 +186,7 @@ struct ref_update *ref_transaction_add_update(
                const char *refname, unsigned int flags,
                const struct object_id *new_oid,
                const struct object_id *old_oid,
+               const char *new_target, const char *old_target,
                const char *msg);
 
 /*
index 0bed6d2ab4844a1eb6b548c77577f3fc13105a81..e6122837c0a7f14d80f7e9709858fde5ad061d3c 100644 (file)
@@ -826,7 +826,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
                        new_update = ref_transaction_add_update(
                                        transaction, "HEAD",
                                        u->flags | REF_LOG_ONLY | REF_NO_DEREF,
-                                       &u->new_oid, &u->old_oid, u->msg);
+                                       &u->new_oid, &u->old_oid, NULL, NULL, u->msg);
                        string_list_insert(&affected_refnames, new_update->refname);
                }
 
@@ -905,7 +905,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
                                 */
                                new_update = ref_transaction_add_update(
                                                transaction, referent.buf, new_flags,
-                                               &u->new_oid, &u->old_oid, u->msg);
+                                               &u->new_oid, &u->old_oid, NULL, NULL, u->msg);
                                new_update->parent_update = u;
 
                                /*
index 2c19846385baa1df3240e865752087db827ba36e..af1b25692b791a798abc8c7581e4df5ec47497ec 100644 (file)
@@ -616,7 +616,7 @@ static int fast_forward_to(struct repository *r,
        if (!transaction ||
            ref_transaction_update(transaction, "HEAD",
                                   to, unborn && !is_rebase_i(opts) ?
-                                  null_oid() : from,
+                                  null_oid() : from, NULL, NULL,
                                   0, sb.buf, &err) ||
            ref_transaction_commit(transaction, &err)) {
                ref_transaction_free(transaction);
@@ -1248,7 +1248,7 @@ int update_head_with_reflog(const struct commit *old_head,
        if (!transaction ||
            ref_transaction_update(transaction, "HEAD", new_head,
                                   old_head ? &old_head->object.oid : null_oid(),
-                                  0, sb.buf, err) ||
+                                  NULL, NULL, 0, sb.buf, err) ||
            ref_transaction_commit(transaction, err)) {
                ret = -1;
        }
@@ -3764,8 +3764,9 @@ static int do_label(struct repository *r, const char *name, int len)
        } else if (repo_get_oid(r, "HEAD", &head_oid)) {
                error(_("could not read HEAD"));
                ret = -1;
-       } else if (ref_transaction_update(transaction, ref_name.buf, &head_oid,
-                                         NULL, 0, msg.buf, &err) < 0 ||
+       } else if (ref_transaction_update(transaction, ref_name.buf,
+                                         &head_oid, NULL, NULL, NULL,
+                                         0, msg.buf, &err) < 0 ||
                   ref_transaction_commit(transaction, &err)) {
                error("%s", err.buf);
                ret = -1;
index c0fd632d921c4f229d56f5c406a4c97386f3788c..1b3df4390610c6899e926646ed24749febdb24da 100644 (file)
--- a/walker.c
+++ b/walker.c
@@ -324,7 +324,7 @@ int walker_fetch(struct walker *walker, int targets, char **target,
                strbuf_reset(&refname);
                strbuf_addf(&refname, "refs/%s", write_ref[i]);
                if (ref_transaction_update(transaction, refname.buf,
-                                          oids + i, NULL, 0,
+                                          oids + i, NULL, NULL, NULL, 0,
                                           msg ? msg : "fetch (unknown)",
                                           &err)) {
                        error("%s", err.buf);