t / t5510-fetch.shon commit reset: optionally setup worktree and refresh index on --mixed (b7756d4)
   1#!/bin/sh
   2# Copyright (c) 2006, Junio C Hamano.
   3
   4test_description='Per branch config variables affects "git fetch".
   5
   6'
   7
   8. ./test-lib.sh
   9
  10D=`pwd`
  11
  12test_bundle_object_count () {
  13        git verify-pack -v "$1" >verify.out &&
  14        test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l)
  15}
  16
  17convert_bundle_to_pack () {
  18        while read x && test -n "$x"
  19        do
  20                :;
  21        done
  22        cat
  23}
  24
  25test_expect_success setup '
  26        echo >file original &&
  27        git add file &&
  28        git commit -a -m original'
  29
  30test_expect_success "clone and setup child repos" '
  31        git clone . one &&
  32        (
  33                cd one &&
  34                echo >file updated by one &&
  35                git commit -a -m "updated by one"
  36        ) &&
  37        git clone . two &&
  38        (
  39                cd two &&
  40                git config branch.master.remote one &&
  41                git config remote.one.url ../one/.git/ &&
  42                git config remote.one.fetch refs/heads/master:refs/heads/one
  43        ) &&
  44        git clone . three &&
  45        (
  46                cd three &&
  47                git config branch.master.remote two &&
  48                git config branch.master.merge refs/heads/one &&
  49                mkdir -p .git/remotes &&
  50                {
  51                        echo "URL: ../two/.git/"
  52                        echo "Pull: refs/heads/master:refs/heads/two"
  53                        echo "Pull: refs/heads/one:refs/heads/one"
  54                } >.git/remotes/two
  55        ) &&
  56        git clone . bundle &&
  57        git clone . seven
  58'
  59
  60test_expect_success "fetch test" '
  61        cd "$D" &&
  62        echo >file updated by origin &&
  63        git commit -a -m "updated by origin" &&
  64        cd two &&
  65        git fetch &&
  66        test -f .git/refs/heads/one &&
  67        mine=`git rev-parse refs/heads/one` &&
  68        his=`cd ../one && git rev-parse refs/heads/master` &&
  69        test "z$mine" = "z$his"
  70'
  71
  72test_expect_success "fetch test for-merge" '
  73        cd "$D" &&
  74        cd three &&
  75        git fetch &&
  76        test -f .git/refs/heads/two &&
  77        test -f .git/refs/heads/one &&
  78        master_in_two=`cd ../two && git rev-parse master` &&
  79        one_in_two=`cd ../two && git rev-parse one` &&
  80        {
  81                echo "$one_in_two       "
  82                echo "$master_in_two    not-for-merge"
  83        } >expected &&
  84        cut -f -2 .git/FETCH_HEAD >actual &&
  85        test_cmp expected actual'
  86
  87test_expect_success 'fetch --prune on its own works as expected' '
  88        cd "$D" &&
  89        git clone . prune &&
  90        cd prune &&
  91        git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
  92
  93        git fetch --prune origin &&
  94        test_must_fail git rev-parse origin/extrabranch
  95'
  96
  97test_expect_success 'fetch --prune with a branch name keeps branches' '
  98        cd "$D" &&
  99        git clone . prune-branch &&
 100        cd prune-branch &&
 101        git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
 102
 103        git fetch --prune origin master &&
 104        git rev-parse origin/extrabranch
 105'
 106
 107test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
 108        cd "$D" &&
 109        git clone . prune-namespace &&
 110        cd prune-namespace &&
 111
 112        git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
 113        git rev-parse origin/master
 114'
 115
 116test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
 117        cd "$D" &&
 118        git clone . prune-tags &&
 119        cd prune-tags &&
 120        git fetch origin refs/heads/master:refs/tags/sometag &&
 121
 122        git fetch --prune --tags origin &&
 123        git rev-parse origin/master &&
 124        test_must_fail git rev-parse somebranch
 125'
 126
 127test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' '
 128        cd "$D" &&
 129        git clone . prune-tags-branch &&
 130        cd prune-tags-branch &&
 131        git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
 132
 133        git fetch --prune --tags origin master &&
 134        git rev-parse origin/extrabranch
 135'
 136
 137test_expect_success 'fetch tags when there is no tags' '
 138
 139    cd "$D" &&
 140
 141    mkdir notags &&
 142    cd notags &&
 143    git init &&
 144
 145    git fetch -t ..
 146
 147'
 148
 149test_expect_success 'fetch following tags' '
 150
 151        cd "$D" &&
 152        git tag -a -m 'annotated' anno HEAD &&
 153        git tag light HEAD &&
 154
 155        mkdir four &&
 156        cd four &&
 157        git init &&
 158
 159        git fetch .. :track &&
 160        git show-ref --verify refs/tags/anno &&
 161        git show-ref --verify refs/tags/light
 162
 163'
 164
 165test_expect_success 'fetch uses remote ref names to describe new refs' '
 166        cd "$D" &&
 167        git init descriptive &&
 168        (
 169                cd descriptive &&
 170                git config remote.o.url .. &&
 171                git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" &&
 172                git config --add remote.o.fetch "refs/others/*:refs/heads/*" &&
 173                git fetch o
 174        ) &&
 175        git tag -a -m "Descriptive tag" descriptive-tag &&
 176        git branch descriptive-branch &&
 177        git checkout descriptive-branch &&
 178        echo "Nuts" >crazy &&
 179        git add crazy &&
 180        git commit -a -m "descriptive commit" &&
 181        git update-ref refs/others/crazy HEAD &&
 182        (
 183                cd descriptive &&
 184                git fetch o 2>actual &&
 185                grep " -> refs/crazyheads/descriptive-branch$" actual |
 186                test_i18ngrep "new branch" &&
 187                grep " -> descriptive-tag$" actual |
 188                test_i18ngrep "new tag" &&
 189                grep " -> crazy$" actual |
 190                test_i18ngrep "new ref"
 191        ) &&
 192        git checkout master
 193'
 194
 195test_expect_success 'fetch must not resolve short tag name' '
 196
 197        cd "$D" &&
 198
 199        mkdir five &&
 200        cd five &&
 201        git init &&
 202
 203        test_must_fail git fetch .. anno:five
 204
 205'
 206
 207test_expect_success 'fetch can now resolve short remote name' '
 208
 209        cd "$D" &&
 210        git update-ref refs/remotes/six/HEAD HEAD &&
 211
 212        mkdir six &&
 213        cd six &&
 214        git init &&
 215
 216        git fetch .. six:six
 217'
 218
 219test_expect_success 'create bundle 1' '
 220        cd "$D" &&
 221        echo >file updated again by origin &&
 222        git commit -a -m "tip" &&
 223        git bundle create bundle1 master^..master
 224'
 225
 226test_expect_success 'header of bundle looks right' '
 227        head -n 1 "$D"/bundle1 | grep "^#" &&
 228        head -n 2 "$D"/bundle1 | grep "^-[0-9a-f]\{40\} " &&
 229        head -n 3 "$D"/bundle1 | grep "^[0-9a-f]\{40\} " &&
 230        head -n 4 "$D"/bundle1 | grep "^$"
 231'
 232
 233test_expect_success 'create bundle 2' '
 234        cd "$D" &&
 235        git bundle create bundle2 master~2..master
 236'
 237
 238test_expect_success 'unbundle 1' '
 239        cd "$D/bundle" &&
 240        git checkout -b some-branch &&
 241        test_must_fail git fetch "$D/bundle1" master:master
 242'
 243
 244
 245test_expect_success 'bundle 1 has only 3 files ' '
 246        cd "$D" &&
 247        convert_bundle_to_pack <bundle1 >bundle.pack &&
 248        git index-pack bundle.pack &&
 249        test_bundle_object_count bundle.pack 3
 250'
 251
 252test_expect_success 'unbundle 2' '
 253        cd "$D/bundle" &&
 254        git fetch ../bundle2 master:master &&
 255        test "tip" = "$(git log -1 --pretty=oneline master | cut -b42-)"
 256'
 257
 258test_expect_success 'bundle does not prerequisite objects' '
 259        cd "$D" &&
 260        touch file2 &&
 261        git add file2 &&
 262        git commit -m add.file2 file2 &&
 263        git bundle create bundle3 -1 HEAD &&
 264        convert_bundle_to_pack <bundle3 >bundle.pack &&
 265        git index-pack bundle.pack &&
 266        test_bundle_object_count bundle.pack 3
 267'
 268
 269test_expect_success 'bundle should be able to create a full history' '
 270
 271        cd "$D" &&
 272        git tag -a -m '1.0' v1.0 master &&
 273        git bundle create bundle4 v1.0
 274
 275'
 276
 277! rsync --help > /dev/null 2> /dev/null &&
 278say 'Skipping rsync tests because rsync was not found' || {
 279test_expect_success 'fetch via rsync' '
 280        git pack-refs &&
 281        mkdir rsynced &&
 282        (cd rsynced &&
 283         git init --bare &&
 284         git fetch "rsync:$(pwd)/../.git" master:refs/heads/master &&
 285         git gc --prune &&
 286         test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
 287         git fsck --full)
 288'
 289
 290test_expect_success 'push via rsync' '
 291        mkdir rsynced2 &&
 292        (cd rsynced2 &&
 293         git init) &&
 294        (cd rsynced &&
 295         git push "rsync:$(pwd)/../rsynced2/.git" master) &&
 296        (cd rsynced2 &&
 297         git gc --prune &&
 298         test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
 299         git fsck --full)
 300'
 301
 302test_expect_success 'push via rsync' '
 303        mkdir rsynced3 &&
 304        (cd rsynced3 &&
 305         git init) &&
 306        git push --all "rsync:$(pwd)/rsynced3/.git" &&
 307        (cd rsynced3 &&
 308         test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
 309         git fsck --full)
 310'
 311}
 312
 313test_expect_success 'fetch with a non-applying branch.<name>.merge' '
 314        git config branch.master.remote yeti &&
 315        git config branch.master.merge refs/heads/bigfoot &&
 316        git config remote.blub.url one &&
 317        git config remote.blub.fetch "refs/heads/*:refs/remotes/one/*" &&
 318        git fetch blub
 319'
 320
 321# URL supplied to fetch does not match the url of the configured branch's remote
 322test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' '
 323        one_head=$(cd one && git rev-parse HEAD) &&
 324        this_head=$(git rev-parse HEAD) &&
 325        git update-ref -d FETCH_HEAD &&
 326        git fetch one &&
 327        test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
 328        test $this_head = "$(git rev-parse --verify HEAD)"
 329'
 330
 331# URL supplied to fetch matches the url of the configured branch's remote and
 332# the merge spec matches the branch the remote HEAD points to
 333test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [2]' '
 334        one_ref=$(cd one && git symbolic-ref HEAD) &&
 335        git config branch.master.remote blub &&
 336        git config branch.master.merge "$one_ref" &&
 337        git update-ref -d FETCH_HEAD &&
 338        git fetch one &&
 339        test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
 340        test $this_head = "$(git rev-parse --verify HEAD)"
 341'
 342
 343# URL supplied to fetch matches the url of the configured branch's remote, but
 344# the merge spec does not match the branch the remote HEAD points to
 345test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' '
 346        git config branch.master.merge "${one_ref}_not" &&
 347        git update-ref -d FETCH_HEAD &&
 348        git fetch one &&
 349        test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
 350        test $this_head = "$(git rev-parse --verify HEAD)"
 351'
 352
 353# the strange name is: a\!'b
 354test_expect_success 'quoting of a strangely named repo' '
 355        test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
 356        cat result &&
 357        grep "fatal: '\''a\\\\!'\''b'\''" result
 358'
 359
 360test_expect_success 'bundle should record HEAD correctly' '
 361
 362        cd "$D" &&
 363        git bundle create bundle5 HEAD master &&
 364        git bundle list-heads bundle5 >actual &&
 365        for h in HEAD refs/heads/master
 366        do
 367                echo "$(git rev-parse --verify $h) $h"
 368        done >expect &&
 369        test_cmp expect actual
 370
 371'
 372
 373test_expect_success 'mark initial state of origin/master' '
 374        (
 375                cd three &&
 376                git tag base-origin-master refs/remotes/origin/master
 377        )
 378'
 379
 380test_expect_success 'explicit fetch should update tracking' '
 381
 382        cd "$D" &&
 383        git branch -f side &&
 384        (
 385                cd three &&
 386                git update-ref refs/remotes/origin/master base-origin-master &&
 387                o=$(git rev-parse --verify refs/remotes/origin/master) &&
 388                git fetch origin master &&
 389                n=$(git rev-parse --verify refs/remotes/origin/master) &&
 390                test "$o" != "$n" &&
 391                test_must_fail git rev-parse --verify refs/remotes/origin/side
 392        )
 393'
 394
 395test_expect_success 'explicit pull should update tracking' '
 396
 397        cd "$D" &&
 398        git branch -f side &&
 399        (
 400                cd three &&
 401                git update-ref refs/remotes/origin/master base-origin-master &&
 402                o=$(git rev-parse --verify refs/remotes/origin/master) &&
 403                git pull origin master &&
 404                n=$(git rev-parse --verify refs/remotes/origin/master) &&
 405                test "$o" != "$n" &&
 406                test_must_fail git rev-parse --verify refs/remotes/origin/side
 407        )
 408'
 409
 410test_expect_success 'configured fetch updates tracking' '
 411
 412        cd "$D" &&
 413        git branch -f side &&
 414        (
 415                cd three &&
 416                git update-ref refs/remotes/origin/master base-origin-master &&
 417                o=$(git rev-parse --verify refs/remotes/origin/master) &&
 418                git fetch origin &&
 419                n=$(git rev-parse --verify refs/remotes/origin/master) &&
 420                test "$o" != "$n" &&
 421                git rev-parse --verify refs/remotes/origin/side
 422        )
 423'
 424
 425test_expect_success 'non-matching refspecs do not confuse tracking update' '
 426        cd "$D" &&
 427        git update-ref refs/odd/location HEAD &&
 428        (
 429                cd three &&
 430                git update-ref refs/remotes/origin/master base-origin-master &&
 431                git config --add remote.origin.fetch \
 432                        refs/odd/location:refs/remotes/origin/odd &&
 433                o=$(git rev-parse --verify refs/remotes/origin/master) &&
 434                git fetch origin master &&
 435                n=$(git rev-parse --verify refs/remotes/origin/master) &&
 436                test "$o" != "$n" &&
 437                test_must_fail git rev-parse --verify refs/remotes/origin/odd
 438        )
 439'
 440
 441test_expect_success 'pushing nonexistent branch by mistake should not segv' '
 442
 443        cd "$D" &&
 444        test_must_fail git push seven no:no
 445
 446'
 447
 448test_expect_success 'auto tag following fetches minimum' '
 449
 450        cd "$D" &&
 451        git clone .git follow &&
 452        git checkout HEAD^0 &&
 453        (
 454                for i in 1 2 3 4 5 6 7
 455                do
 456                        echo $i >>file &&
 457                        git commit -m $i -a &&
 458                        git tag -a -m $i excess-$i || exit 1
 459                done
 460        ) &&
 461        git checkout master &&
 462        (
 463                cd follow &&
 464                git fetch
 465        )
 466'
 467
 468test_expect_success 'refuse to fetch into the current branch' '
 469
 470        test_must_fail git fetch . side:master
 471
 472'
 473
 474test_expect_success 'fetch into the current branch with --update-head-ok' '
 475
 476        git fetch --update-head-ok . side:master
 477
 478'
 479
 480test_expect_success 'fetch --dry-run' '
 481
 482        rm -f .git/FETCH_HEAD &&
 483        git fetch --dry-run . &&
 484        ! test -f .git/FETCH_HEAD
 485'
 486
 487test_expect_success "should be able to fetch with duplicate refspecs" '
 488        mkdir dups &&
 489        (
 490                cd dups &&
 491                git init &&
 492                git config branch.master.remote three &&
 493                git config remote.three.url ../three/.git &&
 494                git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
 495                git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
 496                git fetch three
 497        )
 498'
 499
 500# configured prune tests
 501
 502set_config_tristate () {
 503        # var=$1 val=$2
 504        case "$2" in
 505        unset)  test_unconfig "$1" ;;
 506        *)      git config "$1" "$2" ;;
 507        esac
 508}
 509
 510test_configured_prune () {
 511        fetch_prune=$1 remote_origin_prune=$2 cmdline=$3 expected=$4
 512
 513        test_expect_success "prune fetch.prune=$1 remote.origin.prune=$2${3:+ $3}; $4" '
 514                # make sure a newbranch is there in . and also in one
 515                git branch -f newbranch &&
 516                (
 517                        cd one &&
 518                        test_unconfig fetch.prune &&
 519                        test_unconfig remote.origin.prune &&
 520                        git fetch &&
 521                        git rev-parse --verify refs/remotes/origin/newbranch
 522                )
 523
 524                # now remove it
 525                git branch -d newbranch &&
 526
 527                # then test
 528                (
 529                        cd one &&
 530                        set_config_tristate fetch.prune $fetch_prune &&
 531                        set_config_tristate remote.origin.prune $remote_origin_prune &&
 532
 533                        git fetch $cmdline &&
 534                        case "$expected" in
 535                        pruned)
 536                                test_must_fail git rev-parse --verify refs/remotes/origin/newbranch
 537                                ;;
 538                        kept)
 539                                git rev-parse --verify refs/remotes/origin/newbranch
 540                                ;;
 541                        esac
 542                )
 543        '
 544}
 545
 546test_configured_prune unset unset ""            kept
 547test_configured_prune unset unset "--no-prune"  kept
 548test_configured_prune unset unset "--prune"     pruned
 549
 550test_configured_prune false unset ""            kept
 551test_configured_prune false unset "--no-prune"  kept
 552test_configured_prune false unset "--prune"     pruned
 553
 554test_configured_prune true  unset ""            pruned
 555test_configured_prune true  unset "--prune"     pruned
 556test_configured_prune true  unset "--no-prune"  kept
 557
 558test_configured_prune unset false ""            kept
 559test_configured_prune unset false "--no-prune"  kept
 560test_configured_prune unset false "--prune"     pruned
 561
 562test_configured_prune false false ""            kept
 563test_configured_prune false false "--no-prune"  kept
 564test_configured_prune false false "--prune"     pruned
 565
 566test_configured_prune true  false ""            kept
 567test_configured_prune true  false "--prune"     pruned
 568test_configured_prune true  false "--no-prune"  kept
 569
 570test_configured_prune unset true  ""            pruned
 571test_configured_prune unset true  "--no-prune"  kept
 572test_configured_prune unset true  "--prune"     pruned
 573
 574test_configured_prune false true  ""            pruned
 575test_configured_prune false true  "--no-prune"  kept
 576test_configured_prune false true  "--prune"     pruned
 577
 578test_configured_prune true  true  ""            pruned
 579test_configured_prune true  true  "--prune"     pruned
 580test_configured_prune true  true  "--no-prune"  kept
 581
 582test_expect_success 'all boundary commits are excluded' '
 583        test_commit base &&
 584        test_commit oneside &&
 585        git checkout HEAD^ &&
 586        test_commit otherside &&
 587        git checkout master &&
 588        test_tick &&
 589        git merge otherside &&
 590        ad=$(git log --no-walk --format=%ad HEAD) &&
 591        git bundle create twoside-boundary.bdl master --since="$ad" &&
 592        convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack &&
 593        pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) &&
 594        test_bundle_object_count .git/objects/pack/pack-${pack##pack    }.pack 3
 595'
 596
 597test_expect_success 'fetching a one-level ref works' '
 598        test_commit extra &&
 599        git reset --hard HEAD^ &&
 600        git update-ref refs/foo extra &&
 601        git init one-level &&
 602        (
 603                cd one-level &&
 604                git fetch .. HEAD refs/foo
 605        )
 606'
 607
 608test_done