Merge branch 'jk/log-cherry-pick-duplicate-patches'
[git] / t / t7503-pre-commit-and-pre-merge-commit-hooks.sh
1 #!/bin/sh
2
3 test_description='pre-commit and pre-merge-commit hooks'
4
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 . ./test-lib.sh
9
10 HOOKDIR="$(git rev-parse --git-dir)/hooks"
11 PRECOMMIT="$HOOKDIR/pre-commit"
12 PREMERGE="$HOOKDIR/pre-merge-commit"
13
14 # Prepare sample scripts that write their $0 to actual_hooks
15 test_expect_success 'sample script setup' '
16         mkdir -p "$HOOKDIR" &&
17         write_script "$HOOKDIR/success.sample" <<-\EOF &&
18         echo $0 >>actual_hooks
19         exit 0
20         EOF
21         write_script "$HOOKDIR/fail.sample" <<-\EOF &&
22         echo $0 >>actual_hooks
23         exit 1
24         EOF
25         write_script "$HOOKDIR/non-exec.sample" <<-\EOF &&
26         echo $0 >>actual_hooks
27         exit 1
28         EOF
29         chmod -x "$HOOKDIR/non-exec.sample" &&
30         write_script "$HOOKDIR/require-prefix.sample" <<-\EOF &&
31         echo $0 >>actual_hooks
32         test $GIT_PREFIX = "success/"
33         EOF
34         write_script "$HOOKDIR/check-author.sample" <<-\EOF
35         echo $0 >>actual_hooks
36         test "$GIT_AUTHOR_NAME" = "New Author" &&
37         test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com"
38         EOF
39 '
40
41 test_expect_success 'root commit' '
42         echo "root" >file &&
43         git add file &&
44         git commit -m "zeroth" &&
45         git checkout -b side &&
46         echo "foo" >foo &&
47         git add foo &&
48         git commit -m "make it non-ff" &&
49         git branch side-orig side &&
50         git checkout main
51 '
52
53 test_expect_success 'setup conflicting branches' '
54         test_when_finished "git checkout main" &&
55         git checkout -b conflicting-a main &&
56         echo a >conflicting &&
57         git add conflicting &&
58         git commit -m conflicting-a &&
59         git checkout -b conflicting-b main &&
60         echo b >conflicting &&
61         git add conflicting &&
62         git commit -m conflicting-b
63 '
64
65 test_expect_success 'with no hook' '
66         test_when_finished "rm -f actual_hooks" &&
67         echo "foo" >file &&
68         git add file &&
69         git commit -m "first" &&
70         test_path_is_missing actual_hooks
71 '
72
73 test_expect_success 'with no hook (merge)' '
74         test_when_finished "rm -f actual_hooks" &&
75         git branch -f side side-orig &&
76         git checkout side &&
77         git merge -m "merge main" main &&
78         git checkout main &&
79         test_path_is_missing actual_hooks
80 '
81
82 test_expect_success '--no-verify with no hook' '
83         test_when_finished "rm -f actual_hooks" &&
84         echo "bar" >file &&
85         git add file &&
86         git commit --no-verify -m "bar" &&
87         test_path_is_missing actual_hooks
88 '
89
90 test_expect_success '--no-verify with no hook (merge)' '
91         test_when_finished "rm -f actual_hooks" &&
92         git branch -f side side-orig &&
93         git checkout side &&
94         git merge --no-verify -m "merge main" main &&
95         git checkout main &&
96         test_path_is_missing actual_hooks
97 '
98
99 test_expect_success 'with succeeding hook' '
100         test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" &&
101         cp "$HOOKDIR/success.sample" "$PRECOMMIT" &&
102         echo "$PRECOMMIT" >expected_hooks &&
103         echo "more" >>file &&
104         git add file &&
105         git commit -m "more" &&
106         test_cmp expected_hooks actual_hooks
107 '
108
109 test_expect_success 'with succeeding hook (merge)' '
110         test_when_finished "rm -f \"$PREMERGE\" expected_hooks actual_hooks" &&
111         cp "$HOOKDIR/success.sample" "$PREMERGE" &&
112         echo "$PREMERGE" >expected_hooks &&
113         git checkout side &&
114         git merge -m "merge main" main &&
115         git checkout main &&
116         test_cmp expected_hooks actual_hooks
117 '
118
119 test_expect_success 'automatic merge fails; both hooks are available' '
120         test_when_finished "rm -f \"$PREMERGE\" \"$PRECOMMIT\"" &&
121         test_when_finished "rm -f expected_hooks actual_hooks" &&
122         test_when_finished "git checkout main" &&
123         cp "$HOOKDIR/success.sample" "$PREMERGE" &&
124         cp "$HOOKDIR/success.sample" "$PRECOMMIT" &&
125
126         git checkout conflicting-a &&
127         test_must_fail git merge -m "merge conflicting-b" conflicting-b &&
128         test_path_is_missing actual_hooks &&
129
130         echo "$PRECOMMIT" >expected_hooks &&
131         echo a+b >conflicting &&
132         git add conflicting &&
133         git commit -m "resolve conflict" &&
134         test_cmp expected_hooks actual_hooks
135 '
136
137 test_expect_success '--no-verify with succeeding hook' '
138         test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
139         cp "$HOOKDIR/success.sample" "$PRECOMMIT" &&
140         echo "even more" >>file &&
141         git add file &&
142         git commit --no-verify -m "even more" &&
143         test_path_is_missing actual_hooks
144 '
145
146 test_expect_success '--no-verify with succeeding hook (merge)' '
147         test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
148         cp "$HOOKDIR/success.sample" "$PREMERGE" &&
149         git branch -f side side-orig &&
150         git checkout side &&
151         git merge --no-verify -m "merge main" main &&
152         git checkout main &&
153         test_path_is_missing actual_hooks
154 '
155
156 test_expect_success 'with failing hook' '
157         test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" &&
158         cp "$HOOKDIR/fail.sample" "$PRECOMMIT" &&
159         echo "$PRECOMMIT" >expected_hooks &&
160         echo "another" >>file &&
161         git add file &&
162         test_must_fail git commit -m "another" &&
163         test_cmp expected_hooks actual_hooks
164 '
165
166 test_expect_success '--no-verify with failing hook' '
167         test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
168         cp "$HOOKDIR/fail.sample" "$PRECOMMIT" &&
169         echo "stuff" >>file &&
170         git add file &&
171         git commit --no-verify -m "stuff" &&
172         test_path_is_missing actual_hooks
173 '
174
175 test_expect_success 'with failing hook (merge)' '
176         test_when_finished "rm -f \"$PREMERGE\" expected_hooks actual_hooks" &&
177         cp "$HOOKDIR/fail.sample" "$PREMERGE" &&
178         echo "$PREMERGE" >expected_hooks &&
179         git checkout side &&
180         test_must_fail git merge -m "merge main" main &&
181         git checkout main &&
182         test_cmp expected_hooks actual_hooks
183 '
184
185 test_expect_success '--no-verify with failing hook (merge)' '
186         test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
187         cp "$HOOKDIR/fail.sample" "$PREMERGE" &&
188         git branch -f side side-orig &&
189         git checkout side &&
190         git merge --no-verify -m "merge main" main &&
191         git checkout main &&
192         test_path_is_missing actual_hooks
193 '
194
195 test_expect_success POSIXPERM 'with non-executable hook' '
196         test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
197         cp "$HOOKDIR/non-exec.sample" "$PRECOMMIT" &&
198         echo "content" >>file &&
199         git add file &&
200         git commit -m "content" &&
201         test_path_is_missing actual_hooks
202 '
203
204 test_expect_success POSIXPERM '--no-verify with non-executable hook' '
205         test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" &&
206         cp "$HOOKDIR/non-exec.sample" "$PRECOMMIT" &&
207         echo "more content" >>file &&
208         git add file &&
209         git commit --no-verify -m "more content" &&
210         test_path_is_missing actual_hooks
211 '
212
213 test_expect_success POSIXPERM 'with non-executable hook (merge)' '
214         test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
215         cp "$HOOKDIR/non-exec.sample" "$PREMERGE" &&
216         git branch -f side side-orig &&
217         git checkout side &&
218         git merge -m "merge main" main &&
219         git checkout main &&
220         test_path_is_missing actual_hooks
221 '
222
223 test_expect_success POSIXPERM '--no-verify with non-executable hook (merge)' '
224         test_when_finished "rm -f \"$PREMERGE\" actual_hooks" &&
225         cp "$HOOKDIR/non-exec.sample" "$PREMERGE" &&
226         git branch -f side side-orig &&
227         git checkout side &&
228         git merge --no-verify -m "merge main" main &&
229         git checkout main &&
230         test_path_is_missing actual_hooks
231 '
232
233 test_expect_success 'with hook requiring GIT_PREFIX' '
234         test_when_finished "rm -rf \"$PRECOMMIT\" expected_hooks actual_hooks success" &&
235         cp "$HOOKDIR/require-prefix.sample" "$PRECOMMIT" &&
236         echo "$PRECOMMIT" >expected_hooks &&
237         echo "more content" >>file &&
238         git add file &&
239         mkdir success &&
240         (
241                 cd success &&
242                 git commit -m "hook requires GIT_PREFIX = success/"
243         ) &&
244         test_cmp expected_hooks actual_hooks
245 '
246
247 test_expect_success 'with failing hook requiring GIT_PREFIX' '
248         test_when_finished "rm -rf \"$PRECOMMIT\" expected_hooks actual_hooks fail" &&
249         cp "$HOOKDIR/require-prefix.sample" "$PRECOMMIT" &&
250         echo "$PRECOMMIT" >expected_hooks &&
251         echo "more content" >>file &&
252         git add file &&
253         mkdir fail &&
254         (
255                 cd fail &&
256                 test_must_fail git commit -m "hook must fail"
257         ) &&
258         git checkout -- file &&
259         test_cmp expected_hooks actual_hooks
260 '
261
262 test_expect_success 'check the author in hook' '
263         test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" &&
264         cp "$HOOKDIR/check-author.sample" "$PRECOMMIT" &&
265         cat >expected_hooks <<-EOF &&
266         $PRECOMMIT
267         $PRECOMMIT
268         $PRECOMMIT
269         EOF
270         test_must_fail git commit --allow-empty -m "by a.u.thor" &&
271         (
272                 GIT_AUTHOR_NAME="New Author" &&
273                 GIT_AUTHOR_EMAIL="newauthor@example.com" &&
274                 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
275                 git commit --allow-empty -m "by new.author via env" &&
276                 git show -s
277         ) &&
278         git commit --author="New Author <newauthor@example.com>" \
279                 --allow-empty -m "by new.author via command line" &&
280         git show -s &&
281         test_cmp expected_hooks actual_hooks
282 '
283
284 test_done