refs: support rejection in batch updates during F/D checks

The `refs_verify_refnames_available()` is used to batch check refnames
for F/D conflicts. While this is the more performant alternative than
its individual version, it does not provide rejection capabilities on a
single update level. For batched updates, this would mean a rejection of
the entire transaction whenever one reference has a F/D conflict.

Modify the function to call `ref_transaction_maybe_set_rejected()` to
check if a single update can be rejected. Since this function is only
internally used within 'refs/' and we want to pass in a `struct
ref_transaction *` as a variable. We also move and mark
`refs_verify_refnames_available()` to 'refs-internal.h' to be an
internal function.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Karthik Nayak
2025-04-08 10:51:11 +02:00
committed by Junio C Hamano
parent 23fc8e4f61
commit 31726bb90d
5 changed files with 76 additions and 27 deletions

View File

@@ -1074,6 +1074,7 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor
struct ref_transaction *transaction,
struct reftable_backend *be,
struct ref_update *u,
size_t update_idx,
struct string_list *refnames_to_check,
unsigned int head_type,
struct strbuf *head_referent,
@@ -1149,6 +1150,7 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor
if (ret < 0)
return REF_TRANSACTION_ERROR_GENERIC;
if (ret > 0 && !ref_update_expects_existing_old_ref(u)) {
struct string_list_item *item;
/*
* The reference does not exist, and we either have no
* old object ID or expect the reference to not exist.
@@ -1158,7 +1160,9 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor
* can output a proper error message instead of failing
* at a later point.
*/
string_list_append(refnames_to_check, u->refname);
item = string_list_append(refnames_to_check, u->refname);
item->util = xmalloc(sizeof(update_idx));
memcpy(item->util, &update_idx, sizeof(update_idx));
/*
* There is no need to write the reference deletion
@@ -1368,7 +1372,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
for (i = 0; i < transaction->nr; i++) {
ret = prepare_single_update(refs, tx_data, transaction, be,
transaction->updates[i],
transaction->updates[i], i,
&refnames_to_check, head_type,
&head_referent, &referent, err);
if (ret) {
@@ -1384,6 +1388,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
ret = refs_verify_refnames_available(ref_store, &refnames_to_check,
&transaction->refnames, NULL,
transaction,
transaction->flags & REF_TRANSACTION_FLAG_INITIAL,
err);
if (ret < 0)
@@ -1402,7 +1407,7 @@ done:
}
strbuf_release(&referent);
strbuf_release(&head_referent);
string_list_clear(&refnames_to_check, 0);
string_list_clear(&refnames_to_check, 1);
return ret;
}