fetch: allow passing a transaction to `s_update_ref()`

The handling of ref updates is completely handled by `s_update_ref()`, which will manage the complete lifecycle of the reference transaction. This is fine right now given that git-fetch(1) does not support atomic fetches, so each reference gets its own transaction. It is quite inflexible though, as `s_update_ref()` only knows about a single reference update at a time, so it doesn't allow us to alter the strategy. This commit prepares `s_update_ref()` and its only caller `update_local_ref()` to allow passing an external transaction. If none is given, then the existing behaviour is triggered which creates a new transaction and directly commits it. Otherwise, if the caller provides a transaction, then we only queue the update but don't commit it. This optionally allows the caller to manage when a transaction will be committed. Given that `update_local_ref()` is always called with a `NULL` transaction for now, no change in behaviour is expected from this change. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jan 12, 2021 at 13:27 UTC d4c8db8f1b43cb26efdd53d74afce60e6d9d195a
1 file changed +31 -20
builtin/fetch.c
+31 -20
@@ -583,11 +583,12 @@ static struct ref *get_ref_map(struct remote *remote,
583
584 static int s_update_ref(const char *action,
585 struct ref *ref,
586 + struct ref_transaction *transaction,
587 int check_old)
588 {
589 char *msg;
590 char *rla = getenv("GIT_REFLOG_ACTION");
590 - struct ref_transaction *transaction;
591 + struct ref_transaction *our_transaction = NULL;
592 struct strbuf err = STRBUF_INIT;
593 int ret;
594
@@ -597,10 +598,17 @@ static int s_update_ref(const char *action,
598 rla = default_rla.buf;
599 msg = xstrfmt("%s: %s", rla, action);
600
600 - transaction = ref_transaction_begin(&err);
601 + /*
602 + * If no transaction was passed to us, we manage the transaction
603 + * ourselves. Otherwise, we trust the caller to handle the transaction
604 + * lifecycle.
605 + */
606 if (!transaction) {
602 - ret = STORE_REF_ERROR_OTHER;
603 - goto out;
607 + transaction = our_transaction = ref_transaction_begin(&err);
608 + if (!transaction) {
609 + ret = STORE_REF_ERROR_OTHER;
610 + goto out;
611 + }
612 }
613
614 ret = ref_transaction_update(transaction, ref->name, &ref->new_oid,
@@ -611,19 +619,21 @@ static int s_update_ref(const char *action,
619 goto out;
620 }
621
614 - switch (ref_transaction_commit(transaction, &err)) {
615 - case 0:
616 - break;
617 - case TRANSACTION_NAME_CONFLICT:
618 - ret = STORE_REF_ERROR_DF_CONFLICT;
619 - goto out;
620 - default:
621 - ret = STORE_REF_ERROR_OTHER;
622 - goto out;
622 + if (our_transaction) {
623 + switch (ref_transaction_commit(our_transaction, &err)) {
624 + case 0:
625 + break;
626 + case TRANSACTION_NAME_CONFLICT:
627 + ret = STORE_REF_ERROR_DF_CONFLICT;
628 + goto out;
629 + default:
630 + ret = STORE_REF_ERROR_OTHER;
631 + goto out;
632 + }
633 }
634
635 out:
626 - ref_transaction_free(transaction);
636 + ref_transaction_free(our_transaction);
637 if (ret)
638 error("%s", err.buf);
639 strbuf_release(&err);
@@ -766,6 +776,7 @@ static void format_display(struct strbuf *display, char code,
776 }
777
778 static int update_local_ref(struct ref *ref,
779 + struct ref_transaction *transaction,
780 const char *remote,
781 const struct ref *remote_ref,
782 struct strbuf *display,
@@ -806,7 +817,7 @@ static int update_local_ref(struct ref *ref,
817 starts_with(ref->name, "refs/tags/")) {
818 if (force || ref->force) {
819 int r;
809 - r = s_update_ref("updating tag", ref, 0);
820 + r = s_update_ref("updating tag", ref, transaction, 0);
821 format_display(display, r ? '!' : 't', _("[tag update]"),
822 r ? _("unable to update local ref") : NULL,
823 remote, pretty_ref, summary_width);
@@ -843,7 +854,7 @@ static int update_local_ref(struct ref *ref,
854 what = _("[new ref]");
855 }
856
846 - r = s_update_ref(msg, ref, 0);
857 + r = s_update_ref(msg, ref, transaction, 0);
858 format_display(display, r ? '!' : '*', what,
859 r ? _("unable to update local ref") : NULL,
860 remote, pretty_ref, summary_width);
@@ -865,7 +876,7 @@ static int update_local_ref(struct ref *ref,
876 strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
877 strbuf_addstr(&quickref, "..");
878 strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
868 - r = s_update_ref("fast-forward", ref, 1);
879 + r = s_update_ref("fast-forward", ref, transaction, 1);
880 format_display(display, r ? '!' : ' ', quickref.buf,
881 r ? _("unable to update local ref") : NULL,
882 remote, pretty_ref, summary_width);
@@ -877,7 +888,7 @@ static int update_local_ref(struct ref *ref,
888 strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
889 strbuf_addstr(&quickref, "...");
890 strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
880 - r = s_update_ref("forced-update", ref, 1);
891 + r = s_update_ref("forced-update", ref, transaction, 1);
892 format_display(display, r ? '!' : '+', quickref.buf,
893 r ? _("unable to update local ref") : _("forced update"),
894 remote, pretty_ref, summary_width);
@@ -1094,8 +1105,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
1105
1106 strbuf_reset(&note);
1107 if (ref) {
1097 - rc |= update_local_ref(ref, what, rm, &note,
1098 - summary_width);
1108 + rc |= update_local_ref(ref, NULL, what,
1109 + rm, &note, summary_width);
1110 free(ref);
1111 } else if (write_fetch_head || dry_run) {
1112 /*