git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 09/18] ref_transaction_commit(): use a string_list for detecting duplicates

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
May 1, 2015, 12:25 UTC
Message-ID
<1430483158-14349-10-git-send-email-mhagger@alum.mit.edu>
In-Reply-To
<1430483158-14349-1-git-send-email-mhagger@alum.mit.edu>

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 <mhagger@alum.mit.edu>
---
 refs.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/refs.c b/refs.c
index 8e929c7..fca3ef1 100644
--- a/refs.c
+++ b/refs.c
@@ -3718,25 +3718,18 @@ int update_ref(const char *msg, const char *refname,
 	return 0;
 }
 
-static int ref_update_compare(const void *r1, const void *r2)
-{
-	const struct ref_update * const *u1 = r1;
-	const struct ref_update * const *u2 = r2;
-	return strcmp((*u1)->refname, (*u2)->refname);
-}
-
-static int ref_update_reject_duplicates(struct ref_update **updates, int n,
+static int ref_update_reject_duplicates(struct string_list *refnames,
 					struct strbuf *err)
 {
-	int i;
+	int i, n = refnames->nr;
 
 	assert(err);
 
 	for (i = 1; i < n; i++)
-		if (!strcmp(updates[i - 1]->refname, updates[i]->refname)) {
+		if (!strcmp(refnames->items[i - 1].string, refnames->items[i].string)) {
 			strbuf_addf(err,
 				    "Multiple updates for ref '%s' not allowed.",
-				    updates[i]->refname);
+				    refnames->items[i].string);
 			return 1;
 		}
 	return 0;
@@ -3750,6 +3743,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
 	struct ref_update **updates = transaction->updates;
 	struct string_list refs_to_delete = STRING_LIST_INIT_NODUP;
 	struct string_list_item *ref_to_delete;
+	struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
 
 	assert(err);
 
@@ -3761,9 +3755,11 @@ int ref_transaction_commit(struct ref_transaction *transaction,
 		return 0;
 	}
 
-	/* Copy, sort, and reject duplicate refs */
-	qsort(updates, n, sizeof(*updates), ref_update_compare);
-	if (ref_update_reject_duplicates(updates, n, err)) {
+	/* Fail if a refname appears more than once in the transaction: */
+	for (i = 0; i < n; i++)
+		string_list_append(&affected_refnames, updates[i]->refname);
+	string_list_sort(&affected_refnames);
+	if (ref_update_reject_duplicates(&affected_refnames, err)) {
 		ret = TRANSACTION_GENERIC_ERROR;
 		goto cleanup;
 	}
@@ -3879,6 +3875,7 @@ cleanup:
 		if (updates[i]->lock)
 			unlock_ref(updates[i]->lock);
 	string_list_clear(&refs_to_delete, 0);
+	string_list_clear(&affected_refnames, 0);
 	return ret;
 }
 
-- 
2.1.4
Previous: Michael HaggertyNext: Michael Haggerty
Message 14 of 25 in “Improve handling of D/F conflicts”
  1. 00/18 Improve handling of D/F conflictsMichael Haggerty, May 1, 2015
  2. 01/18 t1404: new tests of D/F conflicts within ref transactionsMichael Haggerty, May 1, 2015
  3. Eric SunshineMay 5, 2015
  4. Michael HaggertyMay 5, 2015
  5. 02/18 is_refname_available(): explain the reason for an early exitMichael Haggerty, May 1, 2015
  6. Stefan BellerMay 1, 2015
  7. Michael HaggertyMay 5, 2015
  8. 03/18 is_refname_available(): avoid shadowing "dir" variableMichael Haggerty, May 1, 2015
  9. 04/18 is_refname_available(): convert local variable "dirname" to strbufMichael Haggerty, May 1, 2015
  10. 05/18 entry_matches(): inline functionMichael Haggerty, May 1, 2015
  11. 06/18 report_refname_conflict(): inline functionMichael Haggerty, May 1, 2015
  12. 07/18 struct nonmatching_ref_data: store a refname instead of a ref_entryMichael Haggerty, May 1, 2015
  13. 08/18 is_refname_available(): use dirname in first loopMichael Haggerty, May 1, 2015
  14. 09/18 ref_transaction_commit(): use a string_list for detecting duplicatesMichael Haggerty, May 1, 2015
  15. 10/18 refs: check for D/F conflicts among refs processed in a transactionMichael Haggerty, May 1, 2015
  16. 11/18 verify_refname_available(): rename functionMichael Haggerty, May 1, 2015
  17. 12/18 verify_refname_available(): report errors via a "struct strbuf *err"Michael Haggerty, May 1, 2015
  18. 13/18 lock_ref_sha1_basic(): report errors via a "struct strbuf *err"Michael Haggerty, May 1, 2015
  19. 14/18 lock_ref_sha1_basic(): improve diagnostics for D/F conflictsMichael Haggerty, May 1, 2015
  20. 15/18 rename_ref(): integrate lock_ref_sha1_basic() errors into oursMichael Haggerty, May 1, 2015
  21. 16/18 ref_transaction_commit(): provide better error messagesMichael Haggerty, May 1, 2015
  22. 17/18 ref_transaction_commit(): delete extra "the" from error messageMichael Haggerty, May 1, 2015
  23. 18/18 reflog_expire(): integrate lock_ref_sha1_basic() errors into oursMichael Haggerty, May 1, 2015
  24. Junio C HamanoMay 3, 2015
  25. Michael HaggertyMay 5, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.