test-lib-functions: add and use a "test_hook" wrapper

Add a "test_hook" wrapper similar to the existing "test_config" wrapper added in d960c47a881 (test-lib: add helper functions for config, 2011-08-17). This wrapper: - Will clean up the hook with "test_when_finished", unless --setup is provided. - Will error if we clobber a hook, unless --clobber is provided. - Takes a name like "update" instead of ".git/hooks/update". - Accepts -C <dir>, like "test_config" and "test_commit". By using a wrapper we'll be able to easily change all the hook-related code that assumes that the template-created ".git/hooks" directory is created by "init", "clone" etc. once another topic follows-up and changes the test suite to stop creating trash directories using those templates. In addition this will make it easy to have the hooks configured using the "configuration-based hooks" topic, once we get around to integrating that. I.e. we'll be able to run the tests in a mode where we sometimes create a .git/hooks/<name>, and other times create a script in another location, and point the relevant configuration snippet to it. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Mar 17, 2022 at 11:13 UTC 7da7f63cf9950d0ecd83579b4ca28f7b2805bf32
13 files changed +97 -43
t/t1416-ref-transaction-hooks.sh
+12 -14
@@ -16,9 +16,8 @@ test_expect_success setup '
16 '
17
18 test_expect_success 'hook allows updating ref if successful' '
19 - test_when_finished "rm .git/hooks/reference-transaction" &&
19 git reset --hard PRE &&
21 - write_script .git/hooks/reference-transaction <<-\EOF &&
20 + test_hook reference-transaction <<-\EOF &&
21 echo "$*" >>actual
22 EOF
23 cat >expect <<-EOF &&
@@ -30,9 +29,8 @@ test_expect_success 'hook allows updating ref if successful' '
29 '
30
31 test_expect_success 'hook aborts updating ref in prepared state' '
33 - test_when_finished "rm .git/hooks/reference-transaction" &&
32 git reset --hard PRE &&
35 - write_script .git/hooks/reference-transaction <<-\EOF &&
33 + test_hook reference-transaction <<-\EOF &&
34 if test "$1" = prepared
35 then
36 exit 1
@@ -43,9 +41,9 @@ test_expect_success 'hook aborts updating ref in prepared state' '
41 '
42
43 test_expect_success 'hook gets all queued updates in prepared state' '
46 - test_when_finished "rm .git/hooks/reference-transaction actual" &&
44 + test_when_finished "rm actual" &&
45 git reset --hard PRE &&
48 - write_script .git/hooks/reference-transaction <<-\EOF &&
46 + test_hook reference-transaction <<-\EOF &&
47 if test "$1" = prepared
48 then
49 while read -r line
@@ -66,9 +64,9 @@ test_expect_success 'hook gets all queued updates in prepared state' '
64 '
65
66 test_expect_success 'hook gets all queued updates in committed state' '
69 - test_when_finished "rm .git/hooks/reference-transaction actual" &&
67 + test_when_finished "rm actual" &&
68 git reset --hard PRE &&
71 - write_script .git/hooks/reference-transaction <<-\EOF &&
69 + test_hook reference-transaction <<-\EOF &&
70 if test "$1" = committed
71 then
72 while read -r line
@@ -86,9 +84,9 @@ test_expect_success 'hook gets all queued updates in committed state' '
84 '
85
86 test_expect_success 'hook gets all queued updates in aborted state' '
89 - test_when_finished "rm .git/hooks/reference-transaction actual" &&
87 + test_when_finished "rm actual" &&
88 git reset --hard PRE &&
91 - write_script .git/hooks/reference-transaction <<-\EOF &&
89 + test_hook reference-transaction <<-\EOF &&
90 if test "$1" = aborted
91 then
92 while read -r line
@@ -115,11 +113,11 @@ test_expect_success 'interleaving hook calls succeed' '
113
114 git init --bare target-repo.git &&
115
118 - write_script target-repo.git/hooks/reference-transaction <<-\EOF &&
116 + test_hook -C target-repo.git reference-transaction <<-\EOF &&
117 echo $0 "$@" >>actual
118 EOF
119
122 - write_script target-repo.git/hooks/update <<-\EOF &&
120 + test_hook -C target-repo.git update <<-\EOF &&
121 echo $0 "$@" >>actual
122 EOF
123
@@ -140,7 +138,7 @@ test_expect_success 'hook does not get called on packing refs' '
138 # Pack references first such that we are in a known state.
139 git pack-refs --all &&
140
143 - write_script .git/hooks/reference-transaction <<-\EOF &&
141 + test_hook reference-transaction <<-\EOF &&
142 echo "$@" >>actual
143 cat >>actual
144 EOF
@@ -166,7 +164,7 @@ test_expect_success 'deleting packed ref calls hook once' '
164 git update-ref refs/heads/to-be-deleted $POST_OID &&
165 git pack-refs --all &&
166
169 - write_script .git/hooks/reference-transaction <<-\EOF &&
167 + test_hook reference-transaction <<-\EOF &&
168 echo "$@" >>actual
169 cat >>actual
170 EOF
t/t1800-hook.sh
+8 -4
@@ -27,7 +27,7 @@ test_expect_success 'git hook run: nonexistent hook with --ignore-missing' '
27 '
28
29 test_expect_success 'git hook run: basic' '
30 - write_script .git/hooks/test-hook <<-EOF &&
30 + test_hook test-hook <<-EOF &&
31 echo Test hook
32 EOF
33
@@ -39,7 +39,7 @@ test_expect_success 'git hook run: basic' '
39 '
40
41 test_expect_success 'git hook run: stdout and stderr both write to our stderr' '
42 - write_script .git/hooks/test-hook <<-EOF &&
42 + test_hook test-hook <<-EOF &&
43 echo >&1 Will end up on stderr
44 echo >&2 Will end up on stderr
45 EOF
@@ -84,7 +84,7 @@ test_expect_success 'git hook run arg u ments without -- is not allowed' '
84 '
85
86 test_expect_success 'git hook run -- pass arguments' '
87 - write_script .git/hooks/test-hook <<-\EOF &&
87 + test_hook test-hook <<-\EOF &&
88 echo $1
89 echo $2
90 EOF
@@ -99,7 +99,7 @@ test_expect_success 'git hook run -- pass arguments' '
99 '
100
101 test_expect_success 'git hook run -- out-of-repo runs excluded' '
102 - write_script .git/hooks/test-hook <<-EOF &&
102 + test_hook test-hook <<-EOF &&
103 echo Test hook
104 EOF
105
@@ -120,6 +120,10 @@ test_expect_success 'git -c core.hooksPath=<PATH> hook run' '
120 Hook ran four
121 EOF
122
123 + test_hook test-hook <<-EOF &&
124 + echo Test hook
125 + EOF
126 +
127 # Test various ways of specifying the path. See also
128 # t1350-config-hooks-path.sh
129 >actual &&
t/t5401-update-hooks.sh
+1 -1
@@ -136,7 +136,7 @@ test_expect_success 'send-pack stderr contains hook messages' '
136 '
137
138 test_expect_success 'pre-receive hook that forgets to read its input' '
139 - write_script victim.git/hooks/pre-receive <<-\EOF &&
139 + test_hook --clobber -C victim.git pre-receive <<-\EOF &&
140 exit 0
141 EOF
142 rm -f victim.git/hooks/update victim.git/hooks/post-update &&
t/t5406-remote-rejects.sh
+1 -1
@@ -5,7 +5,7 @@ test_description='remote push rejects are reported by client'
5 . ./test-lib.sh
6
7 test_expect_success 'setup' '
8 - write_script .git/hooks/update <<-\EOF &&
8 + test_hook update <<-\EOF &&
9 exit 1
10 EOF
11 echo 1 >file &&
t/t5409-colorize-remote-messages.sh
+1 -1
@@ -5,7 +5,7 @@ test_description='remote messages are colorized on the client'
5 . ./test-lib.sh
6
7 test_expect_success 'setup' '
8 - write_script .git/hooks/update <<-\EOF &&
8 + test_hook --setup update <<-\EOF &&
9 echo error: error
10 echo ERROR: also highlighted
11 echo hint: hint
t/t5411-proc-receive-hook.sh
+2 -2
@@ -36,7 +36,7 @@ setup_upstream_and_workbench () {
36 TAG=$(git -C workbench rev-parse v123) &&
37
38 # setup pre-receive hook
39 - write_script upstream.git/hooks/pre-receive <<-\EOF &&
39 + test_hook --setup -C upstream.git pre-receive <<-\EOF &&
40 exec >&2
41 echo "# pre-receive hook"
42 while read old new ref
@@ -46,7 +46,7 @@ setup_upstream_and_workbench () {
46 EOF
47
48 # setup post-receive hook
49 - write_script upstream.git/hooks/post-receive <<-\EOF &&
49 + test_hook --setup -C upstream.git post-receive <<-\EOF &&
50 exec >&2
51 echo "# post-receive hook"
52 while read old new ref
t/t5503-tagfollow.sh
+2 -2
@@ -169,7 +169,7 @@ test_expect_success 'atomic fetch with failing backfill' '
169 # one of both fails to update correctly.
170 #
171 # To trigger failure we simply abort when backfilling a tag.
172 - write_script clone3/.git/hooks/reference-transaction <<-\EOF &&
172 + test_hook -C clone3 reference-transaction <<-\EOF &&
173 while read oldrev newrev reference
174 do
175 if test "$reference" = refs/tags/tag1
@@ -201,7 +201,7 @@ test_expect_success 'atomic fetch with backfill should use single transaction' '
201 $ZERO_OID $T refs/tags/tag1
202 EOF
203
204 - write_script clone4/.git/hooks/reference-transaction <<-\EOF &&
204 + test_hook -C clone4 reference-transaction <<-\EOF &&
205 ( echo "$*" && cat ) >>actual
206 EOF
207
t/t5510-fetch.sh
+4 -4
@@ -273,7 +273,7 @@ test_expect_success 'fetch --atomic executes a single reference transaction only
273 EOF
274
275 rm -f atomic/actual &&
276 - write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
276 + test_hook -C atomic reference-transaction <<-\EOF &&
277 ( echo "$*" && cat ) >>actual
278 EOF
279
@@ -306,7 +306,7 @@ test_expect_success 'fetch --atomic aborts all reference updates if hook aborts'
306 EOF
307
308 rm -f atomic/actual &&
309 - write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
309 + test_hook -C atomic/.git reference-transaction <<-\EOF &&
310 ( echo "$*" && cat ) >>actual
311 exit 1
312 EOF
@@ -334,7 +334,7 @@ test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' '
334 test_line_count = 2 atomic/.git/FETCH_HEAD &&
335 cp atomic/.git/FETCH_HEAD expected &&
336
337 - write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
337 + test_hook -C atomic reference-transaction <<-\EOF &&
338 exit 1
339 EOF
340
@@ -364,7 +364,7 @@ test_expect_success 'fetch --atomic --prune executes a single reference transact
364 $ZERO_OID $head_oid refs/remotes/origin/new-branch
365 EOF
366
367 - write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
367 + test_hook -C atomic reference-transaction <<-\EOF &&
368 ( echo "$*" && cat ) >>actual
369 EOF
370
t/t5521-pull-options.sh
+2 -2
@@ -233,7 +233,7 @@ test_expect_success 'git pull --no-verify flag passed to merge' '
233 git init src &&
234 test_commit -C src one &&
235 git clone src dst &&
236 - write_script dst/.git/hooks/commit-msg <<-\EOF &&
236 + test_hook -C dst commit-msg <<-\EOF &&
237 false
238 EOF
239 test_commit -C src two &&
@@ -245,7 +245,7 @@ test_expect_success 'git pull --no-verify --verify passed to merge' '
245 git init src &&
246 test_commit -C src one &&
247 git clone src dst &&
248 - write_script dst/.git/hooks/commit-msg <<-\EOF &&
248 + test_hook -C dst commit-msg <<-\EOF &&
249 false
250 EOF
251 test_commit -C src two &&
t/t5547-push-quarantine.sh
+2 -2
@@ -5,7 +5,7 @@ test_description='check quarantine of objects during push'
5
6 test_expect_success 'create picky dest repo' '
7 git init --bare dest.git &&
8 - write_script dest.git/hooks/pre-receive <<-\EOF
8 + test_hook --setup -C dest.git pre-receive <<-\EOF
9 while read old new ref; do
10 test "$(git log -1 --format=%s $new)" = reject && exit 1
11 done
@@ -60,7 +60,7 @@ test_expect_success 'push to repo path with path separator (colon)' '
60
61 test_expect_success 'updating a ref from quarantine is forbidden' '
62 git init --bare update.git &&
63 - write_script update.git/hooks/pre-receive <<-\EOF &&
63 + test_hook -C update.git pre-receive <<-\EOF &&
64 read old new refname
65 git update-ref refs/heads/unrelated $new
66 exit 1
t/t5548-push-porcelain.sh
+1 -1
@@ -168,7 +168,7 @@ run_git_push_porcelain_output_test() {
168 '
169
170 test_expect_success "prepare pre-receive hook ($PROTOCOL)" '
171 - write_script "$upstream/hooks/pre-receive" <<-EOF
171 + test_hook --setup -C "$upstream" pre-receive <<-EOF
172 exit 1
173 EOF
174 '
t/t7519-status-fsmonitor.sh
+9 -9
@@ -26,7 +26,7 @@ dirty_repo () {
26 }
27
28 write_integration_script () {
29 - write_script .git/hooks/fsmonitor-test<<-\EOF
29 + test_hook --setup --clobber fsmonitor-test<<-\EOF
30 if test "$#" -ne 2
31 then
32 echo "$0: exactly 2 arguments expected"
@@ -108,7 +108,7 @@ EOF
108
109 # test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit
110 test_expect_success 'update-index --fsmonitor-valid" sets the fsmonitor valid bit' '
111 - write_script .git/hooks/fsmonitor-test<<-\EOF &&
111 + test_hook fsmonitor-test<<-\EOF &&
112 printf "last_update_token\0"
113 EOF
114 git update-index --fsmonitor &&
@@ -169,7 +169,7 @@ EOF
169
170 # test that newly added files are marked valid
171 test_expect_success 'newly added files are marked valid' '
172 - write_script .git/hooks/fsmonitor-test<<-\EOF &&
172 + test_hook --setup --clobber fsmonitor-test<<-\EOF &&
173 printf "last_update_token\0"
174 EOF
175 git add new &&
@@ -210,7 +210,7 @@ EOF
210
211 # test that *only* files returned by the integration script get flagged as invalid
212 test_expect_success '*only* files returned by the integration script get flagged as invalid' '
213 - write_script .git/hooks/fsmonitor-test<<-\EOF &&
213 + test_hook --clobber fsmonitor-test<<-\EOF &&
214 printf "last_update_token\0"
215 printf "dir1/modified\0"
216 EOF
@@ -231,7 +231,7 @@ test_expect_success 'refresh_index() invalidates fsmonitor cache' '
231 dirty_repo &&
232 write_integration_script &&
233 git add . &&
234 - write_script .git/hooks/fsmonitor-test<<-\EOF &&
234 + test_hook --clobber fsmonitor-test<<-\EOF &&
235 EOF
236 git commit -m "to reset" &&
237 git reset HEAD~1 &&
@@ -280,7 +280,7 @@ do
280 # Make sure it's actually skipping the check for modified and untracked
281 # (if enabled) files unless it is told about them.
282 test_expect_success "status doesn't detect unreported modifications" '
283 - write_script .git/hooks/fsmonitor-test<<-\EOF &&
283 + test_hook --clobber fsmonitor-test<<-\EOF &&
284 printf "last_update_token\0"
285 :>marker
286 EOF
@@ -414,14 +414,14 @@ test_expect_success 'status succeeds with sparse index' '
414 git -C sparse sparse-checkout init --cone --sparse-index &&
415 git -C sparse sparse-checkout set dir1 dir2 &&
416
417 - write_script .git/hooks/fsmonitor-test <<-\EOF &&
417 + test_hook --clobber fsmonitor-test <<-\EOF &&
418 printf "last_update_token\0"
419 EOF
420 git -C full config core.fsmonitor ../.git/hooks/fsmonitor-test &&
421 git -C sparse config core.fsmonitor ../.git/hooks/fsmonitor-test &&
422 check_sparse_index_behavior ! &&
423
424 - write_script .git/hooks/fsmonitor-test <<-\EOF &&
424 + test_hook --clobber fsmonitor-test <<-\EOF &&
425 printf "last_update_token\0"
426 printf "dir1/modified\0"
427 EOF
@@ -439,7 +439,7 @@ test_expect_success 'status succeeds with sparse index' '
439
440 # This one modifies outside the sparse-checkout definition
441 # and hence we expect to expand the sparse-index.
442 - write_script .git/hooks/fsmonitor-test <<-\EOF &&
442 + test_hook --clobber fsmonitor-test <<-\EOF &&
443 printf "last_update_token\0"
444 printf "dir1a/modified\0"
445 EOF
t/test-lib-functions.sh
+52
@@ -551,6 +551,58 @@ write_script () {
551 chmod +x "$1"
552 }
553
554 +# Usage: test_hook [options] <hook-name> <<-\EOF
555 +#
556 +# -C <dir>:
557 +# Run all git commands in directory <dir>
558 +# --setup
559 +# Setup a hook for subsequent tests, i.e. don't remove it in a
560 +# "test_when_finished"
561 +# --clobber
562 +# Overwrite an existing <hook-name>, if it exists. Implies
563 +# --setup (i.e. the "test_when_finished" is assumed to have been
564 +# set up already).
565 +test_hook () {
566 + setup= &&
567 + clobber= &&
568 + indir= &&
569 + while test $# != 0
570 + do
571 + case "$1" in
572 + -C)
573 + indir="$2" &&
574 + shift
575 + ;;
576 + --setup)
577 + setup=t
578 + ;;
579 + --clobber)
580 + clobber=t
581 + ;;
582 + -*)
583 + BUG "invalid argument: $1"
584 + ;;
585 + *)
586 + break
587 + ;;
588 + esac &&
589 + shift
590 + done &&
591 +
592 + git_dir=$(git -C "$indir" rev-parse --absolute-git-dir) &&
593 + hook_dir="$git_dir/hooks" &&
594 + hook_file="$hook_dir/$1" &&
595 + if test -z "$clobber"
596 + then
597 + test_path_is_missing "$hook_file"
598 + fi &&
599 + if test -z "$setup$clobber"
600 + then
601 + test_when_finished "rm \"$hook_file\""
602 + fi &&
603 + write_script "$hook_file"
604 +}
605 +
606 # Use test_set_prereq to tell that a particular prerequisite is available.
607 # The prerequisite can later be checked for in two ways:
608 #