aboutsummaryrefslogtreecommitdiffstats
path: root/refs.c
diff options
context:
space:
mode:
authorKarthik Nayak <karthik.188@gmail.com>2025-01-15 11:54:51 +0000
committerJunio C Hamano <gitster@pobox.com>2025-01-15 09:12:09 -0800
commitbc67b4ab5f8bc268ecd2d9bb7dc1b7bf26884a8e (patch)
tree16524e1388f4d785ba359eb507b7755d3d114c3b /refs.c
parentrefs: mark invalid refname message for translation (diff)
downloadgit-bc67b4ab5f8bc268ecd2d9bb7dc1b7bf26884a8e.tar.gz
git-bc67b4ab5f8bc268ecd2d9bb7dc1b7bf26884a8e.zip
reftable: write correct max_update_index to header
In 297c09eabb (refs: allow multiple reflog entries for the same refname, 2024-12-16), the reftable backend learned to handle multiple reflog entries within the same transaction. This was done modifying the `update_index` for reflogs with multiple indices. During writing the logs, the `max_update_index` of the writer was modified to ensure the limits were raised to the modified `update_index`s. However, since ref entries are written before the modification to the `max_update_index`, if there are multiple blocks to be written, the reftable backend writes the header with the old `max_update_index`. When all logs are finally written, the footer will be written with the new `min_update_index`. This causes a mismatch between the header and the footer and causes the reftable file to be corrupted. The existing tests only spawn a single block and since headers are lazily written with the first block, the tests didn't capture this bug. To fix the issue, the appropriate `max_update_index` limit must be set even before the first block is written. Add a `max_index` field to the transaction which holds the `max_index` within all its updates, then propagate this value to the reftable backend, wherein this is used to the set the `max_update_index` correctly. Add a test which creates a few thousand reference updates with multiple reflog entries, which should trigger the bug. Reported-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/refs.c b/refs.c
index c555839869..a5851a7de0 100644
--- a/refs.c
+++ b/refs.c
@@ -1297,6 +1297,13 @@ int ref_transaction_update_reflog(struct ref_transaction *transaction,
update->flags &= ~REF_HAVE_OLD;
update->index = index;
+ /*
+ * Reference backends may need to know the max index to optimize
+ * their writes. So we store the max_index on the transaction level.
+ */
+ if (index > transaction->max_index)
+ transaction->max_index = index;
+
return 0;
}