Skip to content

Commit 2ed1b64

Browse files
pks-tgitster
authored andcommitted
refs: skip hooks when deleting uncovered packed refs
When deleting refs from the loose-files refs backend, then we need to be careful to also delete the same ref from the packed refs backend, if it exists. If we don't, then deleting the loose ref would "uncover" the packed ref. We thus always have to queue up deletions of refs for both the loose and the packed refs backend. This is done in two separate transactions, where the end result is that the reference-transaction hook is executed twice for the deleted refs. This behaviour is quite misleading: it's exposing implementation details of how the files backend works to the user, in contrast to the logical updates that we'd really want to expose via the hook. Worse yet, whether the hook gets executed once or twice depends on how well-packed the repository is: if the ref only exists as a loose ref, then we execute it once, otherwise if it is also packed then we execute it twice. Fix this behaviour and don't execute the reference-transaction hook at all when refs in the packed-refs backend if it's driven by the files backend. This works as expected even in case the refs to be deleted only exist in the packed-refs backend because the loose-backend always queues refs in its own transaction even if they don't exist such that they can be locked for concurrent creation. And it also does the right thing in case neither of the backends has the ref because that would cause the transaction to fail completely. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ffad994 commit 2ed1b64

File tree

2 files changed

+7
-9
lines changed

2 files changed

+7
-9
lines changed

refs/files-backend.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,8 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg,
12611261
if (packed_refs_lock(refs->packed_ref_store, 0, &err))
12621262
goto error;
12631263

1264-
transaction = ref_store_transaction_begin(refs->packed_ref_store, 0, &err);
1264+
transaction = ref_store_transaction_begin(refs->packed_ref_store,
1265+
REF_TRANSACTION_SKIP_HOOK, &err);
12651266
if (!transaction)
12661267
goto error;
12671268

@@ -2776,7 +2777,8 @@ static int files_transaction_prepare(struct ref_store *ref_store,
27762777
*/
27772778
if (!packed_transaction) {
27782779
packed_transaction = ref_store_transaction_begin(
2779-
refs->packed_ref_store, 0, err);
2780+
refs->packed_ref_store,
2781+
REF_TRANSACTION_SKIP_HOOK, err);
27802782
if (!packed_transaction) {
27812783
ret = TRANSACTION_GENERIC_ERROR;
27822784
goto cleanup;
@@ -3047,7 +3049,8 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
30473049
&affected_refnames))
30483050
BUG("initial ref transaction called with existing refs");
30493051

3050-
packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, 0, err);
3052+
packed_transaction = ref_store_transaction_begin(refs->packed_ref_store,
3053+
REF_TRANSACTION_SKIP_HOOK, err);
30513054
if (!packed_transaction) {
30523055
ret = TRANSACTION_GENERIC_ERROR;
30533056
goto cleanup;

t/t1416-ref-transaction-hooks.sh

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,16 +175,11 @@ test_expect_success 'deleting packed ref calls hook once' '
175175
git update-ref -d refs/heads/to-be-deleted $POST_OID &&
176176
177177
# We only expect a single hook invocation, which is the logical
178-
# deletion. But currently, we see two interleaving transactions, once
179-
# for deleting the loose refs and once for deleting the packed ref.
178+
# deletion.
180179
cat >expect <<-EOF &&
181-
prepared
182-
$ZERO_OID $ZERO_OID refs/heads/to-be-deleted
183180
prepared
184181
$POST_OID $ZERO_OID refs/heads/to-be-deleted
185182
committed
186-
$ZERO_OID $ZERO_OID refs/heads/to-be-deleted
187-
committed
188183
$POST_OID $ZERO_OID refs/heads/to-be-deleted
189184
EOF
190185

0 commit comments

Comments
 (0)