Subject: [PATCH 5/9] refs: avoid duplicate running of the reference-transaction hook

From: Jiang Xin <[email-masked]>
Date: Fri, 29 Jul 2022 18:12:41 +0800

From: Jiang Xin <[email-masked]>

If there are references to be deleted in a transaction, we should remove
each reference from both loose references and the "packed-refs" file.
The "reference-transaction" hook will run twice, once for the primary
ref-store (loose references), and another for the second ref-store (i.e.
packed ref-store).

To avoid duplicate running of the "reference-trancaction" hook, we pass
a special "hook-flags" parameter to initialize the second ref-store.
The "REF_TRANSACTION_RUN_PREPARED_HOOK" bit is preserved for the
transaction of the second ref-store because we may still want to call
command "reference-trancaction prepared" for some pre-checks, such as
terminate unwanted transaction for the "packed-refs" file.

The behavior of the following git commands and five testcases have been
fixed in t1416:

 * git cherry-pick
 * git rebase
 * git revert
 * git update-ref -d <ref>
 * git update-ref --stdin	# delete refs

Signed-off-by: Jiang Xin <[email-masked]>
---
 refs/files-backend.c             |  7 +++++--
 t/t1416-ref-transaction-hooks.sh | 10 +++++-----
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/refs/files-backend.c b/refs/files-backend.c
index 3be317d524..e8d12cb343 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2788,8 +2788,11 @@ static int files_transaction_prepare(struct ref_store *ref_store,
 			 * packed-refs if it exists there.
 			 */
 			if (!packed_transaction) {
-				packed_transaction = ref_store_transaction_begin(
-						refs->packed_ref_store, err);
+				packed_transaction = ref_store_transaction_begin_extended(
+						refs->packed_ref_store,
+						transaction->hook_flags &
+							REF_TRANSACTION_RUN_PREPARED_HOOK,
+						err);
 				if (!packed_transaction) {
 					ret = TRANSACTION_GENERIC_ERROR;
 					goto cleanup;
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 7f8fd012e8..21d5326575 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -407,7 +407,7 @@ test_expect_success "update-ref: update refs already packed to .git/packed-refs"
 	test_cmp_heads_and_tags -C workdir expect
 '
 
-test_expect_failure "update-ref: remove refs with mixed ref_stores" '
+test_expect_success "update-ref: remove refs with mixed ref_stores" '
 	test_when_finished "rm -f $HOOK_OUTPUT" &&
 
 	cat >expect <<-EOF &&
@@ -523,7 +523,7 @@ test_expect_success "update-ref --stdin: update refs" '
 	test_cmp_heads_and_tags -C workdir expect
 '
 
-test_expect_failure "update-ref --stdin: delete refs" '
+test_expect_success "update-ref --stdin: delete refs" '
 	test_when_finished "rm -f $HOOK_OUTPUT" &&
 
 	cat >expect <<-EOF &&
@@ -1023,7 +1023,7 @@ test_expect_success "worktree: topic2: merge" '
 	test_cmp_heads_and_tags -C workdir expect
 '
 
-test_expect_failure "worktree: topic3: cherry-pick" '
+test_expect_success "worktree: topic3: cherry-pick" '
 	test_when_finished "rm -f $HOOK_OUTPUT" &&
 
 	cat >expect <<-EOF &&
@@ -1067,7 +1067,7 @@ test_expect_failure "worktree: topic3: cherry-pick" '
 	test_cmp_heads_and_tags -C workdir expect
 '
 
-test_expect_failure "worktree: topic4: rebase" '
+test_expect_success "worktree: topic4: rebase" '
 	test_when_finished "rm -f $HOOK_OUTPUT" &&
 
 	cat >expect <<-EOF &&
@@ -1119,7 +1119,7 @@ test_expect_failure "worktree: topic4: rebase" '
 	test_cmp_heads_and_tags -C workdir expect
 '
 
-test_expect_failure "worktree: topic5: revert" '
+test_expect_success "worktree: topic5: revert" '
 	test_when_finished "rm -f $HOOK_OUTPUT" &&
 
 	cat >expect <<-EOF &&
-- 
2.36.1.25.gc87d5ad63a.dirty