t / t5516-fetch-push.shon commit Merge branch 'nd/diff-i-t-a' (d0c6922)
   1#!/bin/sh
   2
   3test_description='Basic fetch/push functionality.
   4
   5This test checks the following functionality:
   6
   7* command-line syntax
   8* refspecs
   9* fast-forward detection, and overriding it
  10* configuration
  11* hooks
  12* --porcelain output format
  13* hiderefs
  14* reflogs
  15'
  16
  17. ./test-lib.sh
  18
  19D=`pwd`
  20
  21mk_empty () {
  22        repo_name="$1"
  23        rm -fr "$repo_name" &&
  24        mkdir "$repo_name" &&
  25        (
  26                cd "$repo_name" &&
  27                git init &&
  28                git config receive.denyCurrentBranch warn &&
  29                mv .git/hooks .git/hooks-disabled
  30        )
  31}
  32
  33mk_test () {
  34        repo_name="$1"
  35        shift
  36
  37        mk_empty "$repo_name" &&
  38        (
  39                for ref in "$@"
  40                do
  41                        git push "$repo_name" $the_first_commit:refs/$ref ||
  42                        exit
  43                done &&
  44                cd "$repo_name" &&
  45                for ref in "$@"
  46                do
  47                        echo "$the_first_commit" >expect &&
  48                        git show-ref -s --verify refs/$ref >actual &&
  49                        test_cmp expect actual ||
  50                        exit
  51                done &&
  52                git fsck --full
  53        )
  54}
  55
  56mk_test_with_hooks() {
  57        repo_name=$1
  58        mk_test "$@" &&
  59        (
  60                cd "$repo_name" &&
  61                mkdir .git/hooks &&
  62                cd .git/hooks &&
  63
  64                cat >pre-receive <<-'EOF' &&
  65                #!/bin/sh
  66                cat - >>pre-receive.actual
  67                EOF
  68
  69                cat >update <<-'EOF' &&
  70                #!/bin/sh
  71                printf "%s %s %s\n" "$@" >>update.actual
  72                EOF
  73
  74                cat >post-receive <<-'EOF' &&
  75                #!/bin/sh
  76                cat - >>post-receive.actual
  77                EOF
  78
  79                cat >post-update <<-'EOF' &&
  80                #!/bin/sh
  81                for ref in "$@"
  82                do
  83                        printf "%s\n" "$ref" >>post-update.actual
  84                done
  85                EOF
  86
  87                chmod +x pre-receive update post-receive post-update
  88        )
  89}
  90
  91mk_child() {
  92        rm -rf "$2" &&
  93        git clone "$1" "$2"
  94}
  95
  96check_push_result () {
  97        repo_name="$1"
  98        shift
  99
 100        (
 101                cd "$repo_name" &&
 102                echo "$1" >expect &&
 103                shift &&
 104                for ref in "$@"
 105                do
 106                        git show-ref -s --verify refs/$ref >actual &&
 107                        test_cmp expect actual ||
 108                        exit
 109                done &&
 110                git fsck --full
 111        )
 112}
 113
 114test_expect_success setup '
 115
 116        >path1 &&
 117        git add path1 &&
 118        test_tick &&
 119        git commit -a -m repo &&
 120        the_first_commit=$(git show-ref -s --verify refs/heads/master) &&
 121
 122        >path2 &&
 123        git add path2 &&
 124        test_tick &&
 125        git commit -a -m second &&
 126        the_commit=$(git show-ref -s --verify refs/heads/master)
 127
 128'
 129
 130test_expect_success 'fetch without wildcard' '
 131        mk_empty testrepo &&
 132        (
 133                cd testrepo &&
 134                git fetch .. refs/heads/master:refs/remotes/origin/master &&
 135
 136                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 137                git for-each-ref refs/remotes/origin >actual &&
 138                test_cmp expect actual
 139        )
 140'
 141
 142test_expect_success 'fetch with wildcard' '
 143        mk_empty testrepo &&
 144        (
 145                cd testrepo &&
 146                git config remote.up.url .. &&
 147                git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
 148                git fetch up &&
 149
 150                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 151                git for-each-ref refs/remotes/origin >actual &&
 152                test_cmp expect actual
 153        )
 154'
 155
 156test_expect_success 'fetch with insteadOf' '
 157        mk_empty testrepo &&
 158        (
 159                TRASH=$(pwd)/ &&
 160                cd testrepo &&
 161                git config "url.$TRASH.insteadOf" trash/ &&
 162                git config remote.up.url trash/. &&
 163                git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
 164                git fetch up &&
 165
 166                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 167                git for-each-ref refs/remotes/origin >actual &&
 168                test_cmp expect actual
 169        )
 170'
 171
 172test_expect_success 'fetch with pushInsteadOf (should not rewrite)' '
 173        mk_empty testrepo &&
 174        (
 175                TRASH=$(pwd)/ &&
 176                cd testrepo &&
 177                git config "url.trash/.pushInsteadOf" "$TRASH" &&
 178                git config remote.up.url "$TRASH." &&
 179                git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
 180                git fetch up &&
 181
 182                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 183                git for-each-ref refs/remotes/origin >actual &&
 184                test_cmp expect actual
 185        )
 186'
 187
 188test_expect_success 'push without wildcard' '
 189        mk_empty testrepo &&
 190
 191        git push testrepo refs/heads/master:refs/remotes/origin/master &&
 192        (
 193                cd testrepo &&
 194                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 195                git for-each-ref refs/remotes/origin >actual &&
 196                test_cmp expect actual
 197        )
 198'
 199
 200test_expect_success 'push with wildcard' '
 201        mk_empty testrepo &&
 202
 203        git push testrepo "refs/heads/*:refs/remotes/origin/*" &&
 204        (
 205                cd testrepo &&
 206                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 207                git for-each-ref refs/remotes/origin >actual &&
 208                test_cmp expect actual
 209        )
 210'
 211
 212test_expect_success 'push with insteadOf' '
 213        mk_empty testrepo &&
 214        TRASH="$(pwd)/" &&
 215        test_config "url.$TRASH.insteadOf" trash/ &&
 216        git push trash/testrepo refs/heads/master:refs/remotes/origin/master &&
 217        (
 218                cd testrepo &&
 219                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 220                git for-each-ref refs/remotes/origin >actual &&
 221                test_cmp expect actual
 222        )
 223'
 224
 225test_expect_success 'push with pushInsteadOf' '
 226        mk_empty testrepo &&
 227        TRASH="$(pwd)/" &&
 228        test_config "url.$TRASH.pushInsteadOf" trash/ &&
 229        git push trash/testrepo refs/heads/master:refs/remotes/origin/master &&
 230        (
 231                cd testrepo &&
 232                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 233                git for-each-ref refs/remotes/origin >actual &&
 234                test_cmp expect actual
 235        )
 236'
 237
 238test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)' '
 239        mk_empty testrepo &&
 240        test_config "url.trash2/.pushInsteadOf" testrepo/ &&
 241        test_config "url.trash3/.pushInsteadOf" trash/wrong &&
 242        test_config remote.r.url trash/wrong &&
 243        test_config remote.r.pushurl "testrepo/" &&
 244        git push r refs/heads/master:refs/remotes/origin/master &&
 245        (
 246                cd testrepo &&
 247                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 248                git for-each-ref refs/remotes/origin >actual &&
 249                test_cmp expect actual
 250        )
 251'
 252
 253test_expect_success 'push with matching heads' '
 254
 255        mk_test testrepo heads/master &&
 256        git push testrepo : &&
 257        check_push_result testrepo $the_commit heads/master
 258
 259'
 260
 261test_expect_success 'push with matching heads on the command line' '
 262
 263        mk_test testrepo heads/master &&
 264        git push testrepo : &&
 265        check_push_result testrepo $the_commit heads/master
 266
 267'
 268
 269test_expect_success 'failed (non-fast-forward) push with matching heads' '
 270
 271        mk_test testrepo heads/master &&
 272        git push testrepo : &&
 273        git commit --amend -massaged &&
 274        test_must_fail git push testrepo &&
 275        check_push_result testrepo $the_commit heads/master &&
 276        git reset --hard $the_commit
 277
 278'
 279
 280test_expect_success 'push --force with matching heads' '
 281
 282        mk_test testrepo heads/master &&
 283        git push testrepo : &&
 284        git commit --amend -massaged &&
 285        git push --force testrepo : &&
 286        ! check_push_result testrepo $the_commit heads/master &&
 287        git reset --hard $the_commit
 288
 289'
 290
 291test_expect_success 'push with matching heads and forced update' '
 292
 293        mk_test testrepo heads/master &&
 294        git push testrepo : &&
 295        git commit --amend -massaged &&
 296        git push testrepo +: &&
 297        ! check_push_result testrepo $the_commit heads/master &&
 298        git reset --hard $the_commit
 299
 300'
 301
 302test_expect_success 'push with no ambiguity (1)' '
 303
 304        mk_test testrepo heads/master &&
 305        git push testrepo master:master &&
 306        check_push_result testrepo $the_commit heads/master
 307
 308'
 309
 310test_expect_success 'push with no ambiguity (2)' '
 311
 312        mk_test testrepo remotes/origin/master &&
 313        git push testrepo master:origin/master &&
 314        check_push_result testrepo $the_commit remotes/origin/master
 315
 316'
 317
 318test_expect_success 'push with colon-less refspec, no ambiguity' '
 319
 320        mk_test testrepo heads/master heads/t/master &&
 321        git branch -f t/master master &&
 322        git push testrepo master &&
 323        check_push_result testrepo $the_commit heads/master &&
 324        check_push_result testrepo $the_first_commit heads/t/master
 325
 326'
 327
 328test_expect_success 'push with weak ambiguity (1)' '
 329
 330        mk_test testrepo heads/master remotes/origin/master &&
 331        git push testrepo master:master &&
 332        check_push_result testrepo $the_commit heads/master &&
 333        check_push_result testrepo $the_first_commit remotes/origin/master
 334
 335'
 336
 337test_expect_success 'push with weak ambiguity (2)' '
 338
 339        mk_test testrepo heads/master remotes/origin/master remotes/another/master &&
 340        git push testrepo master:master &&
 341        check_push_result testrepo $the_commit heads/master &&
 342        check_push_result testrepo $the_first_commit remotes/origin/master remotes/another/master
 343
 344'
 345
 346test_expect_success 'push with ambiguity' '
 347
 348        mk_test testrepo heads/frotz tags/frotz &&
 349        test_must_fail git push testrepo master:frotz &&
 350        check_push_result testrepo $the_first_commit heads/frotz tags/frotz
 351
 352'
 353
 354test_expect_success 'push with colon-less refspec (1)' '
 355
 356        mk_test testrepo heads/frotz tags/frotz &&
 357        git branch -f frotz master &&
 358        git push testrepo frotz &&
 359        check_push_result testrepo $the_commit heads/frotz &&
 360        check_push_result testrepo $the_first_commit tags/frotz
 361
 362'
 363
 364test_expect_success 'push with colon-less refspec (2)' '
 365
 366        mk_test testrepo heads/frotz tags/frotz &&
 367        if git show-ref --verify -q refs/heads/frotz
 368        then
 369                git branch -D frotz
 370        fi &&
 371        git tag -f frotz &&
 372        git push -f testrepo frotz &&
 373        check_push_result testrepo $the_commit tags/frotz &&
 374        check_push_result testrepo $the_first_commit heads/frotz
 375
 376'
 377
 378test_expect_success 'push with colon-less refspec (3)' '
 379
 380        mk_test testrepo &&
 381        if git show-ref --verify -q refs/tags/frotz
 382        then
 383                git tag -d frotz
 384        fi &&
 385        git branch -f frotz master &&
 386        git push testrepo frotz &&
 387        check_push_result testrepo $the_commit heads/frotz &&
 388        test 1 = $( cd testrepo && git show-ref | wc -l )
 389'
 390
 391test_expect_success 'push with colon-less refspec (4)' '
 392
 393        mk_test testrepo &&
 394        if git show-ref --verify -q refs/heads/frotz
 395        then
 396                git branch -D frotz
 397        fi &&
 398        git tag -f frotz &&
 399        git push testrepo frotz &&
 400        check_push_result testrepo $the_commit tags/frotz &&
 401        test 1 = $( cd testrepo && git show-ref | wc -l )
 402
 403'
 404
 405test_expect_success 'push head with non-existent, incomplete dest' '
 406
 407        mk_test testrepo &&
 408        git push testrepo master:branch &&
 409        check_push_result testrepo $the_commit heads/branch
 410
 411'
 412
 413test_expect_success 'push tag with non-existent, incomplete dest' '
 414
 415        mk_test testrepo &&
 416        git tag -f v1.0 &&
 417        git push testrepo v1.0:tag &&
 418        check_push_result testrepo $the_commit tags/tag
 419
 420'
 421
 422test_expect_success 'push sha1 with non-existent, incomplete dest' '
 423
 424        mk_test testrepo &&
 425        test_must_fail git push testrepo `git rev-parse master`:foo
 426
 427'
 428
 429test_expect_success 'push ref expression with non-existent, incomplete dest' '
 430
 431        mk_test testrepo &&
 432        test_must_fail git push testrepo master^:branch
 433
 434'
 435
 436test_expect_success 'push with HEAD' '
 437
 438        mk_test testrepo heads/master &&
 439        git checkout master &&
 440        git push testrepo HEAD &&
 441        check_push_result testrepo $the_commit heads/master
 442
 443'
 444
 445test_expect_success 'push with HEAD nonexisting at remote' '
 446
 447        mk_test testrepo heads/master &&
 448        git checkout -b local master &&
 449        git push testrepo HEAD &&
 450        check_push_result testrepo $the_commit heads/local
 451'
 452
 453test_expect_success 'push with +HEAD' '
 454
 455        mk_test testrepo heads/master &&
 456        git checkout master &&
 457        git branch -D local &&
 458        git checkout -b local &&
 459        git push testrepo master local &&
 460        check_push_result testrepo $the_commit heads/master &&
 461        check_push_result testrepo $the_commit heads/local &&
 462
 463        # Without force rewinding should fail
 464        git reset --hard HEAD^ &&
 465        test_must_fail git push testrepo HEAD &&
 466        check_push_result testrepo $the_commit heads/local &&
 467
 468        # With force rewinding should succeed
 469        git push testrepo +HEAD &&
 470        check_push_result testrepo $the_first_commit heads/local
 471
 472'
 473
 474test_expect_success 'push HEAD with non-existent, incomplete dest' '
 475
 476        mk_test testrepo &&
 477        git checkout master &&
 478        git push testrepo HEAD:branch &&
 479        check_push_result testrepo $the_commit heads/branch
 480
 481'
 482
 483test_expect_success 'push with config remote.*.push = HEAD' '
 484
 485        mk_test testrepo heads/local &&
 486        git checkout master &&
 487        git branch -f local $the_commit &&
 488        (
 489                cd testrepo &&
 490                git checkout local &&
 491                git reset --hard $the_first_commit
 492        ) &&
 493        test_config remote.there.url testrepo &&
 494        test_config remote.there.push HEAD &&
 495        test_config branch.master.remote there &&
 496        git push &&
 497        check_push_result testrepo $the_commit heads/master &&
 498        check_push_result testrepo $the_first_commit heads/local
 499'
 500
 501test_expect_success 'push with remote.pushdefault' '
 502        mk_test up_repo heads/master &&
 503        mk_test down_repo heads/master &&
 504        test_config remote.up.url up_repo &&
 505        test_config remote.down.url down_repo &&
 506        test_config branch.master.remote up &&
 507        test_config remote.pushdefault down &&
 508        test_config push.default matching &&
 509        git push &&
 510        check_push_result up_repo $the_first_commit heads/master &&
 511        check_push_result down_repo $the_commit heads/master
 512'
 513
 514test_expect_success 'push with config remote.*.pushurl' '
 515
 516        mk_test testrepo heads/master &&
 517        git checkout master &&
 518        test_config remote.there.url test2repo &&
 519        test_config remote.there.pushurl testrepo &&
 520        git push there : &&
 521        check_push_result testrepo $the_commit heads/master
 522'
 523
 524test_expect_success 'push with config branch.*.pushremote' '
 525        mk_test up_repo heads/master &&
 526        mk_test side_repo heads/master &&
 527        mk_test down_repo heads/master &&
 528        test_config remote.up.url up_repo &&
 529        test_config remote.pushdefault side_repo &&
 530        test_config remote.down.url down_repo &&
 531        test_config branch.master.remote up &&
 532        test_config branch.master.pushremote down &&
 533        test_config push.default matching &&
 534        git push &&
 535        check_push_result up_repo $the_first_commit heads/master &&
 536        check_push_result side_repo $the_first_commit heads/master &&
 537        check_push_result down_repo $the_commit heads/master
 538'
 539
 540test_expect_success 'branch.*.pushremote config order is irrelevant' '
 541        mk_test one_repo heads/master &&
 542        mk_test two_repo heads/master &&
 543        test_config remote.one.url one_repo &&
 544        test_config remote.two.url two_repo &&
 545        test_config branch.master.pushremote two_repo &&
 546        test_config remote.pushdefault one_repo &&
 547        test_config push.default matching &&
 548        git push &&
 549        check_push_result one_repo $the_first_commit heads/master &&
 550        check_push_result two_repo $the_commit heads/master
 551'
 552
 553test_expect_success 'push with dry-run' '
 554
 555        mk_test testrepo heads/master &&
 556        (
 557                cd testrepo &&
 558                old_commit=$(git show-ref -s --verify refs/heads/master)
 559        ) &&
 560        git push --dry-run testrepo : &&
 561        check_push_result testrepo $old_commit heads/master
 562'
 563
 564test_expect_success 'push updates local refs' '
 565
 566        mk_test testrepo heads/master &&
 567        mk_child testrepo child &&
 568        (
 569                cd child &&
 570                git pull .. master &&
 571                git push &&
 572                test $(git rev-parse master) = \
 573                        $(git rev-parse remotes/origin/master)
 574        )
 575
 576'
 577
 578test_expect_success 'push updates up-to-date local refs' '
 579
 580        mk_test testrepo heads/master &&
 581        mk_child testrepo child1 &&
 582        mk_child testrepo child2 &&
 583        (cd child1 && git pull .. master && git push) &&
 584        (
 585                cd child2 &&
 586                git pull ../child1 master &&
 587                git push &&
 588                test $(git rev-parse master) = \
 589                        $(git rev-parse remotes/origin/master)
 590        )
 591
 592'
 593
 594test_expect_success 'push preserves up-to-date packed refs' '
 595
 596        mk_test testrepo heads/master &&
 597        mk_child testrepo child &&
 598        (
 599                cd child &&
 600                git push &&
 601                ! test -f .git/refs/remotes/origin/master
 602        )
 603
 604'
 605
 606test_expect_success 'push does not update local refs on failure' '
 607
 608        mk_test testrepo heads/master &&
 609        mk_child testrepo child &&
 610        mkdir testrepo/.git/hooks &&
 611        echo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive &&
 612        chmod +x testrepo/.git/hooks/pre-receive &&
 613        (
 614                cd child &&
 615                git pull .. master
 616                test_must_fail git push &&
 617                test $(git rev-parse master) != \
 618                        $(git rev-parse remotes/origin/master)
 619        )
 620
 621'
 622
 623test_expect_success 'allow deleting an invalid remote ref' '
 624
 625        mk_test testrepo heads/master &&
 626        rm -f testrepo/.git/objects/??/* &&
 627        git push testrepo :refs/heads/master &&
 628        (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
 629
 630'
 631
 632test_expect_success 'pushing valid refs triggers post-receive and post-update hooks' '
 633        mk_test_with_hooks testrepo heads/master heads/next &&
 634        orgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&
 635        newmaster=$(git show-ref -s --verify refs/heads/master) &&
 636        orgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&
 637        newnext=$_z40 &&
 638        git push testrepo refs/heads/master:refs/heads/master :refs/heads/next &&
 639        (
 640                cd testrepo/.git &&
 641                cat >pre-receive.expect <<-EOF &&
 642                $orgmaster $newmaster refs/heads/master
 643                $orgnext $newnext refs/heads/next
 644                EOF
 645
 646                cat >update.expect <<-EOF &&
 647                refs/heads/master $orgmaster $newmaster
 648                refs/heads/next $orgnext $newnext
 649                EOF
 650
 651                cat >post-receive.expect <<-EOF &&
 652                $orgmaster $newmaster refs/heads/master
 653                $orgnext $newnext refs/heads/next
 654                EOF
 655
 656                cat >post-update.expect <<-EOF &&
 657                refs/heads/master
 658                refs/heads/next
 659                EOF
 660
 661                test_cmp pre-receive.expect pre-receive.actual &&
 662                test_cmp update.expect update.actual &&
 663                test_cmp post-receive.expect post-receive.actual &&
 664                test_cmp post-update.expect post-update.actual
 665        )
 666'
 667
 668test_expect_success 'deleting dangling ref triggers hooks with correct args' '
 669        mk_test_with_hooks testrepo heads/master &&
 670        rm -f testrepo/.git/objects/??/* &&
 671        git push testrepo :refs/heads/master &&
 672        (
 673                cd testrepo/.git &&
 674                cat >pre-receive.expect <<-EOF &&
 675                $_z40 $_z40 refs/heads/master
 676                EOF
 677
 678                cat >update.expect <<-EOF &&
 679                refs/heads/master $_z40 $_z40
 680                EOF
 681
 682                cat >post-receive.expect <<-EOF &&
 683                $_z40 $_z40 refs/heads/master
 684                EOF
 685
 686                cat >post-update.expect <<-EOF &&
 687                refs/heads/master
 688                EOF
 689
 690                test_cmp pre-receive.expect pre-receive.actual &&
 691                test_cmp update.expect update.actual &&
 692                test_cmp post-receive.expect post-receive.actual &&
 693                test_cmp post-update.expect post-update.actual
 694        )
 695'
 696
 697test_expect_success 'deletion of a non-existent ref is not fed to post-receive and post-update hooks' '
 698        mk_test_with_hooks testrepo heads/master &&
 699        orgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&
 700        newmaster=$(git show-ref -s --verify refs/heads/master) &&
 701        git push testrepo master :refs/heads/nonexistent &&
 702        (
 703                cd testrepo/.git &&
 704                cat >pre-receive.expect <<-EOF &&
 705                $orgmaster $newmaster refs/heads/master
 706                $_z40 $_z40 refs/heads/nonexistent
 707                EOF
 708
 709                cat >update.expect <<-EOF &&
 710                refs/heads/master $orgmaster $newmaster
 711                refs/heads/nonexistent $_z40 $_z40
 712                EOF
 713
 714                cat >post-receive.expect <<-EOF &&
 715                $orgmaster $newmaster refs/heads/master
 716                EOF
 717
 718                cat >post-update.expect <<-EOF &&
 719                refs/heads/master
 720                EOF
 721
 722                test_cmp pre-receive.expect pre-receive.actual &&
 723                test_cmp update.expect update.actual &&
 724                test_cmp post-receive.expect post-receive.actual &&
 725                test_cmp post-update.expect post-update.actual
 726        )
 727'
 728
 729test_expect_success 'deletion of a non-existent ref alone does trigger post-receive and post-update hooks' '
 730        mk_test_with_hooks testrepo heads/master &&
 731        git push testrepo :refs/heads/nonexistent &&
 732        (
 733                cd testrepo/.git &&
 734                cat >pre-receive.expect <<-EOF &&
 735                $_z40 $_z40 refs/heads/nonexistent
 736                EOF
 737
 738                cat >update.expect <<-EOF &&
 739                refs/heads/nonexistent $_z40 $_z40
 740                EOF
 741
 742                test_cmp pre-receive.expect pre-receive.actual &&
 743                test_cmp update.expect update.actual &&
 744                test_path_is_missing post-receive.actual &&
 745                test_path_is_missing post-update.actual
 746        )
 747'
 748
 749test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks with correct input' '
 750        mk_test_with_hooks testrepo heads/master heads/next heads/pu &&
 751        orgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&
 752        newmaster=$(git show-ref -s --verify refs/heads/master) &&
 753        orgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&
 754        newnext=$_z40 &&
 755        orgpu=$(cd testrepo && git show-ref -s --verify refs/heads/pu) &&
 756        newpu=$(git show-ref -s --verify refs/heads/master) &&
 757        git push testrepo refs/heads/master:refs/heads/master \
 758            refs/heads/master:refs/heads/pu :refs/heads/next \
 759            :refs/heads/nonexistent &&
 760        (
 761                cd testrepo/.git &&
 762                cat >pre-receive.expect <<-EOF &&
 763                $orgmaster $newmaster refs/heads/master
 764                $orgnext $newnext refs/heads/next
 765                $orgpu $newpu refs/heads/pu
 766                $_z40 $_z40 refs/heads/nonexistent
 767                EOF
 768
 769                cat >update.expect <<-EOF &&
 770                refs/heads/master $orgmaster $newmaster
 771                refs/heads/next $orgnext $newnext
 772                refs/heads/pu $orgpu $newpu
 773                refs/heads/nonexistent $_z40 $_z40
 774                EOF
 775
 776                cat >post-receive.expect <<-EOF &&
 777                $orgmaster $newmaster refs/heads/master
 778                $orgnext $newnext refs/heads/next
 779                $orgpu $newpu refs/heads/pu
 780                EOF
 781
 782                cat >post-update.expect <<-EOF &&
 783                refs/heads/master
 784                refs/heads/next
 785                refs/heads/pu
 786                EOF
 787
 788                test_cmp pre-receive.expect pre-receive.actual &&
 789                test_cmp update.expect update.actual &&
 790                test_cmp post-receive.expect post-receive.actual &&
 791                test_cmp post-update.expect post-update.actual
 792        )
 793'
 794
 795test_expect_success 'allow deleting a ref using --delete' '
 796        mk_test testrepo heads/master &&
 797        (cd testrepo && git config receive.denyDeleteCurrent warn) &&
 798        git push testrepo --delete master &&
 799        (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
 800'
 801
 802test_expect_success 'allow deleting a tag using --delete' '
 803        mk_test testrepo heads/master &&
 804        git tag -a -m dummy_message deltag heads/master &&
 805        git push testrepo --tags &&
 806        (cd testrepo && git rev-parse --verify -q refs/tags/deltag) &&
 807        git push testrepo --delete tag deltag &&
 808        (cd testrepo && test_must_fail git rev-parse --verify refs/tags/deltag)
 809'
 810
 811test_expect_success 'push --delete without args aborts' '
 812        mk_test testrepo heads/master &&
 813        test_must_fail git push testrepo --delete
 814'
 815
 816test_expect_success 'push --delete refuses src:dest refspecs' '
 817        mk_test testrepo heads/master &&
 818        test_must_fail git push testrepo --delete master:foo
 819'
 820
 821test_expect_success 'warn on push to HEAD of non-bare repository' '
 822        mk_test testrepo heads/master &&
 823        (
 824                cd testrepo &&
 825                git checkout master &&
 826                git config receive.denyCurrentBranch warn
 827        ) &&
 828        git push testrepo master 2>stderr &&
 829        grep "warning: updating the current branch" stderr
 830'
 831
 832test_expect_success 'deny push to HEAD of non-bare repository' '
 833        mk_test testrepo heads/master &&
 834        (
 835                cd testrepo &&
 836                git checkout master &&
 837                git config receive.denyCurrentBranch true
 838        ) &&
 839        test_must_fail git push testrepo master
 840'
 841
 842test_expect_success 'allow push to HEAD of bare repository (bare)' '
 843        mk_test testrepo heads/master &&
 844        (
 845                cd testrepo &&
 846                git checkout master &&
 847                git config receive.denyCurrentBranch true &&
 848                git config core.bare true
 849        ) &&
 850        git push testrepo master 2>stderr &&
 851        ! grep "warning: updating the current branch" stderr
 852'
 853
 854test_expect_success 'allow push to HEAD of non-bare repository (config)' '
 855        mk_test testrepo heads/master &&
 856        (
 857                cd testrepo &&
 858                git checkout master &&
 859                git config receive.denyCurrentBranch false
 860        ) &&
 861        git push testrepo master 2>stderr &&
 862        ! grep "warning: updating the current branch" stderr
 863'
 864
 865test_expect_success 'fetch with branches' '
 866        mk_empty testrepo &&
 867        git branch second $the_first_commit &&
 868        git checkout second &&
 869        echo ".." > testrepo/.git/branches/branch1 &&
 870        (
 871                cd testrepo &&
 872                git fetch branch1 &&
 873                echo "$the_commit commit        refs/heads/branch1" >expect &&
 874                git for-each-ref refs/heads >actual &&
 875                test_cmp expect actual
 876        ) &&
 877        git checkout master
 878'
 879
 880test_expect_success 'fetch with branches containing #' '
 881        mk_empty testrepo &&
 882        echo "..#second" > testrepo/.git/branches/branch2 &&
 883        (
 884                cd testrepo &&
 885                git fetch branch2 &&
 886                echo "$the_first_commit commit  refs/heads/branch2" >expect &&
 887                git for-each-ref refs/heads >actual &&
 888                test_cmp expect actual
 889        ) &&
 890        git checkout master
 891'
 892
 893test_expect_success 'push with branches' '
 894        mk_empty testrepo &&
 895        git checkout second &&
 896        echo "testrepo" > .git/branches/branch1 &&
 897        git push branch1 &&
 898        (
 899                cd testrepo &&
 900                echo "$the_first_commit commit  refs/heads/master" >expect &&
 901                git for-each-ref refs/heads >actual &&
 902                test_cmp expect actual
 903        )
 904'
 905
 906test_expect_success 'push with branches containing #' '
 907        mk_empty testrepo &&
 908        echo "testrepo#branch3" > .git/branches/branch2 &&
 909        git push branch2 &&
 910        (
 911                cd testrepo &&
 912                echo "$the_first_commit commit  refs/heads/branch3" >expect &&
 913                git for-each-ref refs/heads >actual &&
 914                test_cmp expect actual
 915        ) &&
 916        git checkout master
 917'
 918
 919test_expect_success 'push into aliased refs (consistent)' '
 920        mk_test testrepo heads/master &&
 921        mk_child testrepo child1 &&
 922        mk_child testrepo child2 &&
 923        (
 924                cd child1 &&
 925                git branch foo &&
 926                git symbolic-ref refs/heads/bar refs/heads/foo
 927                git config receive.denyCurrentBranch false
 928        ) &&
 929        (
 930                cd child2 &&
 931                >path2 &&
 932                git add path2 &&
 933                test_tick &&
 934                git commit -a -m child2 &&
 935                git branch foo &&
 936                git branch bar &&
 937                git push ../child1 foo bar
 938        )
 939'
 940
 941test_expect_success 'push into aliased refs (inconsistent)' '
 942        mk_test testrepo heads/master &&
 943        mk_child testrepo child1 &&
 944        mk_child testrepo child2 &&
 945        (
 946                cd child1 &&
 947                git branch foo &&
 948                git symbolic-ref refs/heads/bar refs/heads/foo
 949                git config receive.denyCurrentBranch false
 950        ) &&
 951        (
 952                cd child2 &&
 953                >path2 &&
 954                git add path2 &&
 955                test_tick &&
 956                git commit -a -m child2 &&
 957                git branch foo &&
 958                >path3 &&
 959                git add path3 &&
 960                test_tick &&
 961                git commit -a -m child2 &&
 962                git branch bar &&
 963                test_must_fail git push ../child1 foo bar 2>stderr &&
 964                grep "refusing inconsistent update" stderr
 965        )
 966'
 967
 968test_expect_success 'push requires --force to update lightweight tag' '
 969        mk_test testrepo heads/master &&
 970        mk_child testrepo child1 &&
 971        mk_child testrepo child2 &&
 972        (
 973                cd child1 &&
 974                git tag Tag &&
 975                git push ../child2 Tag &&
 976                git push ../child2 Tag &&
 977                >file1 &&
 978                git add file1 &&
 979                git commit -m "file1" &&
 980                git tag -f Tag &&
 981                test_must_fail git push ../child2 Tag &&
 982                git push --force ../child2 Tag &&
 983                git tag -f Tag &&
 984                test_must_fail git push ../child2 Tag HEAD~ &&
 985                git push --force ../child2 Tag
 986        )
 987'
 988
 989test_expect_success 'push --porcelain' '
 990        mk_empty testrepo &&
 991        echo >.git/foo  "To testrepo" &&
 992        echo >>.git/foo "*      refs/heads/master:refs/remotes/origin/master    [new branch]"  &&
 993        echo >>.git/foo "Done" &&
 994        git push >.git/bar --porcelain  testrepo refs/heads/master:refs/remotes/origin/master &&
 995        (
 996                cd testrepo &&
 997                echo "$the_commit commit        refs/remotes/origin/master" >expect &&
 998                git for-each-ref refs/remotes/origin >actual &&
 999                test_cmp expect actual
1000        ) &&
1001        test_cmp .git/foo .git/bar
1002'
1003
1004test_expect_success 'push --porcelain bad url' '
1005        mk_empty testrepo &&
1006        test_must_fail git push >.git/bar --porcelain asdfasdfasd refs/heads/master:refs/remotes/origin/master &&
1007        test_must_fail grep -q Done .git/bar
1008'
1009
1010test_expect_success 'push --porcelain rejected' '
1011        mk_empty testrepo &&
1012        git push testrepo refs/heads/master:refs/remotes/origin/master &&
1013        (cd testrepo &&
1014                git reset --hard origin/master^
1015                git config receive.denyCurrentBranch true) &&
1016
1017        echo >.git/foo  "To testrepo"  &&
1018        echo >>.git/foo "!      refs/heads/master:refs/heads/master     [remote rejected] (branch is currently checked out)" &&
1019
1020        test_must_fail git push >.git/bar --porcelain  testrepo refs/heads/master:refs/heads/master &&
1021        test_cmp .git/foo .git/bar
1022'
1023
1024test_expect_success 'push --porcelain --dry-run rejected' '
1025        mk_empty testrepo &&
1026        git push testrepo refs/heads/master:refs/remotes/origin/master &&
1027        (cd testrepo &&
1028                git reset --hard origin/master
1029                git config receive.denyCurrentBranch true) &&
1030
1031        echo >.git/foo  "To testrepo"  &&
1032        echo >>.git/foo "!      refs/heads/master^:refs/heads/master    [rejected] (non-fast-forward)" &&
1033        echo >>.git/foo "Done" &&
1034
1035        test_must_fail git push >.git/bar --porcelain  --dry-run testrepo refs/heads/master^:refs/heads/master &&
1036        test_cmp .git/foo .git/bar
1037'
1038
1039test_expect_success 'push --prune' '
1040        mk_test testrepo heads/master heads/second heads/foo heads/bar &&
1041        git push --prune testrepo : &&
1042        check_push_result testrepo $the_commit heads/master &&
1043        check_push_result testrepo $the_first_commit heads/second &&
1044        ! check_push_result testrepo $the_first_commit heads/foo heads/bar
1045'
1046
1047test_expect_success 'push --prune refspec' '
1048        mk_test testrepo tmp/master tmp/second tmp/foo tmp/bar &&
1049        git push --prune testrepo "refs/heads/*:refs/tmp/*" &&
1050        check_push_result testrepo $the_commit tmp/master &&
1051        check_push_result testrepo $the_first_commit tmp/second &&
1052        ! check_push_result testrepo $the_first_commit tmp/foo tmp/bar
1053'
1054
1055for configsection in transfer receive
1056do
1057        test_expect_success "push to update a ref hidden by $configsection.hiderefs" '
1058                mk_test testrepo heads/master hidden/one hidden/two hidden/three &&
1059                (
1060                        cd testrepo &&
1061                        git config $configsection.hiderefs refs/hidden
1062                ) &&
1063
1064                # push to unhidden ref succeeds normally
1065                git push testrepo master:refs/heads/master &&
1066                check_push_result testrepo $the_commit heads/master &&
1067
1068                # push to update a hidden ref should fail
1069                test_must_fail git push testrepo master:refs/hidden/one &&
1070                check_push_result testrepo $the_first_commit hidden/one &&
1071
1072                # push to delete a hidden ref should fail
1073                test_must_fail git push testrepo :refs/hidden/two &&
1074                check_push_result testrepo $the_first_commit hidden/two &&
1075
1076                # idempotent push to update a hidden ref should fail
1077                test_must_fail git push testrepo $the_first_commit:refs/hidden/three &&
1078                check_push_result testrepo $the_first_commit hidden/three
1079        '
1080done
1081
1082test_expect_success 'fetch exact SHA1' '
1083        mk_test testrepo heads/master hidden/one &&
1084        git push testrepo master:refs/hidden/one &&
1085        (
1086                cd testrepo &&
1087                git config transfer.hiderefs refs/hidden
1088        ) &&
1089        check_push_result testrepo $the_commit hidden/one &&
1090
1091        mk_child testrepo child &&
1092        (
1093                cd child &&
1094
1095                # make sure $the_commit does not exist here
1096                git repack -a -d &&
1097                git prune &&
1098                test_must_fail git cat-file -t $the_commit &&
1099
1100                # fetching the hidden object should fail by default
1101                test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
1102                test_must_fail git rev-parse --verify refs/heads/copy &&
1103
1104                # the server side can allow it to succeed
1105                (
1106                        cd ../testrepo &&
1107                        git config uploadpack.allowtipsha1inwant true
1108                ) &&
1109
1110                git fetch -v ../testrepo $the_commit:refs/heads/copy master:refs/heads/extra &&
1111                cat >expect <<-EOF &&
1112                $the_commit
1113                $the_first_commit
1114                EOF
1115                {
1116                        git rev-parse --verify refs/heads/copy &&
1117                        git rev-parse --verify refs/heads/extra
1118                } >actual &&
1119                test_cmp expect actual
1120        )
1121'
1122
1123test_expect_success 'fetch follows tags by default' '
1124        mk_test testrepo heads/master &&
1125        rm -fr src dst &&
1126        git init src &&
1127        (
1128                cd src &&
1129                git pull ../testrepo master &&
1130                git tag -m "annotated" tag &&
1131                git for-each-ref >tmp1 &&
1132                (
1133                        cat tmp1
1134                        sed -n "s|refs/heads/master$|refs/remotes/origin/master|p" tmp1
1135                ) |
1136                sort -k 3 >../expect
1137        ) &&
1138        git init dst &&
1139        (
1140                cd dst &&
1141                git remote add origin ../src &&
1142                git config branch.master.remote origin &&
1143                git config branch.master.merge refs/heads/master &&
1144                git pull &&
1145                git for-each-ref >../actual
1146        ) &&
1147        test_cmp expect actual
1148'
1149
1150test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' '
1151        mk_test testrepo heads/master &&
1152        rm -fr src dst &&
1153        git init src &&
1154        git init --bare dst &&
1155        (
1156                cd src &&
1157                git pull ../testrepo master &&
1158                git branch next &&
1159                git config remote.dst.url ../dst &&
1160                git config remote.dst.push "+refs/heads/*:refs/remotes/src/*" &&
1161                git push dst master &&
1162                git show-ref refs/heads/master |
1163                sed -e "s|refs/heads/|refs/remotes/src/|" >../dst/expect
1164        ) &&
1165        (
1166                cd dst &&
1167                test_must_fail git show-ref refs/heads/next &&
1168                test_must_fail git show-ref refs/heads/master &&
1169                git show-ref refs/remotes/src/master >actual
1170        ) &&
1171        test_cmp dst/expect dst/actual
1172'
1173
1174test_expect_success 'with no remote.$name.push, it is not used as refmap' '
1175        mk_test testrepo heads/master &&
1176        rm -fr src dst &&
1177        git init src &&
1178        git init --bare dst &&
1179        (
1180                cd src &&
1181                git pull ../testrepo master &&
1182                git branch next &&
1183                git config remote.dst.url ../dst &&
1184                git config push.default matching &&
1185                git push dst master &&
1186                git show-ref refs/heads/master >../dst/expect
1187        ) &&
1188        (
1189                cd dst &&
1190                test_must_fail git show-ref refs/heads/next &&
1191                git show-ref refs/heads/master >actual
1192        ) &&
1193        test_cmp dst/expect dst/actual
1194'
1195
1196test_expect_success 'with no remote.$name.push, upstream mapping is used' '
1197        mk_test testrepo heads/master &&
1198        rm -fr src dst &&
1199        git init src &&
1200        git init --bare dst &&
1201        (
1202                cd src &&
1203                git pull ../testrepo master &&
1204                git branch next &&
1205                git config remote.dst.url ../dst &&
1206                git config remote.dst.fetch "+refs/heads/*:refs/remotes/dst/*" &&
1207                git config push.default upstream &&
1208
1209                git config branch.master.merge refs/heads/trunk &&
1210                git config branch.master.remote dst &&
1211
1212                git push dst master &&
1213                git show-ref refs/heads/master |
1214                sed -e "s|refs/heads/master|refs/heads/trunk|" >../dst/expect
1215        ) &&
1216        (
1217                cd dst &&
1218                test_must_fail git show-ref refs/heads/master &&
1219                test_must_fail git show-ref refs/heads/next &&
1220                git show-ref refs/heads/trunk >actual
1221        ) &&
1222        test_cmp dst/expect dst/actual
1223'
1224
1225test_expect_success 'push does not follow tags by default' '
1226        mk_test testrepo heads/master &&
1227        rm -fr src dst &&
1228        git init src &&
1229        git init --bare dst &&
1230        (
1231                cd src &&
1232                git pull ../testrepo master &&
1233                git tag -m "annotated" tag &&
1234                git checkout -b another &&
1235                git commit --allow-empty -m "future commit" &&
1236                git tag -m "future" future &&
1237                git checkout master &&
1238                git for-each-ref refs/heads/master >../expect &&
1239                git push ../dst master
1240        ) &&
1241        (
1242                cd dst &&
1243                git for-each-ref >../actual
1244        ) &&
1245        test_cmp expect actual
1246'
1247
1248test_expect_success 'push --follow-tag only pushes relevant tags' '
1249        mk_test testrepo heads/master &&
1250        rm -fr src dst &&
1251        git init src &&
1252        git init --bare dst &&
1253        (
1254                cd src &&
1255                git pull ../testrepo master &&
1256                git tag -m "annotated" tag &&
1257                git checkout -b another &&
1258                git commit --allow-empty -m "future commit" &&
1259                git tag -m "future" future &&
1260                git checkout master &&
1261                git for-each-ref refs/heads/master refs/tags/tag >../expect
1262                git push --follow-tag ../dst master
1263        ) &&
1264        (
1265                cd dst &&
1266                git for-each-ref >../actual
1267        ) &&
1268        test_cmp expect actual
1269'
1270
1271test_expect_success 'push --no-thin must produce non-thin pack' '
1272        cat >>path1 <<\EOF &&
1273keep base version of path1 big enough, compared to the new changes
1274later, in order to pass size heuristics in
1275builtin/pack-objects.c:try_delta()
1276EOF
1277        git commit -am initial &&
1278        git init no-thin &&
1279        git --git-dir=no-thin/.git config receive.unpacklimit 0 &&
1280        git push no-thin/.git refs/heads/master:refs/heads/foo &&
1281        echo modified >> path1 &&
1282        git commit -am modified &&
1283        git repack -adf &&
1284        rcvpck="git receive-pack --reject-thin-pack-for-testing" &&
1285        git push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/master:refs/heads/foo
1286'
1287
1288test_expect_success 'pushing a tag pushes the tagged object' '
1289        rm -rf dst.git &&
1290        blob=$(echo unreferenced | git hash-object -w --stdin) &&
1291        git tag -m foo tag-of-blob $blob &&
1292        git init --bare dst.git &&
1293        git push dst.git tag-of-blob &&
1294        # the receiving index-pack should have noticed
1295        # any problems, but we double check
1296        echo unreferenced >expect &&
1297        git --git-dir=dst.git cat-file blob tag-of-blob >actual &&
1298        test_cmp expect actual
1299'
1300
1301test_expect_success 'push into bare respects core.logallrefupdates' '
1302        rm -rf dst.git &&
1303        git init --bare dst.git &&
1304        git -C dst.git config core.logallrefupdates true &&
1305
1306        # double push to test both with and without
1307        # the actual pack transfer
1308        git push dst.git master:one &&
1309        echo "one@{0} push" >expect &&
1310        git -C dst.git log -g --format="%gd %gs" one >actual &&
1311        test_cmp expect actual &&
1312
1313        git push dst.git master:two &&
1314        echo "two@{0} push" >expect &&
1315        git -C dst.git log -g --format="%gd %gs" two >actual &&
1316        test_cmp expect actual
1317'
1318
1319test_expect_success 'fetch into bare respects core.logallrefupdates' '
1320        rm -rf dst.git &&
1321        git init --bare dst.git &&
1322        (
1323                cd dst.git &&
1324                git config core.logallrefupdates true &&
1325
1326                # as above, we double-fetch to test both
1327                # with and without pack transfer
1328                git fetch .. master:one &&
1329                echo "one@{0} fetch .. master:one: storing head" >expect &&
1330                git log -g --format="%gd %gs" one >actual &&
1331                test_cmp expect actual &&
1332
1333                git fetch .. master:two &&
1334                echo "two@{0} fetch .. master:two: storing head" >expect &&
1335                git log -g --format="%gd %gs" two >actual &&
1336                test_cmp expect actual
1337        )
1338'
1339
1340test_expect_success 'receive.denyCurrentBranch = updateInstead' '
1341        git push testrepo master &&
1342        (
1343                cd testrepo &&
1344                git reset --hard &&
1345                git config receive.denyCurrentBranch updateInstead
1346        ) &&
1347        test_commit third path2 &&
1348
1349        # Try pushing into a repository with pristine working tree
1350        git push testrepo master &&
1351        (
1352                cd testrepo &&
1353                git update-index -q --refresh &&
1354                git diff-files --quiet -- &&
1355                git diff-index --quiet --cached HEAD -- &&
1356                test third = "$(cat path2)" &&
1357                test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1358        ) &&
1359
1360        # Try pushing into a repository with working tree needing a refresh
1361        (
1362                cd testrepo &&
1363                git reset --hard HEAD^ &&
1364                test $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&
1365                test-chmtime +100 path1
1366        ) &&
1367        git push testrepo master &&
1368        (
1369                cd testrepo &&
1370                git update-index -q --refresh &&
1371                git diff-files --quiet -- &&
1372                git diff-index --quiet --cached HEAD -- &&
1373                test_cmp ../path1 path1 &&
1374                test third = "$(cat path2)" &&
1375                test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1376        ) &&
1377
1378        # Update what is to be pushed
1379        test_commit fourth path2 &&
1380
1381        # Try pushing into a repository with a dirty working tree
1382        # (1) the working tree updated
1383        (
1384                cd testrepo &&
1385                echo changed >path1
1386        ) &&
1387        test_must_fail git push testrepo master &&
1388        (
1389                cd testrepo &&
1390                test $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&
1391                git diff --quiet --cached &&
1392                test changed = "$(cat path1)"
1393        ) &&
1394
1395        # (2) the index updated
1396        (
1397                cd testrepo &&
1398                echo changed >path1 &&
1399                git add path1
1400        ) &&
1401        test_must_fail git push testrepo master &&
1402        (
1403                cd testrepo &&
1404                test $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&
1405                git diff --quiet &&
1406                test changed = "$(cat path1)"
1407        ) &&
1408
1409        # Introduce a new file in the update
1410        test_commit fifth path3 &&
1411
1412        # (3) the working tree has an untracked file that would interfere
1413        (
1414                cd testrepo &&
1415                git reset --hard &&
1416                echo changed >path3
1417        ) &&
1418        test_must_fail git push testrepo master &&
1419        (
1420                cd testrepo &&
1421                test $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&
1422                git diff --quiet &&
1423                git diff --quiet --cached &&
1424                test changed = "$(cat path3)"
1425        ) &&
1426
1427        # (4) the target changes to what gets pushed but it still is a change
1428        (
1429                cd testrepo &&
1430                git reset --hard &&
1431                echo fifth >path3 &&
1432                git add path3
1433        ) &&
1434        test_must_fail git push testrepo master &&
1435        (
1436                cd testrepo &&
1437                test $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&
1438                git diff --quiet &&
1439                test fifth = "$(cat path3)"
1440        ) &&
1441
1442        # (5) push into void
1443        rm -fr void &&
1444        git init void &&
1445        (
1446                cd void &&
1447                git config receive.denyCurrentBranch updateInstead
1448        ) &&
1449        git push void master &&
1450        (
1451                cd void &&
1452                test $(git -C .. rev-parse master) = $(git rev-parse HEAD) &&
1453                git diff --quiet &&
1454                git diff --cached --quiet
1455        )
1456'
1457
1458test_expect_success 'updateInstead with push-to-checkout hook' '
1459        rm -fr testrepo &&
1460        git init testrepo &&
1461        (
1462                cd testrepo &&
1463                git pull .. master &&
1464                git reset --hard HEAD^^ &&
1465                git tag initial &&
1466                git config receive.denyCurrentBranch updateInstead &&
1467                write_script .git/hooks/push-to-checkout <<-\EOF
1468                echo >&2 updating from $(git rev-parse HEAD)
1469                echo >&2 updating to "$1"
1470
1471                git update-index -q --refresh &&
1472                git read-tree -u -m HEAD "$1" || {
1473                        status=$?
1474                        echo >&2 read-tree failed
1475                        exit $status
1476                }
1477                EOF
1478        ) &&
1479
1480        # Try pushing into a pristine
1481        git push testrepo master &&
1482        (
1483                cd testrepo &&
1484                git diff --quiet &&
1485                git diff HEAD --quiet &&
1486                test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1487        ) &&
1488
1489        # Try pushing into a repository with conflicting change
1490        (
1491                cd testrepo &&
1492                git reset --hard initial &&
1493                echo conflicting >path2
1494        ) &&
1495        test_must_fail git push testrepo master &&
1496        (
1497                cd testrepo &&
1498                test $(git rev-parse initial) = $(git rev-parse HEAD) &&
1499                test conflicting = "$(cat path2)" &&
1500                git diff-index --quiet --cached HEAD
1501        ) &&
1502
1503        # Try pushing into a repository with unrelated change
1504        (
1505                cd testrepo &&
1506                git reset --hard initial &&
1507                echo unrelated >path1 &&
1508                echo irrelevant >path5 &&
1509                git add path5
1510        ) &&
1511        git push testrepo master &&
1512        (
1513                cd testrepo &&
1514                test "$(cat path1)" = unrelated &&
1515                test "$(cat path5)" = irrelevant &&
1516                test "$(git diff --name-only --cached HEAD)" = path5 &&
1517                test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1518        ) &&
1519
1520        # push into void
1521        rm -fr void &&
1522        git init void &&
1523        (
1524                cd void &&
1525                git config receive.denyCurrentBranch updateInstead &&
1526                write_script .git/hooks/push-to-checkout <<-\EOF
1527                if git rev-parse --quiet --verify HEAD
1528                then
1529                        has_head=yes
1530                        echo >&2 updating from $(git rev-parse HEAD)
1531                else
1532                        has_head=no
1533                        echo >&2 pushing into void
1534                fi
1535                echo >&2 updating to "$1"
1536
1537                git update-index -q --refresh &&
1538                case "$has_head" in
1539                yes)
1540                        git read-tree -u -m HEAD "$1" ;;
1541                no)
1542                        git read-tree -u -m "$1" ;;
1543                esac || {
1544                        status=$?
1545                        echo >&2 read-tree failed
1546                        exit $status
1547                }
1548                EOF
1549        ) &&
1550
1551        git push void master &&
1552        (
1553                cd void &&
1554                git diff --quiet &&
1555                git diff --cached --quiet &&
1556                test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1557        )
1558'
1559
1560test_done