Merge branch 'kn/ref-batch-output-error-reporting-fix'

A handful of code paths that started using batched ref update API
(after Git 2.51 or so) lost detailed error output, which have been
corrected.

* kn/ref-batch-output-error-reporting-fix:
  fetch: delay user information post committing of transaction
  receive-pack: utilize rejected ref error details
  fetch: utilize rejected ref error details
  update-ref: utilize rejected error details if available
  refs: add rejection detail to the callback function
  refs: skip to next ref when current ref is rejected
This commit is contained in:
Junio C Hamano
2026-02-09 12:09:10 -08:00
12 changed files with 319 additions and 132 deletions

60
refs.c
View File

@@ -1267,6 +1267,7 @@ void ref_transaction_free(struct ref_transaction *transaction)
free(transaction->updates[i]->committer_info);
free((char *)transaction->updates[i]->new_target);
free((char *)transaction->updates[i]->old_target);
free((char *)transaction->updates[i]->rejection_details);
free(transaction->updates[i]);
}
@@ -1281,7 +1282,8 @@ void ref_transaction_free(struct ref_transaction *transaction)
int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction,
size_t update_idx,
enum ref_transaction_error err)
enum ref_transaction_error err,
struct strbuf *details)
{
if (update_idx >= transaction->nr)
BUG("trying to set rejection on invalid update index");
@@ -1307,6 +1309,7 @@ int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction,
transaction->updates[update_idx]->refname, 0);
transaction->updates[update_idx]->rejection_err = err;
transaction->updates[update_idx]->rejection_details = strbuf_detach(details, NULL);
ALLOC_GROW(transaction->rejections->update_indices,
transaction->rejections->nr + 1,
transaction->rejections->alloc);
@@ -2698,30 +2701,33 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
if (!initial_transaction &&
(strset_contains(&conflicting_dirnames, dirname.buf) ||
!refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
&type, &ignore_errno))) {
if (transaction && ref_transaction_maybe_set_rejected(
transaction, *update_idx,
REF_TRANSACTION_ERROR_NAME_CONFLICT)) {
strset_remove(&dirnames, dirname.buf);
strset_add(&conflicting_dirnames, dirname.buf);
continue;
}
&type, &ignore_errno))) {
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
dirname.buf, refname);
if (transaction && ref_transaction_maybe_set_rejected(
transaction, *update_idx,
REF_TRANSACTION_ERROR_NAME_CONFLICT, err)) {
strset_remove(&dirnames, dirname.buf);
strset_add(&conflicting_dirnames, dirname.buf);
goto next_ref;
}
goto cleanup;
}
if (extras && string_list_has_string(extras, dirname.buf)) {
if (transaction && ref_transaction_maybe_set_rejected(
transaction, *update_idx,
REF_TRANSACTION_ERROR_NAME_CONFLICT)) {
strset_remove(&dirnames, dirname.buf);
continue;
}
strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
refname, dirname.buf);
if (transaction && ref_transaction_maybe_set_rejected(
transaction, *update_idx,
REF_TRANSACTION_ERROR_NAME_CONFLICT, err)) {
strset_remove(&dirnames, dirname.buf);
goto next_ref;
}
goto cleanup;
}
}
@@ -2751,14 +2757,14 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
if (skip &&
string_list_has_string(skip, iter->ref.name))
continue;
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
iter->ref.name, refname);
if (transaction && ref_transaction_maybe_set_rejected(
transaction, *update_idx,
REF_TRANSACTION_ERROR_NAME_CONFLICT))
continue;
REF_TRANSACTION_ERROR_NAME_CONFLICT, err))
goto next_ref;
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
iter->ref.name, refname);
goto cleanup;
}
@@ -2768,15 +2774,17 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
extra_refname = find_descendant_ref(dirname.buf, extras, skip);
if (extra_refname) {
if (transaction && ref_transaction_maybe_set_rejected(
transaction, *update_idx,
REF_TRANSACTION_ERROR_NAME_CONFLICT))
continue;
strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
refname, extra_refname);
if (transaction && ref_transaction_maybe_set_rejected(
transaction, *update_idx,
REF_TRANSACTION_ERROR_NAME_CONFLICT, err))
goto next_ref;
goto cleanup;
}
next_ref:;
}
ret = 0;
@@ -2905,7 +2913,7 @@ void ref_transaction_for_each_rejected_update(struct ref_transaction *transactio
(update->flags & REF_HAVE_OLD) ? &update->old_oid : NULL,
(update->flags & REF_HAVE_NEW) ? &update->new_oid : NULL,
update->old_target, update->new_target,
update->rejection_err, cb_data);
update->rejection_err, update->rejection_details, cb_data);
}
}