3 test_description
='pre-commit and pre-merge-commit hooks'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 TEST_PASSES_SANITIZE_LEAK
=true
11 test_expect_success
'root commit' '
14 git commit -m "zeroth" &&
15 git checkout -b side &&
18 git commit -m "make it non-ff" &&
19 git branch side-orig side &&
23 test_expect_success
'setup conflicting branches' '
24 test_when_finished "git checkout main" &&
25 git checkout -b conflicting-a main &&
26 echo a >conflicting &&
27 git add conflicting &&
28 git commit -m conflicting-a &&
29 git checkout -b conflicting-b main &&
30 echo b >conflicting &&
31 git add conflicting &&
32 git commit -m conflicting-b
35 test_expect_success
'with no hook' '
36 test_when_finished "rm -f actual_hooks" &&
39 git commit -m "first" &&
40 test_path_is_missing actual_hooks
43 test_expect_success
'with no hook (merge)' '
44 test_when_finished "rm -f actual_hooks" &&
45 git branch -f side side-orig &&
47 git merge -m "merge main" main &&
49 test_path_is_missing actual_hooks
52 test_expect_success
'--no-verify with no hook' '
53 test_when_finished "rm -f actual_hooks" &&
56 git commit --no-verify -m "bar" &&
57 test_path_is_missing actual_hooks
60 test_expect_success
'--no-verify with no hook (merge)' '
61 test_when_finished "rm -f actual_hooks" &&
62 git branch -f side side-orig &&
64 git merge --no-verify -m "merge main" main &&
66 test_path_is_missing actual_hooks
69 setup_success_hook
() {
70 test_when_finished
"rm -f actual_hooks expected_hooks" &&
71 echo "$1" >expected_hooks
&&
73 echo $1 >>actual_hooks
77 test_expect_success
'with succeeding hook' '
78 setup_success_hook "pre-commit" &&
81 git commit -m "more" &&
82 test_cmp expected_hooks actual_hooks
85 test_expect_success
'with succeeding hook (merge)' '
86 setup_success_hook "pre-merge-commit" &&
88 git merge -m "merge main" main &&
90 test_cmp expected_hooks actual_hooks
93 test_expect_success
'automatic merge fails; both hooks are available' '
94 setup_success_hook "pre-commit" &&
95 setup_success_hook "pre-merge-commit" &&
97 git checkout conflicting-a &&
98 test_must_fail git merge -m "merge conflicting-b" conflicting-b &&
99 test_path_is_missing actual_hooks &&
101 echo "pre-commit" >expected_hooks &&
102 echo a+b >conflicting &&
103 git add conflicting &&
104 git commit -m "resolve conflict" &&
105 test_cmp expected_hooks actual_hooks
108 test_expect_success
'--no-verify with succeeding hook' '
109 setup_success_hook "pre-commit" &&
110 echo "even more" >>file &&
112 git commit --no-verify -m "even more" &&
113 test_path_is_missing actual_hooks
116 test_expect_success
'--no-verify with succeeding hook (merge)' '
117 setup_success_hook "pre-merge-commit" &&
118 git branch -f side side-orig &&
120 git merge --no-verify -m "merge main" main &&
122 test_path_is_missing actual_hooks
125 setup_failing_hook
() {
126 test_when_finished
"rm -f actual_hooks" &&
127 test_hook
"$1" <<-EOF
128 echo $1-failing-hook >>actual_hooks
133 test_expect_success
'with failing hook' '
134 setup_failing_hook "pre-commit" &&
135 test_when_finished "rm -f expected_hooks" &&
136 echo "pre-commit-failing-hook" >expected_hooks &&
138 echo "another" >>file &&
140 test_must_fail git commit -m "another" &&
141 test_cmp expected_hooks actual_hooks
144 test_expect_success
'--no-verify with failing hook' '
145 setup_failing_hook "pre-commit" &&
146 echo "stuff" >>file &&
148 git commit --no-verify -m "stuff" &&
149 test_path_is_missing actual_hooks
152 test_expect_success
'with failing hook (merge)' '
153 setup_failing_hook "pre-merge-commit" &&
154 echo "pre-merge-commit-failing-hook" >expected_hooks &&
156 test_must_fail git merge -m "merge main" main &&
158 test_cmp expected_hooks actual_hooks
161 test_expect_success
'--no-verify with failing hook (merge)' '
162 setup_failing_hook "pre-merge-commit" &&
164 git branch -f side side-orig &&
166 git merge --no-verify -m "merge main" main &&
168 test_path_is_missing actual_hooks
171 setup_non_exec_hook
() {
172 test_when_finished
"rm -f actual_hooks" &&
173 test_hook
"$1" <<-\EOF &&
174 echo non-exec >>actual_hooks
177 test_hook --disable "$1"
181 test_expect_success POSIXPERM 'with non-executable hook' '
182 setup_non_exec_hook "pre-commit" &&
183 echo "content" >>file &&
185 git commit -m "content" &&
186 test_path_is_missing actual_hooks
189 test_expect_success POSIXPERM '--no-verify with non-executable hook' '
190 setup_non_exec_hook "pre-commit" &&
191 echo "more content" >>file &&
193 git commit --no-verify -m "more content" &&
194 test_path_is_missing actual_hooks
197 test_expect_success POSIXPERM 'with non-executable hook (merge)' '
198 setup_non_exec_hook "pre-merge" &&
199 git branch -f side side-orig &&
201 git merge -m "merge main" main &&
203 test_path_is_missing actual_hooks
206 test_expect_success POSIXPERM '--no-verify with non-executable hook (merge)' '
207 setup_non_exec_hook "pre-merge" &&
208 git branch -f side side-orig &&
210 git merge --no-verify -m "merge main" main &&
212 test_path_is_missing actual_hooks
215 setup_require_prefix_hook () {
216 test_when_finished "rm -f expected_hooks" &&
217 echo require-prefix >expected_hooks &&
218 test_hook pre-commit <<-\
EOF
219 echo require-prefix >>actual_hooks
220 test $GIT_PREFIX = "success/"
224 test_expect_success 'with hook requiring GIT_PREFIX' '
225 test_when_finished "rm -rf actual_hooks success" &&
226 setup_require_prefix_hook &&
227 echo "more content" >>file &&
232 git commit -m "hook requires GIT_PREFIX = success/"
234 test_cmp expected_hooks actual_hooks
237 test_expect_success 'with failing hook requiring GIT_PREFIX' '
238 test_when_finished "rm -rf actual_hooks fail" &&
239 setup_require_prefix_hook &&
240 echo "more content" >>file &&
245 test_must_fail git commit -m "hook must fail"
247 git checkout -- file &&
248 test_cmp expected_hooks actual_hooks
251 setup_require_author_hook () {
252 test_when_finished "rm -f expected_hooks actual_hooks" &&
253 echo check-author >expected_hooks &&
254 test_hook pre-commit <<-\EOF
255 echo check-author >>actual_hooks
256 test "$GIT_AUTHOR_NAME" = "New Author" &&
257 test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com"
262 test_expect_success 'check the author in hook' '
263 setup_require_author_hook &&
264 cat >expected_hooks <<-EOF &&
269 test_must_fail git commit --allow-empty -m "by a.u.thor" &&
271 GIT_AUTHOR_NAME="New Author" &&
272 GIT_AUTHOR_EMAIL="newauthor@example.com" &&
273 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
274 git commit --allow-empty -m "by new.author via env" &&
277 git commit --author="New Author <newauthor@example.com>" \
278 --allow-empty -m "by new.author via command line" &&
280 test_cmp expected_hooks actual_hooks