t / t2024-checkout-dwim.shon commit t2024: mark test using "checkout -p" with PERL prerequisite (3338e99)
   1#!/bin/sh
   2
   3test_description='checkout <branch>
   4
   5Ensures that checkout on an unborn branch does what the user expects'
   6
   7. ./test-lib.sh
   8
   9# Is the current branch "refs/heads/$1"?
  10test_branch () {
  11        printf "%s\n" "refs/heads/$1" >expect.HEAD &&
  12        git symbolic-ref HEAD >actual.HEAD &&
  13        test_cmp expect.HEAD actual.HEAD
  14}
  15
  16# Is branch "refs/heads/$1" set to pull from "$2/$3"?
  17test_branch_upstream () {
  18        printf "%s\n" "$2" "refs/heads/$3" >expect.upstream &&
  19        {
  20                git config "branch.$1.remote" &&
  21                git config "branch.$1.merge"
  22        } >actual.upstream &&
  23        test_cmp expect.upstream actual.upstream
  24}
  25
  26status_uno_is_clean () {
  27        >status.expect &&
  28        git status -uno --porcelain >status.actual &&
  29        test_cmp status.expect status.actual
  30}
  31
  32test_expect_success 'setup' '
  33        test_commit my_master &&
  34        git init repo_a &&
  35        (
  36                cd repo_a &&
  37                test_commit a_master &&
  38                git checkout -b foo &&
  39                test_commit a_foo &&
  40                git checkout -b bar &&
  41                test_commit a_bar
  42        ) &&
  43        git init repo_b &&
  44        (
  45                cd repo_b &&
  46                test_commit b_master &&
  47                git checkout -b foo &&
  48                test_commit b_foo &&
  49                git checkout -b baz &&
  50                test_commit b_baz
  51        ) &&
  52        git remote add repo_a repo_a &&
  53        git remote add repo_b repo_b &&
  54        git config remote.repo_b.fetch \
  55                "+refs/heads/*:refs/remotes/other_b/*" &&
  56        git fetch --all
  57'
  58
  59test_expect_success 'checkout of non-existing branch fails' '
  60        git checkout -B master &&
  61        test_might_fail git branch -D xyzzy &&
  62
  63        test_must_fail git checkout xyzzy &&
  64        status_uno_is_clean &&
  65        test_must_fail git rev-parse --verify refs/heads/xyzzy &&
  66        test_branch master
  67'
  68
  69test_expect_success 'checkout of branch from multiple remotes fails #1' '
  70        git checkout -B master &&
  71        test_might_fail git branch -D foo &&
  72
  73        test_must_fail git checkout foo &&
  74        status_uno_is_clean &&
  75        test_must_fail git rev-parse --verify refs/heads/foo &&
  76        test_branch master
  77'
  78
  79test_expect_success 'checkout of branch from multiple remotes fails with advice' '
  80        git checkout -B master &&
  81        test_might_fail git branch -D foo &&
  82        test_must_fail git checkout foo 2>stderr &&
  83        test_branch master &&
  84        status_uno_is_clean &&
  85        test_i18ngrep "^hint: " stderr &&
  86        test_must_fail git -c advice.checkoutAmbiguousRemoteBranchName=false \
  87                checkout foo 2>stderr &&
  88        test_branch master &&
  89        status_uno_is_clean &&
  90        test_i18ngrep ! "^hint: " stderr
  91'
  92
  93test_expect_success PERL 'checkout -p with multiple remotes does not print advice' '
  94        git checkout -B master &&
  95        test_might_fail git branch -D foo &&
  96
  97        git checkout -p foo 2>stderr &&
  98        test_i18ngrep ! "^hint: " stderr &&
  99        status_uno_is_clean
 100'
 101
 102test_expect_success 'checkout of branch from multiple remotes succeeds with checkout.defaultRemote #1' '
 103        git checkout -B master &&
 104        status_uno_is_clean &&
 105        test_might_fail git branch -D foo &&
 106
 107        git -c checkout.defaultRemote=repo_a checkout foo &&
 108        status_uno_is_clean &&
 109        test_branch foo &&
 110        test_cmp_rev remotes/repo_a/foo HEAD &&
 111        test_branch_upstream foo repo_a foo
 112'
 113
 114test_expect_success 'checkout of branch from a single remote succeeds #1' '
 115        git checkout -B master &&
 116        test_might_fail git branch -D bar &&
 117
 118        git checkout bar &&
 119        status_uno_is_clean &&
 120        test_branch bar &&
 121        test_cmp_rev remotes/repo_a/bar HEAD &&
 122        test_branch_upstream bar repo_a bar
 123'
 124
 125test_expect_success 'checkout of branch from a single remote succeeds #2' '
 126        git checkout -B master &&
 127        test_might_fail git branch -D baz &&
 128
 129        git checkout baz &&
 130        status_uno_is_clean &&
 131        test_branch baz &&
 132        test_cmp_rev remotes/other_b/baz HEAD &&
 133        test_branch_upstream baz repo_b baz
 134'
 135
 136test_expect_success '--no-guess suppresses branch auto-vivification' '
 137        git checkout -B master &&
 138        status_uno_is_clean &&
 139        test_might_fail git branch -D bar &&
 140
 141        test_must_fail git checkout --no-guess bar &&
 142        test_must_fail git rev-parse --verify refs/heads/bar &&
 143        test_branch master
 144'
 145
 146test_expect_success 'setup more remotes with unconventional refspecs' '
 147        git checkout -B master &&
 148        status_uno_is_clean &&
 149        git init repo_c &&
 150        (
 151                cd repo_c &&
 152                test_commit c_master &&
 153                git checkout -b bar &&
 154                test_commit c_bar &&
 155                git checkout -b spam &&
 156                test_commit c_spam
 157        ) &&
 158        git init repo_d &&
 159        (
 160                cd repo_d &&
 161                test_commit d_master &&
 162                git checkout -b baz &&
 163                test_commit d_baz &&
 164                git checkout -b eggs &&
 165                test_commit d_eggs
 166        ) &&
 167        git remote add repo_c repo_c &&
 168        git config remote.repo_c.fetch \
 169                "+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*" &&
 170        git remote add repo_d repo_d &&
 171        git config remote.repo_d.fetch \
 172                "+refs/heads/*:refs/repo_d/*" &&
 173        git fetch --all
 174'
 175
 176test_expect_success 'checkout of branch from multiple remotes fails #2' '
 177        git checkout -B master &&
 178        status_uno_is_clean &&
 179        test_might_fail git branch -D bar &&
 180
 181        test_must_fail git checkout bar &&
 182        status_uno_is_clean &&
 183        test_must_fail git rev-parse --verify refs/heads/bar &&
 184        test_branch master
 185'
 186
 187test_expect_success 'checkout of branch from multiple remotes fails #3' '
 188        git checkout -B master &&
 189        status_uno_is_clean &&
 190        test_might_fail git branch -D baz &&
 191
 192        test_must_fail git checkout baz &&
 193        status_uno_is_clean &&
 194        test_must_fail git rev-parse --verify refs/heads/baz &&
 195        test_branch master
 196'
 197
 198test_expect_success 'checkout of branch from a single remote succeeds #3' '
 199        git checkout -B master &&
 200        status_uno_is_clean &&
 201        test_might_fail git branch -D spam &&
 202
 203        git checkout spam &&
 204        status_uno_is_clean &&
 205        test_branch spam &&
 206        test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
 207        test_branch_upstream spam repo_c spam
 208'
 209
 210test_expect_success 'checkout of branch from a single remote succeeds #4' '
 211        git checkout -B master &&
 212        status_uno_is_clean &&
 213        test_might_fail git branch -D eggs &&
 214
 215        git checkout eggs &&
 216        status_uno_is_clean &&
 217        test_branch eggs &&
 218        test_cmp_rev refs/repo_d/eggs HEAD &&
 219        test_branch_upstream eggs repo_d eggs
 220'
 221
 222test_expect_success 'checkout of branch with a file having the same name fails' '
 223        git checkout -B master &&
 224        status_uno_is_clean &&
 225        test_might_fail git branch -D spam &&
 226
 227        >spam &&
 228        test_must_fail git checkout spam &&
 229        status_uno_is_clean &&
 230        test_must_fail git rev-parse --verify refs/heads/spam &&
 231        test_branch master
 232'
 233
 234test_expect_success 'checkout of branch with a file in subdir having the same name fails' '
 235        git checkout -B master &&
 236        status_uno_is_clean &&
 237        test_might_fail git branch -D spam &&
 238
 239        >spam &&
 240        mkdir sub &&
 241        mv spam sub/spam &&
 242        test_must_fail git -C sub checkout spam &&
 243        status_uno_is_clean &&
 244        test_must_fail git rev-parse --verify refs/heads/spam &&
 245        test_branch master
 246'
 247
 248test_expect_success 'checkout <branch> -- succeeds, even if a file with the same name exists' '
 249        git checkout -B master &&
 250        status_uno_is_clean &&
 251        test_might_fail git branch -D spam &&
 252
 253        >spam &&
 254        git checkout spam -- &&
 255        status_uno_is_clean &&
 256        test_branch spam &&
 257        test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
 258        test_branch_upstream spam repo_c spam
 259'
 260
 261test_expect_success 'loosely defined local base branch is reported correctly' '
 262
 263        git checkout master &&
 264        status_uno_is_clean &&
 265        git branch strict &&
 266        git branch loose &&
 267        git commit --allow-empty -m "a bit more" &&
 268
 269        test_config branch.strict.remote . &&
 270        test_config branch.loose.remote . &&
 271        test_config branch.strict.merge refs/heads/master &&
 272        test_config branch.loose.merge master &&
 273
 274        git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
 275        status_uno_is_clean &&
 276        git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
 277        status_uno_is_clean &&
 278
 279        test_cmp expect actual
 280'
 281
 282test_done