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

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

From
Karthik Nayak <karthik.188@gmail.com>
Date
Dec 15, 2024, 16:25 UTC
Message-ID
<20241215-320-git-refs-migrate-reflogs-v3-7-4127fe707b98@gmail.com>
In-Reply-To
<20241215-320-git-refs-migrate-reflogs-v3-0-4127fe707b98@gmail.com>

The reference transaction only allows a single 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.

In the reftable backend, the writer sorts all updates based on the update_index before writing to the block. When there are multiple reflogs for a given refname, it is essential that the order of the reflogs is maintained. So add the `index` value to the `update_index`. The `index` field is only set when multiple reflog entries for a given refname are added and as such in most scenarios the old behavior remains.

This is required to add reflog migration support to `git refs migrate`.
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
---
 refs/files-backend.c    | 15 +++++++++++----
 refs/reftable-backend.c | 22 +++++++++++++++++++---
 2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index c11213f52065bcf2fa7612df8f9500692ee2d02c..8953d1c6d37b13b0db701888b3db92fd87a68aaa 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2611,6 +2611,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) {
 			/*
@@ -2829,13 +2832,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
@@ -3035,8 +3041,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..bec5962debea7b62572d08f6fa8fd38ab4cd8af6 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);
 	}
 
 	/*
@@ -1301,6 +1302,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 	struct reftable_log_record *logs = NULL;
 	struct ident_split committer_ident = {0};
 	size_t logs_nr = 0, logs_alloc = 0, i;
+	uint64_t max_update_index = ts;
 	const char *committer_info;
 	int ret = 0;
 
@@ -1405,7 +1407,19 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 				}
 
 				fill_reftable_log_record(log, &c);
-				log->update_index = ts;
+
+				/*
+				 * Updates are sorted by the writer. So updates for the same
+				 * refname need to contain different update indices.
+				 */
+				log->update_index = ts + u->index;
+
+				/*
+				 * Note the max update_index so the limit can be set later on.
+				 */
+				if (log->update_index > max_update_index)
+					max_update_index = log->update_index;
+
 				log->refname = xstrdup(u->refname);
 				memcpy(log->value.update.new_hash,
 				       u->new_oid.hash, GIT_MAX_RAWSZ);
@@ -1469,6 +1483,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 	 * and log blocks.
 	 */
 	if (logs) {
+		reftable_writer_set_limits(writer, ts, max_update_index);
+
 		ret = reftable_writer_add_logs(writer, logs, logs_nr);
 		if (ret < 0)
 			goto done;
-- 
2.47.1
Previous: Karthik NayakNext: Karthik Nayak
Message 28 of 63 in “refs: add reflog support to `git refs migrate`”
  1. 0/8 refs: add reflog support to `git refs migrate`Karthik Nayak, Dec 13, 2024
  2. 1/8 refs: include committer info in `ref_update` structKarthik Nayak, Dec 13, 2024
  3. 2/8 refs: add `index` field to `struct ref_udpate`Karthik Nayak, Dec 13, 2024
  4. 3/8 refs/files: add count field to ref_lockKarthik Nayak, Dec 13, 2024
  5. 4/8 refs: extract out refname verification in transactionsKarthik Nayak, Dec 13, 2024
  6. 5/8 refs: add `committer_info` to `ref_transaction_add_update()`Karthik Nayak, Dec 13, 2024
  7. Patrick SteinhardtDec 13, 2024
  8. karthik nayakDec 13, 2024
  9. Toon ClaesDec 19, 2024
  10. karthik nayakDec 20, 2024
  11. 6/8 refs: introduce the `ref_transaction_update_reflog` functionKarthik Nayak, Dec 13, 2024
  12. Christian CouderDec 13, 2024
  13. karthik nayakDec 13, 2024
  14. Patrick SteinhardtDec 13, 2024
  15. 7/8 refs: allow multiple reflog entries for the same refnameKarthik Nayak, Dec 13, 2024
  16. Patrick SteinhardtDec 13, 2024
  17. karthik nayakDec 13, 2024
  18. 8/8 refs: add support for migrating reflogsKarthik Nayak, Dec 13, 2024
  19. Patrick SteinhardtDec 13, 2024
  20. karthik nayakDec 15, 2024
  21. 0/8 refs: add reflog support to `git refs migrate`Karthik Nayak, Dec 15, 2024
  22. 1/8 refs: include committer info in `ref_update` structKarthik Nayak, Dec 15, 2024
  23. 2/8 refs: add `index` field to `struct ref_udpate`Karthik Nayak, Dec 15, 2024
  24. 3/8 refs/files: add count field to ref_lockKarthik Nayak, Dec 15, 2024
  25. 4/8 refs: extract out refname verification in transactionsKarthik Nayak, Dec 15, 2024
  26. 5/8 refs: add `committer_info` to `ref_transaction_add_update()`Karthik Nayak, Dec 15, 2024
  27. 6/8 refs: introduce the `ref_transaction_update_reflog` functionKarthik Nayak, Dec 15, 2024
  28. 7/8 refs: allow multiple reflog entries for the same refnameKarthik Nayak, Dec 15, 2024
  29. 8/8 refs: add support for migrating reflogsKarthik Nayak, Dec 15, 2024
  30. Patrick SteinhardtDec 16, 2024
  31. Junio C HamanoDec 16, 2024
  32. karthik nayakDec 16, 2024
  33. Junio C HamanoDec 15, 2024
  34. karthik nayakDec 16, 2024
  35. Junio C HamanoDec 16, 2024
  36. 0/8 refs: add reflog support to `git refs migrate`Karthik Nayak, Dec 16, 2024
  37. 1/8 refs: include committer info in `ref_update` structKarthik Nayak, Dec 16, 2024
  38. 2/8 refs: add `index` field to `struct ref_udpate`Karthik Nayak, Dec 16, 2024
  39. Toon ClaesDec 19, 2024
  40. karthik nayakDec 20, 2024
  41. 3/8 refs/files: add count field to ref_lockKarthik Nayak, Dec 16, 2024
  42. 4/8 refs: extract out refname verification in transactionsKarthik Nayak, Dec 16, 2024
  43. Toon ClaesDec 19, 2024
  44. karthik nayakDec 20, 2024
  45. 5/8 refs: add `committer_info` to `ref_transaction_add_update()`Karthik Nayak, Dec 16, 2024
  46. Toon ClaesDec 19, 2024
  47. karthik nayakDec 20, 2024
  48. 6/8 refs: introduce the `ref_transaction_update_reflog` functionKarthik Nayak, Dec 16, 2024
  49. Toon ClaesDec 19, 2024
  50. Junio C HamanoDec 19, 2024
  51. karthik nayakDec 20, 2024
  52. refs: mark invalid refname message for translationKarthik Nayak, Dec 20, 2024
  53. Junio C HamanoDec 20, 2024
  54. Toon ClaesDec 24, 2024
  55. 7/8 refs: allow multiple reflog entries for the same refnameKarthik Nayak, Dec 16, 2024
  56. Toon ClaesDec 19, 2024
  57. karthik nayakDec 20, 2024
  58. 8/8 refs: add support for migrating reflogsKarthik Nayak, Dec 16, 2024
  59. Patrick SteinhardtDec 17, 2024
  60. karthik nayakDec 17, 2024
  61. Junio C HamanoDec 17, 2024
  62. Toon ClaesDec 19, 2024
  63. karthik nayakDec 20, 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.