Skip to content

Commit 2caf589

Browse files
KarthikNayakgitster
authored andcommitted
refs: allow multiple reflog entries for the same refname
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b17521f commit 2caf589

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

refs/files-backend.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,6 +2612,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,
26122612

26132613
update->backend_data = lock;
26142614

2615+
if (update->flags & REF_LOG_ONLY)
2616+
goto out;
2617+
26152618
if (update->type & REF_ISSYMREF) {
26162619
if (update->flags & REF_NO_DEREF) {
26172620
/*
@@ -2830,13 +2833,16 @@ static int files_transaction_prepare(struct ref_store *ref_store,
28302833
*/
28312834
for (i = 0; i < transaction->nr; i++) {
28322835
struct ref_update *update = transaction->updates[i];
2833-
struct string_list_item *item =
2834-
string_list_append(&affected_refnames, update->refname);
2836+
struct string_list_item *item;
28352837

28362838
if ((update->flags & REF_IS_PRUNING) &&
28372839
!(update->flags & REF_NO_DEREF))
28382840
BUG("REF_IS_PRUNING set without REF_NO_DEREF");
28392841

2842+
if (update->flags & REF_LOG_ONLY)
2843+
continue;
2844+
2845+
item = string_list_append(&affected_refnames, update->refname);
28402846
/*
28412847
* We store a pointer to update in item->util, but at
28422848
* 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,
30363042

30373043
/* Fail if a refname appears more than once in the transaction: */
30383044
for (i = 0; i < transaction->nr; i++)
3039-
string_list_append(&affected_refnames,
3040-
transaction->updates[i]->refname);
3045+
if (!(transaction->updates[i]->flags & REF_LOG_ONLY))
3046+
string_list_append(&affected_refnames,
3047+
transaction->updates[i]->refname);
30413048
string_list_sort(&affected_refnames);
30423049
if (ref_update_reject_duplicates(&affected_refnames, err)) {
30433050
ret = TRANSACTION_GENERIC_ERROR;

refs/reftable-backend.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -990,8 +990,9 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
990990
if (ret)
991991
goto done;
992992

993-
string_list_append(&affected_refnames,
994-
transaction->updates[i]->refname);
993+
if (!(transaction->updates[i]->flags & REF_LOG_ONLY))
994+
string_list_append(&affected_refnames,
995+
transaction->updates[i]->refname);
995996
}
996997

997998
/*
@@ -1302,6 +1303,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
13021303
struct ident_split committer_ident = {0};
13031304
size_t logs_nr = 0, logs_alloc = 0, i;
13041305
const char *committer_info;
1306+
struct strintmap logs_ts;
13051307
int ret = 0;
13061308

13071309
committer_info = git_committer_info(0);
@@ -1310,6 +1312,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
13101312

13111313
QSORT(arg->updates, arg->updates_nr, transaction_update_cmp);
13121314

1315+
strintmap_init(&logs_ts, ts);
1316+
13131317
reftable_writer_set_limits(writer, ts, ts);
13141318

13151319
for (i = 0; i < arg->updates_nr; i++) {
@@ -1391,6 +1395,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
13911395

13921396
if (create_reflog) {
13931397
struct ident_split c;
1398+
uint64_t update_index;
13941399

13951400
ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
13961401
log = &logs[logs_nr++];
@@ -1405,7 +1410,11 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
14051410
}
14061411

14071412
fill_reftable_log_record(log, &c);
1408-
log->update_index = ts;
1413+
1414+
update_index = strintmap_get(&logs_ts, u->refname);
1415+
log->update_index = update_index;
1416+
strintmap_set(&logs_ts, u->refname, update_index+1);
1417+
14091418
log->refname = xstrdup(u->refname);
14101419
memcpy(log->value.update.new_hash,
14111420
u->new_oid.hash, GIT_MAX_RAWSZ);
@@ -1476,6 +1485,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
14761485

14771486
done:
14781487
assert(ret != REFTABLE_API_ERROR);
1488+
strintmap_clear(&logs_ts);
14791489
for (i = 0; i < logs_nr; i++)
14801490
reftable_log_record_release(&logs[i]);
14811491
free(logs);

0 commit comments

Comments
 (0)