Skip to content

Commit 07f9c88

Browse files
mhaggergitster
authored andcommitted
ref_transaction_commit(): use a string_list for detecting duplicates
Detect duplicates by storing the reference names in a string_list and sorting that, instead of sorting the ref_updates directly. * In a moment the string_list will be used for another purpose, too. * This removes the need for the custom comparison function ref_update_compare(). * This means that we can carry out the updates in the order that the user specified them instead of reordering them. This might be handy someday if, we want to permit multiple updates to a single reference as long as they are compatible with each other. Note: we can't use string_list_remove_duplicates() to check for duplicates, because we need to know the name of the reference that appeared multiple times, to be used in the error message. Signed-off-by: Michael Haggerty <[email protected]>
1 parent 61da596 commit 07f9c88

File tree

1 file changed

+11
-14
lines changed

1 file changed

+11
-14
lines changed

refs.c

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3720,25 +3720,18 @@ int update_ref(const char *msg, const char *refname,
37203720
return 0;
37213721
}
37223722

3723-
static int ref_update_compare(const void *r1, const void *r2)
3724-
{
3725-
const struct ref_update * const *u1 = r1;
3726-
const struct ref_update * const *u2 = r2;
3727-
return strcmp((*u1)->refname, (*u2)->refname);
3728-
}
3729-
3730-
static int ref_update_reject_duplicates(struct ref_update **updates, int n,
3723+
static int ref_update_reject_duplicates(struct string_list *refnames,
37313724
struct strbuf *err)
37323725
{
3733-
int i;
3726+
int i, n = refnames->nr;
37343727

37353728
assert(err);
37363729

37373730
for (i = 1; i < n; i++)
3738-
if (!strcmp(updates[i - 1]->refname, updates[i]->refname)) {
3731+
if (!strcmp(refnames->items[i - 1].string, refnames->items[i].string)) {
37393732
strbuf_addf(err,
37403733
"Multiple updates for ref '%s' not allowed.",
3741-
updates[i]->refname);
3734+
refnames->items[i].string);
37423735
return 1;
37433736
}
37443737
return 0;
@@ -3752,6 +3745,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
37523745
struct ref_update **updates = transaction->updates;
37533746
struct string_list refs_to_delete = STRING_LIST_INIT_NODUP;
37543747
struct string_list_item *ref_to_delete;
3748+
struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
37553749

37563750
assert(err);
37573751

@@ -3763,9 +3757,11 @@ int ref_transaction_commit(struct ref_transaction *transaction,
37633757
return 0;
37643758
}
37653759

3766-
/* Copy, sort, and reject duplicate refs */
3767-
qsort(updates, n, sizeof(*updates), ref_update_compare);
3768-
if (ref_update_reject_duplicates(updates, n, err)) {
3760+
/* Fail if a refname appears more than once in the transaction: */
3761+
for (i = 0; i < n; i++)
3762+
string_list_append(&affected_refnames, updates[i]->refname);
3763+
string_list_sort(&affected_refnames);
3764+
if (ref_update_reject_duplicates(&affected_refnames, err)) {
37693765
ret = TRANSACTION_GENERIC_ERROR;
37703766
goto cleanup;
37713767
}
@@ -3857,6 +3853,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
38573853
if (updates[i]->lock)
38583854
unlock_ref(updates[i]->lock);
38593855
string_list_clear(&refs_to_delete, 0);
3856+
string_list_clear(&affected_refnames, 0);
38603857
return ret;
38613858
}
38623859

0 commit comments

Comments
 (0)