Skip to content

Commit 4f2ba2d

Browse files
pks-tgitster
authored andcommitted
refs: add interface to iterate over queued transactional updates
There is no way for a caller to see whether a reference update has already been queued up for a given reference transaction. There are multiple alternatives to provide this functionality: - We may add a function that simply tells us whether a specific reference has already been queued. If implemented naively then this would potentially be quadratic in runtime behaviour if this question is asked repeatedly because we have to iterate over all references every time. The alternative would be to add a hashmap of all queued reference updates to speed up the lookup, but this adds overhead to all callers. - We may add a flag to `ref_transaction_add_update()` that causes it to skip duplicates, but this has the same runtime concerns as the first alternative. - We may add an interface which lets callers collect all updates which have already been queued such that he can avoid re-adding them. This is the most flexible approach and puts the burden on the caller, but also allows us to not impact any of the existing callsites which don't need this information. This commit implements the last approach: it allows us to compute the map of already-queued updates once up front such that we can then skip all subsequent references which are already part of this map. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 62091b4 commit 4f2ba2d

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

refs.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,6 +2412,22 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
24122412
return refs->be->initial_transaction_commit(refs, transaction, err);
24132413
}
24142414

2415+
void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
2416+
ref_transaction_for_each_queued_update_fn cb,
2417+
void *cb_data)
2418+
{
2419+
int i;
2420+
2421+
for (i = 0; i < transaction->nr; i++) {
2422+
struct ref_update *update = transaction->updates[i];
2423+
2424+
cb(update->refname,
2425+
(update->flags & REF_HAVE_OLD) ? &update->old_oid : NULL,
2426+
(update->flags & REF_HAVE_NEW) ? &update->new_oid : NULL,
2427+
cb_data);
2428+
}
2429+
}
2430+
24152431
int refs_delete_refs(struct ref_store *refs, const char *logmsg,
24162432
struct string_list *refnames, unsigned int flags)
24172433
{

refs.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,20 @@ int ref_transaction_abort(struct ref_transaction *transaction,
770770
int initial_ref_transaction_commit(struct ref_transaction *transaction,
771771
struct strbuf *err);
772772

773+
/*
774+
* Execute the given callback function for each of the reference updates which
775+
* have been queued in the given transaction. `old_oid` and `new_oid` may be
776+
* `NULL` pointers depending on whether the update has these object IDs set or
777+
* not.
778+
*/
779+
typedef void ref_transaction_for_each_queued_update_fn(const char *refname,
780+
const struct object_id *old_oid,
781+
const struct object_id *new_oid,
782+
void *cb_data);
783+
void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
784+
ref_transaction_for_each_queued_update_fn cb,
785+
void *cb_data);
786+
773787
/*
774788
* Free `*transaction` and all associated data.
775789
*/

0 commit comments

Comments
 (0)