refs: skip hooks when deleting uncovered packed refs
commit2ed1b64ebdeefc7f9473ae159fb45ff0c6cf121a
authorPatrick Steinhardt <ps@pks.im>
Mon, 17 Jan 2022 08:12:53 +0000 (17 09:12 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 17 Jan 2022 19:01:45 +0000 (17 11:01 -0800)
tree496bc6a121deffd8b9ee7ef6b718a49b9f077df9
parentffad9941383465553bf26d88050f3243726f30df
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 <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs/files-backend.c
t/t1416-ref-transaction-hooks.sh