de1d0fcf438c7c366642c46d78e983df57ca8a59
   1#!/bin/sh
   2
   3test_description='git remote porcelain-ish'
   4
   5. ./test-lib.sh
   6
   7setup_repository () {
   8        mkdir "$1" && (
   9        cd "$1" &&
  10        git init &&
  11        >file &&
  12        git add file &&
  13        test_tick &&
  14        git commit -m "Initial" &&
  15        git checkout -b side &&
  16        >elif &&
  17        git add elif &&
  18        test_tick &&
  19        git commit -m "Second" &&
  20        git checkout master
  21        )
  22}
  23
  24tokens_match () {
  25        echo "$1" | tr ' ' '\012' | sort | sed -e '/^$/d' >expect &&
  26        echo "$2" | tr ' ' '\012' | sort | sed -e '/^$/d' >actual &&
  27        test_cmp expect actual
  28}
  29
  30check_remote_track () {
  31        actual=$(git remote show "$1" | sed -e '1,/Tracked/d') &&
  32        shift &&
  33        tokens_match "$*" "$actual"
  34}
  35
  36check_tracking_branch () {
  37        f="" &&
  38        r=$(git for-each-ref "--format=%(refname)" |
  39                sed -ne "s|^refs/remotes/$1/||p") &&
  40        shift &&
  41        tokens_match "$*" "$r"
  42}
  43
  44test_expect_success setup '
  45
  46        setup_repository one &&
  47        setup_repository two &&
  48        (
  49                cd two && git branch another
  50        ) &&
  51        git clone one test
  52
  53'
  54
  55test_expect_success 'remote information for the origin' '
  56(
  57        cd test &&
  58        tokens_match origin "$(git remote)" &&
  59        check_remote_track origin master side &&
  60        check_tracking_branch origin HEAD master side
  61)
  62'
  63
  64test_expect_success 'add another remote' '
  65(
  66        cd test &&
  67        git remote add -f second ../two &&
  68        tokens_match "origin second" "$(git remote)" &&
  69        check_remote_track origin master side &&
  70        check_remote_track second master side another &&
  71        check_tracking_branch second master side another &&
  72        git for-each-ref "--format=%(refname)" refs/remotes |
  73        sed -e "/^refs\/remotes\/origin\//d" \
  74            -e "/^refs\/remotes\/second\//d" >actual &&
  75        >expect &&
  76        test_cmp expect actual
  77)
  78'
  79
  80test_expect_success 'remote forces tracking branches' '
  81(
  82        cd test &&
  83        case `git config remote.second.fetch` in
  84        +*) true ;;
  85         *) false ;;
  86        esac
  87)
  88'
  89
  90test_expect_success 'remove remote' '
  91(
  92        cd test &&
  93        git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/master &&
  94        git remote rm second
  95)
  96'
  97
  98test_expect_success 'remove remote' '
  99(
 100        cd test &&
 101        tokens_match origin "$(git remote)" &&
 102        check_remote_track origin master side &&
 103        git for-each-ref "--format=%(refname)" refs/remotes |
 104        sed -e "/^refs\/remotes\/origin\//d" >actual &&
 105        >expect &&
 106        test_cmp expect actual
 107)
 108'
 109
 110test_expect_success 'remove remote protects non-remote branches' '
 111(
 112        cd test &&
 113        (cat >expect1 <<EOF
 114Note: A non-remote branch was not removed; to delete it, use:
 115  git branch -d master
 116EOF
 117    cat >expect2 <<EOF
 118Note: Non-remote branches were not removed; to delete them, use:
 119  git branch -d foobranch
 120  git branch -d master
 121EOF
 122) &&
 123        git tag footag
 124        git config --add remote.oops.fetch "+refs/*:refs/*" &&
 125        git remote rm oops 2>actual1 &&
 126        git branch foobranch &&
 127        git config --add remote.oops.fetch "+refs/*:refs/*" &&
 128        git remote rm oops 2>actual2 &&
 129        git branch -d foobranch &&
 130        git tag -d footag &&
 131        test_cmp expect1 actual1 &&
 132        test_cmp expect2 actual2
 133)
 134'
 135
 136cat > test/expect << EOF
 137* remote origin
 138  URL: $(pwd)/one
 139  HEAD branch: master
 140  Remote branch merged with 'git pull' while on branch master
 141    master
 142  New remote branch (next fetch will store in remotes/origin)
 143    master
 144  Tracked remote branches
 145    master
 146    side
 147  Local branches pushed with 'git push'
 148    master:upstream
 149    +refs/tags/lastbackup
 150* remote two
 151  URL: ../two
 152  HEAD branch (remote HEAD is ambiguous, may be one of the following):
 153    another
 154    master
 155EOF
 156
 157test_expect_success 'show' '
 158        (cd test &&
 159         git config --add remote.origin.fetch \
 160                refs/heads/master:refs/heads/upstream &&
 161         git fetch &&
 162         git branch -d -r origin/master &&
 163         git config --add remote.two.url ../two &&
 164         (cd ../one &&
 165          echo 1 > file &&
 166          test_tick &&
 167          git commit -m update file) &&
 168         git config remote.origin.push \
 169                refs/heads/master:refs/heads/upstream &&
 170         git config --add remote.origin.push \
 171                +refs/tags/lastbackup &&
 172         git remote show origin two > output &&
 173         test_cmp expect output)
 174'
 175
 176cat > test/expect << EOF
 177* remote origin
 178  URL: $(pwd)/one
 179  HEAD branch: (not queried)
 180  Remote branch merged with 'git pull' while on branch master
 181    master
 182  Tracked remote branches
 183    master
 184    side
 185  Local branches pushed with 'git push'
 186    master:upstream
 187    +refs/tags/lastbackup
 188EOF
 189
 190test_expect_success 'show -n' '
 191        (mv one one.unreachable &&
 192         cd test &&
 193         git remote show -n origin > output &&
 194         mv ../one.unreachable ../one &&
 195         test_cmp expect output)
 196'
 197
 198test_expect_success 'prune' '
 199        (cd one &&
 200         git branch -m side side2) &&
 201        (cd test &&
 202         git fetch origin &&
 203         git remote prune origin &&
 204         git rev-parse refs/remotes/origin/side2 &&
 205         test_must_fail git rev-parse refs/remotes/origin/side)
 206'
 207
 208test_expect_success 'set-head --delete' '
 209        (cd test &&
 210         git symbolic-ref refs/remotes/origin/HEAD &&
 211         git remote set-head --delete origin &&
 212         test_must_fail git symbolic-ref refs/remotes/origin/HEAD)
 213'
 214
 215test_expect_success 'set-head --auto' '
 216        (cd test &&
 217         git remote set-head --auto origin &&
 218         echo refs/remotes/origin/master >expect &&
 219         git symbolic-ref refs/remotes/origin/HEAD >output &&
 220         test_cmp expect output
 221        )
 222'
 223
 224cat >test/expect <<EOF
 225error: Multiple remote HEAD branches. Please choose one explicitly with:
 226  git remote set-head two another
 227  git remote set-head two master
 228EOF
 229
 230test_expect_success 'set-head --auto fails w/multiple HEADs' '
 231        (cd test &&
 232         test_must_fail git remote set-head --auto two >output 2>&1 &&
 233        test_cmp expect output)
 234'
 235
 236cat >test/expect <<EOF
 237refs/remotes/origin/side2
 238EOF
 239
 240test_expect_success 'set-head explicit' '
 241        (cd test &&
 242         git remote set-head origin side2 &&
 243         git symbolic-ref refs/remotes/origin/HEAD >output &&
 244         git remote set-head origin master &&
 245         test_cmp expect output)
 246'
 247
 248cat > test/expect << EOF
 249Pruning origin
 250URL: $(pwd)/one
 251 * [would prune] origin/side2
 252EOF
 253
 254test_expect_success 'prune --dry-run' '
 255        (cd one &&
 256         git branch -m side2 side) &&
 257        (cd test &&
 258         git remote prune --dry-run origin > output &&
 259         git rev-parse refs/remotes/origin/side2 &&
 260         test_must_fail git rev-parse refs/remotes/origin/side &&
 261        (cd ../one &&
 262         git branch -m side side2) &&
 263         test_cmp expect output)
 264'
 265
 266test_expect_success 'add --mirror && prune' '
 267        (mkdir mirror &&
 268         cd mirror &&
 269         git init --bare &&
 270         git remote add --mirror -f origin ../one) &&
 271        (cd one &&
 272         git branch -m side2 side) &&
 273        (cd mirror &&
 274         git rev-parse --verify refs/heads/side2 &&
 275         test_must_fail git rev-parse --verify refs/heads/side &&
 276         git fetch origin &&
 277         git remote prune origin &&
 278         test_must_fail git rev-parse --verify refs/heads/side2 &&
 279         git rev-parse --verify refs/heads/side)
 280'
 281
 282test_expect_success 'add alt && prune' '
 283        (mkdir alttst &&
 284         cd alttst &&
 285         git init &&
 286         git remote add -f origin ../one &&
 287         git config remote.alt.url ../one &&
 288         git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*") &&
 289        (cd one &&
 290         git branch -m side side2) &&
 291        (cd alttst &&
 292         git rev-parse --verify refs/remotes/origin/side &&
 293         test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
 294         git fetch alt &&
 295         git remote prune alt &&
 296         test_must_fail git rev-parse --verify refs/remotes/origin/side &&
 297         git rev-parse --verify refs/remotes/origin/side2)
 298'
 299
 300cat > one/expect << EOF
 301  apis/master
 302  apis/side
 303  drosophila/another
 304  drosophila/master
 305  drosophila/side
 306EOF
 307
 308test_expect_success 'update' '
 309
 310        (cd one &&
 311         git remote add drosophila ../two &&
 312         git remote add apis ../mirror &&
 313         git remote update &&
 314         git branch -r > output &&
 315         test_cmp expect output)
 316
 317'
 318
 319cat > one/expect << EOF
 320  drosophila/another
 321  drosophila/master
 322  drosophila/side
 323  manduca/master
 324  manduca/side
 325  megaloprepus/master
 326  megaloprepus/side
 327EOF
 328
 329test_expect_success 'update with arguments' '
 330
 331        (cd one &&
 332         for b in $(git branch -r)
 333         do
 334                git branch -r -d $b || break
 335         done &&
 336         git remote add manduca ../mirror &&
 337         git remote add megaloprepus ../mirror &&
 338         git config remotes.phobaeticus "drosophila megaloprepus" &&
 339         git config remotes.titanus manduca &&
 340         git remote update phobaeticus titanus &&
 341         git branch -r > output &&
 342         test_cmp expect output)
 343
 344'
 345
 346cat > one/expect << EOF
 347  apis/master
 348  apis/side
 349  manduca/master
 350  manduca/side
 351  megaloprepus/master
 352  megaloprepus/side
 353EOF
 354
 355test_expect_success 'update default' '
 356
 357        (cd one &&
 358         for b in $(git branch -r)
 359         do
 360                git branch -r -d $b || break
 361         done &&
 362         git config remote.drosophila.skipDefaultUpdate true &&
 363         git remote update default &&
 364         git branch -r > output &&
 365         test_cmp expect output)
 366
 367'
 368
 369cat > one/expect << EOF
 370  drosophila/another
 371  drosophila/master
 372  drosophila/side
 373EOF
 374
 375test_expect_success 'update default (overridden, with funny whitespace)' '
 376
 377        (cd one &&
 378         for b in $(git branch -r)
 379         do
 380                git branch -r -d $b || break
 381         done &&
 382         git config remotes.default "$(printf "\t drosophila  \n")" &&
 383         git remote update default &&
 384         git branch -r > output &&
 385         test_cmp expect output)
 386
 387'
 388
 389test_expect_success '"remote show" does not show symbolic refs' '
 390
 391        git clone one three &&
 392        (cd three &&
 393         git remote show origin > output &&
 394         ! grep "^ *HEAD$" < output &&
 395         ! grep -i stale < output)
 396
 397'
 398
 399test_expect_success 'reject adding remote with an invalid name' '
 400
 401        test_must_fail git remote add some:url desired-name
 402
 403'
 404
 405# The first three test if the tracking branches are properly renamed,
 406# the last two ones check if the config is updated.
 407
 408test_expect_success 'rename a remote' '
 409
 410        git clone one four &&
 411        (cd four &&
 412         git remote rename origin upstream &&
 413         rmdir .git/refs/remotes/origin &&
 414         test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
 415         test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
 416         test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
 417         test "$(git config branch.master.remote)" = "upstream")
 418
 419'
 420
 421cat > remotes_origin << EOF
 422URL: $(pwd)/one
 423Push: refs/heads/master:refs/heads/upstream
 424Pull: refs/heads/master:refs/heads/origin
 425EOF
 426
 427test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
 428        git clone one five &&
 429        origin_url=$(pwd)/one &&
 430        (cd five &&
 431         git remote rm origin &&
 432         mkdir -p .git/remotes &&
 433         cat ../remotes_origin > .git/remotes/origin &&
 434         git remote rename origin origin &&
 435         ! test -f .git/remotes/origin &&
 436         test "$(git config remote.origin.url)" = "$origin_url" &&
 437         test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
 438         test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
 439'
 440
 441test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
 442        git clone one six &&
 443        origin_url=$(pwd)/one &&
 444        (cd six &&
 445         git remote rm origin &&
 446         echo "$origin_url" > .git/branches/origin &&
 447         git remote rename origin origin &&
 448         ! test -f .git/branches/origin &&
 449         test "$(git config remote.origin.url)" = "$origin_url" &&
 450         test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
 451'
 452
 453test_expect_success 'remote prune to cause a dangling symref' '
 454        git clone one seven &&
 455        (
 456                cd one &&
 457                git checkout side2 &&
 458                git branch -D master
 459        ) &&
 460        (
 461                cd seven &&
 462                git remote prune origin
 463        ) 2>err &&
 464        grep "has become dangling" err &&
 465
 466        : And the dangling symref will not cause other annoying errors
 467        (
 468                cd seven &&
 469                git branch -a
 470        ) 2>err &&
 471        ! grep "points nowhere" err
 472        (
 473                cd seven &&
 474                test_must_fail git branch nomore origin
 475        ) 2>err &&
 476        grep "dangling symref" err
 477'
 478
 479test_done
 480