| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='fetch/receive strict mode' |
| 4 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
| 5 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
| 6 | |
| 7 | . ./test-lib.sh |
| 8 | |
| 9 | test_expect_success 'setup and inject "corrupt or missing" object' ' |
| 10 | echo hello >greetings && |
| 11 | git add greetings && |
| 12 | git commit -m greetings && |
| 13 | |
| 14 | S=$(git rev-parse :greetings | sed -e "s|^..|&/|") && |
| 15 | X=$(echo bye | git hash-object -w --stdin | sed -e "s|^..|&/|") && |
| 16 | echo $S >S && |
| 17 | echo $X >X && |
| 18 | cp .git/objects/$S .git/objects/$S.back && |
| 19 | mv -f .git/objects/$X .git/objects/$S && |
| 20 | |
| 21 | test_must_fail git fsck |
| 22 | ' |
| 23 | |
| 24 | test_expect_success 'fetch without strict' ' |
| 25 | rm -rf dst && |
| 26 | git init dst && |
| 27 | ( |
| 28 | cd dst && |
| 29 | git config fetch.fsckobjects false && |
| 30 | git config transfer.fsckobjects false && |
| 31 | test_must_fail git fetch ../.git main |
| 32 | ) |
| 33 | ' |
| 34 | |
| 35 | test_expect_success 'fetch with !fetch.fsckobjects' ' |
| 36 | rm -rf dst && |
| 37 | git init dst && |
| 38 | ( |
| 39 | cd dst && |
| 40 | git config fetch.fsckobjects false && |
| 41 | git config transfer.fsckobjects true && |
| 42 | test_must_fail git fetch ../.git main |
| 43 | ) |
| 44 | ' |
| 45 | |
| 46 | test_expect_success 'fetch with fetch.fsckobjects' ' |
| 47 | rm -rf dst && |
| 48 | git init dst && |
| 49 | ( |
| 50 | cd dst && |
| 51 | git config fetch.fsckobjects true && |
| 52 | git config transfer.fsckobjects false && |
| 53 | test_must_fail git fetch ../.git main |
| 54 | ) |
| 55 | ' |
| 56 | |
| 57 | test_expect_success 'fetch with transfer.fsckobjects' ' |
| 58 | rm -rf dst && |
| 59 | git init dst && |
| 60 | ( |
| 61 | cd dst && |
| 62 | git config transfer.fsckobjects true && |
| 63 | test_must_fail git fetch ../.git main |
| 64 | ) |
| 65 | ' |
| 66 | |
| 67 | test_expect_success 'push without strict' ' |
| 68 | rm -rf dst && |
| 69 | git init dst && |
| 70 | ( |
| 71 | cd dst && |
| 72 | git config fetch.fsckobjects false && |
| 73 | git config transfer.fsckobjects false |
| 74 | ) && |
| 75 | cat >exp <<-\EOF && |
| 76 | To dst |
| 77 | ! refs/heads/main:refs/heads/test [remote rejected] (missing necessary objects) |
| 78 | Done |
| 79 | EOF |
| 80 | test_must_fail git push --porcelain dst main:refs/heads/test >act && |
| 81 | test_cmp exp act |
| 82 | ' |
| 83 | |
| 84 | test_expect_success 'push with !receive.fsckobjects' ' |
| 85 | rm -rf dst && |
| 86 | git init dst && |
| 87 | ( |
| 88 | cd dst && |
| 89 | git config receive.fsckobjects false && |
| 90 | git config transfer.fsckobjects true |
| 91 | ) && |
| 92 | test_must_fail git push --porcelain dst main:refs/heads/test >act && |
| 93 | test_cmp exp act |
| 94 | ' |
| 95 | |
| 96 | test_expect_success 'push with receive.fsckobjects' ' |
| 97 | rm -rf dst && |
| 98 | git init dst && |
| 99 | ( |
| 100 | cd dst && |
| 101 | git config receive.fsckobjects true && |
| 102 | git config transfer.fsckobjects false |
| 103 | ) && |
| 104 | cat >exp <<-\EOF && |
| 105 | To dst |
| 106 | ! refs/heads/main:refs/heads/test [remote rejected] (unpacker error) |
| 107 | EOF |
| 108 | test_must_fail git push --porcelain dst main:refs/heads/test >act && |
| 109 | test_cmp exp act |
| 110 | ' |
| 111 | |
| 112 | test_expect_success 'push with transfer.fsckobjects' ' |
| 113 | rm -rf dst && |
| 114 | git init dst && |
| 115 | ( |
| 116 | cd dst && |
| 117 | git config transfer.fsckobjects true |
| 118 | ) && |
| 119 | test_must_fail git push --porcelain dst main:refs/heads/test >act && |
| 120 | test_cmp exp act |
| 121 | ' |
| 122 | |
| 123 | test_expect_success 'repair the "corrupt or missing" object' ' |
| 124 | mv -f .git/objects/$(cat S) .git/objects/$(cat X) && |
| 125 | mv .git/objects/$(cat S).back .git/objects/$(cat S) && |
| 126 | rm -rf .git/objects/$(cat X) && |
| 127 | git fsck |
| 128 | ' |
| 129 | |
| 130 | test_expect_success 'setup bogus commit' ' |
| 131 | cat >bogus-commit <<-EOF && |
| 132 | tree $EMPTY_TREE |
| 133 | author Bugs Bunny 1234567890 +0000 |
| 134 | committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000 |
| 135 | |
| 136 | This commit object intentionally broken |
| 137 | EOF |
| 138 | commit="$(git hash-object --literally -t commit -w --stdin <bogus-commit)" |
| 139 | ' |
| 140 | |
| 141 | test_expect_success 'fsck with no skipList input' ' |
| 142 | test_must_fail git fsck 2>err && |
| 143 | test_grep "missingEmail" err |
| 144 | ' |
| 145 | |
| 146 | test_expect_success 'setup sorted and unsorted skipLists' ' |
| 147 | cat >SKIP.unsorted <<-EOF && |
| 148 | $(test_oid 004) |
| 149 | $(test_oid 002) |
| 150 | $commit |
| 151 | $(test_oid 001) |
| 152 | $(test_oid 003) |
| 153 | EOF |
| 154 | sort SKIP.unsorted >SKIP.sorted |
| 155 | ' |
| 156 | |
| 157 | test_expect_success 'fsck with sorted skipList' ' |
| 158 | git -c fsck.skipList=SKIP.sorted fsck |
| 159 | ' |
| 160 | |
| 161 | test_expect_success 'fsck with unsorted skipList' ' |
| 162 | git -c fsck.skipList=SKIP.unsorted fsck |
| 163 | ' |
| 164 | |
| 165 | test_expect_success 'fsck with invalid or bogus skipList input' ' |
| 166 | git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck && |
| 167 | test_must_fail git -c fsck.skipList -c fsck.missingEmail=ignore fsck 2>err && |
| 168 | test_grep "unable to parse '\'fsck.skiplist\'' from command-line config" err && |
| 169 | test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err && |
| 170 | test_grep "could not open.*: does-not-exist" err && |
| 171 | test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err && |
| 172 | test_grep "invalid object name: " err |
| 173 | ' |
| 174 | |
| 175 | test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' ' |
| 176 | cat >SKIP.with-comment <<-EOF && |
| 177 | # Some bad commit |
| 178 | $(test_oid 001) |
| 179 | EOF |
| 180 | test_must_fail git -c fsck.skipList=SKIP.with-comment fsck 2>err-with-comment && |
| 181 | test_grep "missingEmail" err-with-comment && |
| 182 | cat >SKIP.with-empty-line <<-EOF && |
| 183 | $(test_oid 001) |
| 184 | |
| 185 | $(test_oid 002) |
| 186 | EOF |
| 187 | test_must_fail git -c fsck.skipList=SKIP.with-empty-line fsck 2>err-with-empty-line && |
| 188 | test_grep "missingEmail" err-with-empty-line |
| 189 | ' |
| 190 | |
| 191 | test_expect_success 'fsck no garbage output from comments & empty lines errors' ' |
| 192 | test_line_count = 1 err-with-comment && |
| 193 | test_line_count = 1 err-with-empty-line |
| 194 | ' |
| 195 | |
| 196 | test_expect_success 'fsck with invalid abbreviated skipList input' ' |
| 197 | echo $commit | test_copy_bytes 20 >SKIP.abbreviated && |
| 198 | test_must_fail git -c fsck.skipList=SKIP.abbreviated fsck 2>err-abbreviated && |
| 199 | test_grep "^fatal: invalid object name: " err-abbreviated |
| 200 | ' |
| 201 | |
| 202 | test_expect_success 'fsck with exhaustive accepted skipList input (various types of comments etc.)' ' |
| 203 | >SKIP.exhaustive && |
| 204 | echo "# A commented line" >>SKIP.exhaustive && |
| 205 | echo "" >>SKIP.exhaustive && |
| 206 | echo " " >>SKIP.exhaustive && |
| 207 | echo " # Comment after whitespace" >>SKIP.exhaustive && |
| 208 | echo "$commit # Our bad commit (with leading whitespace and trailing comment)" >>SKIP.exhaustive && |
| 209 | echo "# Some bad commit (leading whitespace)" >>SKIP.exhaustive && |
| 210 | echo " $(test_oid 001)" >>SKIP.exhaustive && |
| 211 | git -c fsck.skipList=SKIP.exhaustive fsck 2>err && |
| 212 | test_must_be_empty err |
| 213 | ' |
| 214 | |
| 215 | test_expect_success 'receive-pack with missing receive.fsck.skipList path' ' |
| 216 | test_must_fail git -c receive.fsck.skipList receive-pack dst 2>err && |
| 217 | test_grep "unable to parse '\'receive.fsck.skiplist\'' from command-line config" err |
| 218 | ' |
| 219 | |
| 220 | test_expect_success 'push with receive.fsck.skipList' ' |
| 221 | git push . $commit:refs/heads/bogus && |
| 222 | rm -rf dst && |
| 223 | git init dst && |
| 224 | git --git-dir=dst/.git config receive.fsckObjects true && |
| 225 | test_must_fail git push --porcelain dst bogus && |
| 226 | echo $commit >dst/.git/SKIP && |
| 227 | |
| 228 | # receive.fsck.* does not fall back on fsck.* |
| 229 | git --git-dir=dst/.git config fsck.skipList SKIP && |
| 230 | test_must_fail git push --porcelain dst bogus && |
| 231 | |
| 232 | # Invalid and/or bogus skipList input |
| 233 | git --git-dir=dst/.git config receive.fsck.skipList /dev/null && |
| 234 | test_must_fail git push --porcelain dst bogus && |
| 235 | git --git-dir=dst/.git config receive.fsck.skipList does-not-exist && |
| 236 | test_must_fail git push --porcelain dst bogus 2>err && |
| 237 | test_grep "could not open.*: does-not-exist" err && |
| 238 | git --git-dir=dst/.git config receive.fsck.skipList config && |
| 239 | test_must_fail git push --porcelain dst bogus 2>err && |
| 240 | test_grep "invalid object name: " err && |
| 241 | |
| 242 | git --git-dir=dst/.git config receive.fsck.skipList SKIP && |
| 243 | git push --porcelain dst bogus |
| 244 | ' |
| 245 | |
| 246 | test_expect_success 'fetch with fetch.fsck.skipList' ' |
| 247 | refspec=refs/heads/bogus:refs/heads/bogus && |
| 248 | git push . $commit:refs/heads/bogus && |
| 249 | rm -rf dst && |
| 250 | git init dst && |
| 251 | git --git-dir=dst/.git config fetch.fsckObjects true && |
| 252 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && |
| 253 | git --git-dir=dst/.git config fetch.fsck.skipList /dev/null && |
| 254 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && |
| 255 | echo $commit >dst/.git/SKIP && |
| 256 | |
| 257 | # fetch.fsck.* does not fall back on fsck.* |
| 258 | git --git-dir=dst/.git config fsck.skipList dst/.git/SKIP && |
| 259 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && |
| 260 | |
| 261 | # Invalid and/or bogus skipList input |
| 262 | test_must_fail git --git-dir=dst/.git -c fetch.fsck.skipList fetch \ |
| 263 | "file://$(pwd)" $refspec 2>err && |
| 264 | test_grep "unable to parse '\'fetch.fsck.skiplist\'' from command-line config" err && |
| 265 | git --git-dir=dst/.git config fetch.fsck.skipList /dev/null && |
| 266 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && |
| 267 | git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist && |
| 268 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && |
| 269 | test_grep "could not open.*: does-not-exist" err && |
| 270 | git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config && |
| 271 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && |
| 272 | test_grep "invalid object name: " err && |
| 273 | |
| 274 | git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP && |
| 275 | git --git-dir=dst/.git fetch "file://$(pwd)" $refspec |
| 276 | ' |
| 277 | |
| 278 | test_expect_success 'fsck.<unknownmsg-id> dies' ' |
| 279 | test_must_fail git -c fsck.whatEver=ignore fsck 2>err && |
| 280 | test_grep "Unhandled message id: whatever" err |
| 281 | ' |
| 282 | |
| 283 | test_expect_success 'push with receive.fsck.missingEmail=warn' ' |
| 284 | git push . $commit:refs/heads/bogus && |
| 285 | rm -rf dst && |
| 286 | git init dst && |
| 287 | git --git-dir=dst/.git config receive.fsckobjects true && |
| 288 | test_must_fail git push --porcelain dst bogus && |
| 289 | |
| 290 | # receive.fsck.<msg-id> does not fall back on fsck.<msg-id> |
| 291 | git --git-dir=dst/.git config fsck.missingEmail warn && |
| 292 | test_must_fail git push --porcelain dst bogus && |
| 293 | |
| 294 | # receive.fsck.<unknownmsg-id> warns |
| 295 | git --git-dir=dst/.git config \ |
| 296 | receive.fsck.whatEver error && |
| 297 | |
| 298 | git --git-dir=dst/.git config \ |
| 299 | receive.fsck.missingEmail warn && |
| 300 | git push --porcelain dst bogus >act 2>&1 && |
| 301 | grep "missingEmail" act && |
| 302 | test_grep "skipping unknown msg id.*whatever" act && |
| 303 | git --git-dir=dst/.git branch -D bogus && |
| 304 | git --git-dir=dst/.git config --add \ |
| 305 | receive.fsck.missingEmail ignore && |
| 306 | git push --porcelain dst bogus >act 2>&1 && |
| 307 | ! grep "missingEmail" act |
| 308 | ' |
| 309 | |
| 310 | test_expect_success 'fetch with fetch.fsck.missingEmail=warn' ' |
| 311 | refspec=refs/heads/bogus:refs/heads/bogus && |
| 312 | git push . $commit:refs/heads/bogus && |
| 313 | rm -rf dst && |
| 314 | git init dst && |
| 315 | git --git-dir=dst/.git config fetch.fsckobjects true && |
| 316 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && |
| 317 | |
| 318 | # fetch.fsck.<msg-id> does not fall back on fsck.<msg-id> |
| 319 | git --git-dir=dst/.git config fsck.missingEmail warn && |
| 320 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && |
| 321 | |
| 322 | # receive.fsck.<unknownmsg-id> warns |
| 323 | git --git-dir=dst/.git config \ |
| 324 | fetch.fsck.whatEver error && |
| 325 | |
| 326 | git --git-dir=dst/.git config \ |
| 327 | fetch.fsck.missingEmail warn && |
| 328 | git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 && |
| 329 | grep "missingEmail" act && |
| 330 | test_grep "Skipping unknown msg id.*whatever" act && |
| 331 | rm -rf dst && |
| 332 | git init dst && |
| 333 | git --git-dir=dst/.git config fetch.fsckobjects true && |
| 334 | git --git-dir=dst/.git config \ |
| 335 | fetch.fsck.missingEmail ignore && |
| 336 | git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 && |
| 337 | ! grep "missingEmail" act |
| 338 | ' |
| 339 | |
| 340 | test_expect_success \ |
| 341 | 'receive.fsck.unterminatedHeader=warn triggers error' ' |
| 342 | rm -rf dst && |
| 343 | git init dst && |
| 344 | git --git-dir=dst/.git config receive.fsckobjects true && |
| 345 | git --git-dir=dst/.git config \ |
| 346 | receive.fsck.unterminatedheader warn && |
| 347 | test_must_fail git push --porcelain dst HEAD >act 2>&1 && |
| 348 | grep "Cannot demote unterminatedheader" act |
| 349 | ' |
| 350 | |
| 351 | test_expect_success \ |
| 352 | 'fetch.fsck.unterminatedHeader=warn triggers error' ' |
| 353 | rm -rf dst && |
| 354 | git init dst && |
| 355 | git --git-dir=dst/.git config fetch.fsckobjects true && |
| 356 | git --git-dir=dst/.git config \ |
| 357 | fetch.fsck.unterminatedheader warn && |
| 358 | test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" HEAD && |
| 359 | grep "Cannot demote unterminatedheader" act |
| 360 | ' |
| 361 | |
| 362 | test_expect_success PERL_TEST_HELPERS 'badFilemode is not a strict error' ' |
| 363 | git init --bare badmode.git && |
| 364 | tree=$( |
| 365 | cd badmode.git && |
| 366 | blob=$(echo blob | git hash-object -w --stdin | hex2oct) && |
| 367 | printf "123456 foo\0${blob}" | |
| 368 | git hash-object -t tree --stdin -w --literally |
| 369 | ) && |
| 370 | |
| 371 | rm -rf dst.git && |
| 372 | git init --bare dst.git && |
| 373 | git -C dst.git config transfer.fsckObjects true && |
| 374 | |
| 375 | git -C badmode.git push ../dst.git $tree:refs/tags/tree 2>err && |
| 376 | grep "$tree: badFilemode" err |
| 377 | ' |
| 378 | |
| 379 | test_done |