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

[PATCH 6/7] refs: allow multiple reflog entries for the same refname

From
Karthik Nayak <karthik.188@gmail.com>
Date
Dec 9, 2024, 11:07 UTC
Message-ID
<20241209-320-git-refs-migrate-reflogs-v1-6-d4bc37ee860f@gmail.com>
In-Reply-To
<20241209-320-git-refs-migrate-reflogs-v1-0-d4bc37ee860f@gmail.com>

The reference transaction only allows a update for a given reference to avoid conflicts. This, however, isn't an issue for reflogs. There are no conflicts to be resolved in reflogs and when migrating reflogs between backends we'd have multiple reflog entries for the same refname.

So allow multiple reflog updates within a single transaction. Also the reflog creation logic isn't exposed to the end user. While this might change in the future, currently, this reduces the scope of issues to think about.

This is required to add reflog migration support to `git refs migrate` which currently doesn't support it.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
---
 refs/files-backend.c    | 15 +++++++++++----
 refs/reftable-backend.c | 16 +++++++++++++---
 2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 32975e0fd7a03ab8ddf99c0a68af99921d3f5090..10fba1e97b967fbc04c62a0a6d7d9648ce1c51fb 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2612,6 +2612,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,
 
 	update->backend_data = lock;
 
+	if (update->flags & REF_LOG_ONLY)
+		goto out;
+
 	if (update->type & REF_ISSYMREF) {
 		if (update->flags & REF_NO_DEREF) {
 			/*
@@ -2830,13 +2833,16 @@ static int files_transaction_prepare(struct ref_store *ref_store,
 	 */
 	for (i = 0; i < transaction->nr; i++) {
 		struct ref_update *update = transaction->updates[i];
-		struct string_list_item *item =
-			string_list_append(&affected_refnames, update->refname);
+		struct string_list_item *item;
 
 		if ((update->flags & REF_IS_PRUNING) &&
 		    !(update->flags & REF_NO_DEREF))
 			BUG("REF_IS_PRUNING set without REF_NO_DEREF");
 
+		if (update->flags & REF_LOG_ONLY)
+			continue;
+
+		item = string_list_append(&affected_refnames, update->refname);
 		/*
 		 * We store a pointer to update in item->util, but at
 		 * the moment we never use the value of this field
@@ -3036,8 +3042,9 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
 
 	/* Fail if a refname appears more than once in the transaction: */
 	for (i = 0; i < transaction->nr; i++)
-		string_list_append(&affected_refnames,
-				   transaction->updates[i]->refname);
+		if (!(transaction->updates[i]->flags & REF_LOG_ONLY))
+			string_list_append(&affected_refnames,
+					   transaction->updates[i]->refname);
 	string_list_sort(&affected_refnames);
 	if (ref_update_reject_duplicates(&affected_refnames, err)) {
 		ret = TRANSACTION_GENERIC_ERROR;
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index b2e3ba877de9e59fea5a4d066eb13e60ef22a32b..d9d2e28122a00ddd7f835c35a5851e390761885b 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -990,8 +990,9 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
 		if (ret)
 			goto done;
 
-		string_list_append(&affected_refnames,
-				   transaction->updates[i]->refname);
+		if (!(transaction->updates[i]->flags & REF_LOG_ONLY))
+			string_list_append(&affected_refnames,
+					   transaction->updates[i]->refname);
 	}
 
 	/*
@@ -1302,6 +1303,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 	struct ident_split committer_ident = {0};
 	size_t logs_nr = 0, logs_alloc = 0, i;
 	const char *committer_info;
+	struct strintmap logs_ts;
 	int ret = 0;
 
 	committer_info = git_committer_info(0);
@@ -1310,6 +1312,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 
 	QSORT(arg->updates, arg->updates_nr, transaction_update_cmp);
 
+	strintmap_init(&logs_ts, ts);
+
 	reftable_writer_set_limits(writer, ts, ts);
 
 	for (i = 0; i < arg->updates_nr; i++) {
@@ -1391,6 +1395,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 
 			if (create_reflog) {
 				struct ident_split c;
+				uint64_t update_index;
 
 				ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
 				log = &logs[logs_nr++];
@@ -1405,7 +1410,11 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 				}
 
 				fill_reftable_log_record(log, &c);
-				log->update_index = ts;
+
+				update_index = strintmap_get(&logs_ts, u->refname);
+				log->update_index = update_index;
+				strintmap_set(&logs_ts, u->refname, update_index+1);
+
 				log->refname = xstrdup(u->refname);
 				memcpy(log->value.update.new_hash,
 				       u->new_oid.hash, GIT_MAX_RAWSZ);
@@ -1476,6 +1485,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 
 done:
 	assert(ret != REFTABLE_API_ERROR);
+	strintmap_clear(&logs_ts);
 	for (i = 0; i < logs_nr; i++)
 		reftable_log_record_release(&logs[i]);
 	free(logs);
-- 
2.47.1
Previous: karthik nayakNext: Christian Couder
Message 20 of 30 in “refs: add reflog support to `git refs migrate`”
  1. 0/7 refs: add reflog support to `git refs migrate`Karthik Nayak, Dec 9, 2024
  2. 1/7 refs: include committer info in `ref_update` structKarthik Nayak, Dec 9, 2024
  3. Christian CouderDec 10, 2024
  4. karthik nayakDec 11, 2024
  5. 2/7 refs: add `index` field to `struct ref_udpate`Karthik Nayak, Dec 9, 2024
  6. 3/7 refs/files: add count field to ref_lockKarthik Nayak, Dec 9, 2024
  7. Christian CouderDec 10, 2024
  8. karthik nayakDec 11, 2024
  9. Christian CouderDec 11, 2024
  10. karthik nayakDec 11, 2024
  11. 4/7 refs: extract out refname verification in transactionsKarthik Nayak, Dec 9, 2024
  12. Christian CouderDec 11, 2024
  13. karthik nayakDec 11, 2024
  14. Patrick SteinhardtDec 11, 2024
  15. 5/7 refs: introduce the `ref_transaction_update_reflog` functionKarthik Nayak, Dec 9, 2024
  16. Christian CouderDec 11, 2024
  17. karthik nayakDec 11, 2024
  18. Patrick SteinhardtDec 11, 2024
  19. karthik nayakDec 11, 2024
  20. 6/7 refs: allow multiple reflog entries for the same refnameKarthik Nayak, Dec 9, 2024
  21. Christian CouderDec 11, 2024
  22. karthik nayakDec 12, 2024
  23. Patrick SteinhardtDec 11, 2024
  24. karthik nayakDec 12, 2024
  25. 7/7 refs: add support for migrating reflogsKarthik Nayak, Dec 9, 2024
  26. Patrick SteinhardtDec 11, 2024
  27. karthik nayakDec 12, 2024
  28. Junio C HamanoDec 10, 2024
  29. karthik nayakDec 10, 2024
  30. karthik nayakDec 10, 2024

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.