91525c3f9c1a04437516dbc7fa095cef0ef4a666
   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
 208cat > test/expect << EOF
 209Pruning origin
 210URL: $(pwd)/one
 211 * [would prune] origin/side2
 212EOF
 213
 214test_expect_success 'prune --dry-run' '
 215        (cd one &&
 216         git branch -m side2 side) &&
 217        (cd test &&
 218         git remote prune --dry-run origin > output &&
 219         git rev-parse refs/remotes/origin/side2 &&
 220         test_must_fail git rev-parse refs/remotes/origin/side &&
 221        (cd ../one &&
 222         git branch -m side side2) &&
 223         test_cmp expect output)
 224'
 225
 226test_expect_success 'add --mirror && prune' '
 227        (mkdir mirror &&
 228         cd mirror &&
 229         git init --bare &&
 230         git remote add --mirror -f origin ../one) &&
 231        (cd one &&
 232         git branch -m side2 side) &&
 233        (cd mirror &&
 234         git rev-parse --verify refs/heads/side2 &&
 235         test_must_fail git rev-parse --verify refs/heads/side &&
 236         git fetch origin &&
 237         git remote prune origin &&
 238         test_must_fail git rev-parse --verify refs/heads/side2 &&
 239         git rev-parse --verify refs/heads/side)
 240'
 241
 242test_expect_success 'add alt && prune' '
 243        (mkdir alttst &&
 244         cd alttst &&
 245         git init &&
 246         git remote add -f origin ../one &&
 247         git config remote.alt.url ../one &&
 248         git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*") &&
 249        (cd one &&
 250         git branch -m side side2) &&
 251        (cd alttst &&
 252         git rev-parse --verify refs/remotes/origin/side &&
 253         test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
 254         git fetch alt &&
 255         git remote prune alt &&
 256         test_must_fail git rev-parse --verify refs/remotes/origin/side &&
 257         git rev-parse --verify refs/remotes/origin/side2)
 258'
 259
 260cat > one/expect << EOF
 261  apis/master
 262  apis/side
 263  drosophila/another
 264  drosophila/master
 265  drosophila/side
 266EOF
 267
 268test_expect_success 'update' '
 269
 270        (cd one &&
 271         git remote add drosophila ../two &&
 272         git remote add apis ../mirror &&
 273         git remote update &&
 274         git branch -r > output &&
 275         test_cmp expect output)
 276
 277'
 278
 279cat > one/expect << EOF
 280  drosophila/another
 281  drosophila/master
 282  drosophila/side
 283  manduca/master
 284  manduca/side
 285  megaloprepus/master
 286  megaloprepus/side
 287EOF
 288
 289test_expect_success 'update with arguments' '
 290
 291        (cd one &&
 292         for b in $(git branch -r)
 293         do
 294                git branch -r -d $b || break
 295         done &&
 296         git remote add manduca ../mirror &&
 297         git remote add megaloprepus ../mirror &&
 298         git config remotes.phobaeticus "drosophila megaloprepus" &&
 299         git config remotes.titanus manduca &&
 300         git remote update phobaeticus titanus &&
 301         git branch -r > output &&
 302         test_cmp expect output)
 303
 304'
 305
 306cat > one/expect << EOF
 307  apis/master
 308  apis/side
 309  manduca/master
 310  manduca/side
 311  megaloprepus/master
 312  megaloprepus/side
 313EOF
 314
 315test_expect_success 'update default' '
 316
 317        (cd one &&
 318         for b in $(git branch -r)
 319         do
 320                git branch -r -d $b || break
 321         done &&
 322         git config remote.drosophila.skipDefaultUpdate true &&
 323         git remote update default &&
 324         git branch -r > output &&
 325         test_cmp expect output)
 326
 327'
 328
 329cat > one/expect << EOF
 330  drosophila/another
 331  drosophila/master
 332  drosophila/side
 333EOF
 334
 335test_expect_success 'update default (overridden, with funny whitespace)' '
 336
 337        (cd one &&
 338         for b in $(git branch -r)
 339         do
 340                git branch -r -d $b || break
 341         done &&
 342         git config remotes.default "$(printf "\t drosophila  \n")" &&
 343         git remote update default &&
 344         git branch -r > output &&
 345         test_cmp expect output)
 346
 347'
 348
 349test_expect_success '"remote show" does not show symbolic refs' '
 350
 351        git clone one three &&
 352        (cd three &&
 353         git remote show origin > output &&
 354         ! grep "^ *HEAD$" < output &&
 355         ! grep -i stale < output)
 356
 357'
 358
 359test_expect_success 'reject adding remote with an invalid name' '
 360
 361        test_must_fail git remote add some:url desired-name
 362
 363'
 364
 365# The first three test if the tracking branches are properly renamed,
 366# the last two ones check if the config is updated.
 367
 368test_expect_success 'rename a remote' '
 369
 370        git clone one four &&
 371        (cd four &&
 372         git remote rename origin upstream &&
 373         rmdir .git/refs/remotes/origin &&
 374         test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
 375         test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
 376         test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
 377         test "$(git config branch.master.remote)" = "upstream")
 378
 379'
 380
 381cat > remotes_origin << EOF
 382URL: $(pwd)/one
 383Push: refs/heads/master:refs/heads/upstream
 384Pull: refs/heads/master:refs/heads/origin
 385EOF
 386
 387test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
 388        git clone one five &&
 389        origin_url=$(pwd)/one &&
 390        (cd five &&
 391         git remote rm origin &&
 392         mkdir -p .git/remotes &&
 393         cat ../remotes_origin > .git/remotes/origin &&
 394         git remote rename origin origin &&
 395         ! test -f .git/remotes/origin &&
 396         test "$(git config remote.origin.url)" = "$origin_url" &&
 397         test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
 398         test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
 399'
 400
 401test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
 402        git clone one six &&
 403        origin_url=$(pwd)/one &&
 404        (cd six &&
 405         git remote rm origin &&
 406         echo "$origin_url" > .git/branches/origin &&
 407         git remote rename origin origin &&
 408         ! test -f .git/branches/origin &&
 409         test "$(git config remote.origin.url)" = "$origin_url" &&
 410         test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
 411'
 412
 413test_expect_success 'remote prune to cause a dangling symref' '
 414        git clone one seven &&
 415        (
 416                cd one &&
 417                git checkout side2 &&
 418                git branch -D master
 419        ) &&
 420        (
 421                cd seven &&
 422                git remote prune origin
 423        ) 2>err &&
 424        grep "has become dangling" err &&
 425
 426        : And the dangling symref will not cause other annoying errors
 427        (
 428                cd seven &&
 429                git branch -a
 430        ) 2>err &&
 431        ! grep "points nowhere" err
 432        (
 433                cd seven &&
 434                test_must_fail git branch nomore origin
 435        ) 2>err &&
 436        grep "dangling symref" err
 437'
 438
 439test_done
 440