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