#!/bin/sh global test_description := ''checkout Ensures that checkout on an unborn branch does what the user expects'' source ./test-lib.sh # Is the current branch "refs/heads/$1"? proc test_branch { printf "%s\n" "refs/heads/$1" >expect.HEAD && git symbolic-ref HEAD >actual.HEAD && test_cmp expect.HEAD actual.HEAD } # Is branch "refs/heads/$1" set to pull from "$2/$3"? proc test_branch_upstream { printf "%s\n" $2 "refs/heads/$3" >expect.upstream && do { git config "branch.$1.remote" && git config "branch.$1.merge" } >actual.upstream && test_cmp expect.upstream actual.upstream } test_expect_success 'setup' ' test_commit my_master && git init repo_a && ( cd repo_a && test_commit a_master && git checkout -b foo && test_commit a_foo && git checkout -b bar && test_commit a_bar ) && git init repo_b && ( cd repo_b && test_commit b_master && git checkout -b foo && test_commit b_foo && git checkout -b baz && test_commit b_baz ) && git remote add repo_a repo_a && git remote add repo_b repo_b && git config remote.repo_b.fetch \ "+refs/heads/*:refs/remotes/other_b/*" && git fetch --all ' test_expect_success 'checkout of non-existing branch fails' ' git checkout -B master && test_might_fail git branch -D xyzzy && test_must_fail git checkout xyzzy && test_must_fail git rev-parse --verify refs/heads/xyzzy && test_branch master ' test_expect_success 'checkout of branch from multiple remotes fails #1' ' git checkout -B master && test_might_fail git branch -D foo && test_must_fail git checkout foo && test_must_fail git rev-parse --verify refs/heads/foo && test_branch master ' test_expect_success 'checkout of branch from a single remote succeeds #1' ' git checkout -B master && test_might_fail git branch -D bar && git checkout bar && test_branch bar && test_cmp_rev remotes/repo_a/bar HEAD && test_branch_upstream bar repo_a bar ' test_expect_success 'checkout of branch from a single remote succeeds #2' ' git checkout -B master && test_might_fail git branch -D baz && git checkout baz && test_branch baz && test_cmp_rev remotes/other_b/baz HEAD && test_branch_upstream baz repo_b baz ' test_expect_success '--no-guess suppresses branch auto-vivification' ' git checkout -B master && test_might_fail git branch -D bar && test_must_fail git checkout --no-guess bar && test_must_fail git rev-parse --verify refs/heads/bar && test_branch master ' test_expect_success 'setup more remotes with unconventional refspecs' ' git checkout -B master && git init repo_c && ( cd repo_c && test_commit c_master && git checkout -b bar && test_commit c_bar && git checkout -b spam && test_commit c_spam ) && git init repo_d && ( cd repo_d && test_commit d_master && git checkout -b baz && test_commit d_baz && git checkout -b eggs && test_commit d_eggs ) && git remote add repo_c repo_c && git config remote.repo_c.fetch \ "+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*" && git remote add repo_d repo_d && git config remote.repo_d.fetch \ "+refs/heads/*:refs/repo_d/*" && git fetch --all ' test_expect_success 'checkout of branch from multiple remotes fails #2' ' git checkout -B master && test_might_fail git branch -D bar && test_must_fail git checkout bar && test_must_fail git rev-parse --verify refs/heads/bar && test_branch master ' test_expect_success 'checkout of branch from multiple remotes fails #3' ' git checkout -B master && test_might_fail git branch -D baz && test_must_fail git checkout baz && test_must_fail git rev-parse --verify refs/heads/baz && test_branch master ' test_expect_success 'checkout of branch from a single remote succeeds #3' ' git checkout -B master && test_might_fail git branch -D spam && git checkout spam && test_branch spam && test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD && test_branch_upstream spam repo_c spam ' test_expect_success 'checkout of branch from a single remote succeeds #4' ' git checkout -B master && test_might_fail git branch -D eggs && git checkout eggs && test_branch eggs && test_cmp_rev refs/repo_d/eggs HEAD && test_branch_upstream eggs repo_d eggs ' test_expect_success 'checkout of branch with a file having the same name fails' ' git checkout -B master && test_might_fail git branch -D spam && >spam && test_must_fail git checkout spam && test_must_fail git rev-parse --verify refs/heads/spam && test_branch master ' test_expect_success 'checkout of branch with a file in subdir having the same name fails' ' git checkout -B master && test_might_fail git branch -D spam && >spam && mkdir sub && mv spam sub/spam && test_must_fail git -C sub checkout spam && test_must_fail git rev-parse --verify refs/heads/spam && test_branch master ' test_expect_success 'checkout -- succeeds, even if a file with the same name exists' ' git checkout -B master && test_might_fail git branch -D spam && >spam && git checkout spam -- && test_branch spam && test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD && test_branch_upstream spam repo_c spam ' test_expect_success 'loosely defined local base branch is reported correctly' ' git checkout master && git branch strict && git branch loose && git commit --allow-empty -m "a bit more" && test_config branch.strict.remote . && test_config branch.loose.remote . && test_config branch.strict.merge refs/heads/master && test_config branch.loose.merge master && git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect && git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual && test_cmp expect actual ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: { (SQ <"checkout \n"> <"\n"> <"Ensures that checkout on an unborn branch does what the user expects"> ) } spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (FuncDef name: test_branch body: (BraceGroup children: [ (AndOr children: [ (SimpleCommand words: [ {(printf)} {(DQ ("%s") (EscapedLiteralPart token:))} {(DQ (refs/heads/) ($ VSub_Number "$1"))} ] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(expect.HEAD)} spids:[40])] ) (AndOr children: [ (SimpleCommand words: [{(git)} {(symbolic-ref)} {(HEAD)}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(actual.HEAD)} spids:[52])] ) (C {(test_cmp)} {(expect.HEAD)} {(actual.HEAD)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [25] ) spids: [20 24] ) (FuncDef name: test_branch_upstream body: (BraceGroup children: [ (AndOr children: [ (SimpleCommand words: [ {(printf)} {(DQ ("%s") (EscapedLiteralPart token:))} {(DQ ($ VSub_Number "$2"))} {(DQ (refs/heads/) ($ VSub_Number "$3"))} ] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(expect.upstream)} spids:[94])] ) (AndOr children: [ (BraceGroup children: [ (AndOr children: [ (C {(git)} {(config)} {(DQ (branch.) ($ VSub_Number "$1") (.remote))}) (C {(git)} {(config)} {(DQ (branch.) ($ VSub_Number "$1") (.merge))}) ] op_id: Op_DAmp ) ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(actual.upstream)} spids: [129] ) ] spids: [100] ) (C {(test_cmp)} {(expect.upstream)} {(actual.upstream)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [75] ) spids: [70 74] ) (C {(test_expect_success)} {(SQ )} { (SQ <"\n"> <"\ttest_commit my_master &&\n"> <"\tgit init repo_a &&\n"> <"\t(\n"> <"\t\tcd repo_a &&\n"> <"\t\ttest_commit a_master &&\n"> <"\t\tgit checkout -b foo &&\n"> <"\t\ttest_commit a_foo &&\n"> <"\t\tgit checkout -b bar &&\n"> <"\t\ttest_commit a_bar\n"> <"\t) &&\n"> <"\tgit init repo_b &&\n"> <"\t(\n"> <"\t\tcd repo_b &&\n"> <"\t\ttest_commit b_master &&\n"> <"\t\tgit checkout -b foo &&\n"> <"\t\ttest_commit b_foo &&\n"> <"\t\tgit checkout -b baz &&\n"> <"\t\ttest_commit b_baz\n"> <"\t) &&\n"> <"\tgit remote add repo_a repo_a &&\n"> <"\tgit remote add repo_b repo_b &&\n"> <"\tgit config remote.repo_b.fetch \\\n"> <"\t\t\"+refs/heads/*:refs/remotes/other_b/*\" &&\n"> <"\tgit fetch --all\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of non-existing branch fails">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D xyzzy &&\n"> <"\n"> <"\ttest_must_fail git checkout xyzzy &&\n"> <"\ttest_must_fail git rev-parse --verify refs/heads/xyzzy &&\n"> <"\ttest_branch master\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch from multiple remotes fails #1">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D foo &&\n"> <"\n"> <"\ttest_must_fail git checkout foo &&\n"> <"\ttest_must_fail git rev-parse --verify refs/heads/foo &&\n"> <"\ttest_branch master\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch from a single remote succeeds #1">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D bar &&\n"> <"\n"> <"\tgit checkout bar &&\n"> <"\ttest_branch bar &&\n"> <"\ttest_cmp_rev remotes/repo_a/bar HEAD &&\n"> <"\ttest_branch_upstream bar repo_a bar\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch from a single remote succeeds #2">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D baz &&\n"> <"\n"> <"\tgit checkout baz &&\n"> <"\ttest_branch baz &&\n"> <"\ttest_cmp_rev remotes/other_b/baz HEAD &&\n"> <"\ttest_branch_upstream baz repo_b baz\n"> ) } ) (C {(test_expect_success)} {(SQ <"--no-guess suppresses branch auto-vivification">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D bar &&\n"> <"\n"> <"\ttest_must_fail git checkout --no-guess bar &&\n"> <"\ttest_must_fail git rev-parse --verify refs/heads/bar &&\n"> <"\ttest_branch master\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup more remotes with unconventional refspecs">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\tgit init repo_c &&\n"> <"\t(\n"> <"\t\tcd repo_c &&\n"> <"\t\ttest_commit c_master &&\n"> <"\t\tgit checkout -b bar &&\n"> <"\t\ttest_commit c_bar &&\n"> <"\t\tgit checkout -b spam &&\n"> <"\t\ttest_commit c_spam\n"> <"\t) &&\n"> <"\tgit init repo_d &&\n"> <"\t(\n"> <"\t\tcd repo_d &&\n"> <"\t\ttest_commit d_master &&\n"> <"\t\tgit checkout -b baz &&\n"> <"\t\ttest_commit d_baz &&\n"> <"\t\tgit checkout -b eggs &&\n"> <"\t\ttest_commit d_eggs\n"> <"\t) &&\n"> <"\tgit remote add repo_c repo_c &&\n"> <"\tgit config remote.repo_c.fetch \\\n"> <"\t\t\"+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*\" &&\n"> <"\tgit remote add repo_d repo_d &&\n"> <"\tgit config remote.repo_d.fetch \\\n"> <"\t\t\"+refs/heads/*:refs/repo_d/*\" &&\n"> <"\tgit fetch --all\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch from multiple remotes fails #2">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D bar &&\n"> <"\n"> <"\ttest_must_fail git checkout bar &&\n"> <"\ttest_must_fail git rev-parse --verify refs/heads/bar &&\n"> <"\ttest_branch master\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch from multiple remotes fails #3">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D baz &&\n"> <"\n"> <"\ttest_must_fail git checkout baz &&\n"> <"\ttest_must_fail git rev-parse --verify refs/heads/baz &&\n"> <"\ttest_branch master\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch from a single remote succeeds #3">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D spam &&\n"> <"\n"> <"\tgit checkout spam &&\n"> <"\ttest_branch spam &&\n"> <"\ttest_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&\n"> <"\ttest_branch_upstream spam repo_c spam\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch from a single remote succeeds #4">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D eggs &&\n"> <"\n"> <"\tgit checkout eggs &&\n"> <"\ttest_branch eggs &&\n"> <"\ttest_cmp_rev refs/repo_d/eggs HEAD &&\n"> <"\ttest_branch_upstream eggs repo_d eggs\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch with a file having the same name fails">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D spam &&\n"> <"\n"> <"\t>spam &&\n"> <"\ttest_must_fail git checkout spam &&\n"> <"\ttest_must_fail git rev-parse --verify refs/heads/spam &&\n"> <"\ttest_branch master\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout of branch with a file in subdir having the same name fails">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D spam &&\n"> <"\n"> <"\t>spam &&\n"> <"\tmkdir sub &&\n"> <"\tmv spam sub/spam &&\n"> <"\ttest_must_fail git -C sub checkout spam &&\n"> <"\ttest_must_fail git rev-parse --verify refs/heads/spam &&\n"> <"\ttest_branch master\n"> ) } ) (C {(test_expect_success)} {(SQ <"checkout -- succeeds, even if a file with the same name exists">)} { (SQ <"\n"> <"\tgit checkout -B master &&\n"> <"\ttest_might_fail git branch -D spam &&\n"> <"\n"> <"\t>spam &&\n"> <"\tgit checkout spam -- &&\n"> <"\ttest_branch spam &&\n"> <"\ttest_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&\n"> <"\ttest_branch_upstream spam repo_c spam\n"> ) } ) (C {(test_expect_success)} {(SQ <"loosely defined local base branch is reported correctly">)} { (SQ <"\n"> <"\n"> <"\tgit checkout master &&\n"> <"\tgit branch strict &&\n"> <"\tgit branch loose &&\n"> <"\tgit commit --allow-empty -m \"a bit more\" &&\n"> <"\n"> <"\ttest_config branch.strict.remote . &&\n"> <"\ttest_config branch.loose.remote . &&\n"> <"\ttest_config branch.strict.merge refs/heads/master &&\n"> <"\ttest_config branch.loose.merge master &&\n"> <"\n"> <"\tgit checkout strict | sed -e \"s/strict/BRANCHNAME/g\" >expect &&\n"> <"\tgit checkout loose | sed -e \"s/loose/BRANCHNAME/g\" >actual &&\n"> <"\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_done)}) ] )