summaryrefslogtreecommitdiff
path: root/t/t2025-worktree-add.sh
diff options
context:
space:
mode:
Diffstat (limited to 't/t2025-worktree-add.sh')
-rwxr-xr-xt/t2025-worktree-add.sh270
1 files changed, 263 insertions, 7 deletions
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index b5c47ac602..286bba35d8 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -198,13 +198,25 @@ test_expect_success '"add" with <branch> omitted' '
test_cmp_rev HEAD bat
'
-test_expect_success '"add" auto-vivify does not clobber existing branch' '
- test_commit c1 &&
- test_commit c2 &&
- git branch precious HEAD~1 &&
- test_must_fail git worktree add precious &&
- test_cmp_rev HEAD~1 precious &&
- test_path_is_missing precious
+test_expect_success '"add" checks out existing branch of dwimd name' '
+ git branch dwim HEAD~1 &&
+ git worktree add dwim &&
+ test_cmp_rev HEAD~1 dwim &&
+ (
+ cd dwim &&
+ test_cmp_rev HEAD dwim
+ )
+'
+
+test_expect_success '"add <path>" dwim fails with checked out branch' '
+ git checkout -b test-branch &&
+ test_must_fail git worktree add test-branch &&
+ test_path_is_missing test-branch
+'
+
+test_expect_success '"add --force" with existing dwimd name doesnt die' '
+ git checkout test-branch &&
+ git worktree add --force test-branch
'
test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
@@ -240,11 +252,22 @@ test_expect_success 'add -B' '
test_cmp_rev master^ poodle
'
+test_expect_success 'add --quiet' '
+ git worktree add --quiet another-worktree master 2>actual &&
+ test_must_be_empty actual
+'
+
test_expect_success 'local clone from linked checkout' '
git clone --local here here-clone &&
( cd here-clone && git fsck )
'
+test_expect_success 'local clone --shared from linked checkout' '
+ git -C bare worktree add --detach ../baretree &&
+ git clone --local --shared baretree bare-clone &&
+ grep /bare/ bare-clone/.git/objects/info/alternates
+'
+
test_expect_success '"add" worktree with --no-checkout' '
git worktree add --no-checkout -b swamp swamp &&
! test -e swamp/init.t &&
@@ -313,5 +336,238 @@ test_expect_success 'checkout a branch under bisect' '
test_expect_success 'rename a branch under bisect not allowed' '
test_must_fail git branch -M under-bisect bisect-with-new-name
'
+# Is branch "refs/heads/$1" set to pull from "$2/$3"?
+test_branch_upstream () {
+ printf "%s\n" "$2" "refs/heads/$3" >expect.upstream &&
+ {
+ git config "branch.$1.remote" &&
+ git config "branch.$1.merge"
+ } >actual.upstream &&
+ test_cmp expect.upstream actual.upstream
+}
+
+test_expect_success '--track sets up tracking' '
+ test_when_finished rm -rf track &&
+ git worktree add --track -b track track master &&
+ test_branch_upstream track . master
+'
+
+# setup remote repository $1 and repository $2 with $1 set up as
+# remote. The remote has two branches, master and foo.
+setup_remote_repo () {
+ git init $1 &&
+ (
+ cd $1 &&
+ test_commit $1_master &&
+ git checkout -b foo &&
+ test_commit upstream_foo
+ ) &&
+ git init $2 &&
+ (
+ cd $2 &&
+ test_commit $2_master &&
+ git remote add $1 ../$1 &&
+ git config remote.$1.fetch \
+ "refs/heads/*:refs/remotes/$1/*" &&
+ git fetch --all
+ )
+}
+
+test_expect_success '--no-track avoids setting up tracking' '
+ test_when_finished rm -rf repo_upstream repo_local foo &&
+ setup_remote_repo repo_upstream repo_local &&
+ (
+ cd repo_local &&
+ git worktree add --no-track -b foo ../foo repo_upstream/foo
+ ) &&
+ (
+ cd foo &&
+ test_must_fail git config "branch.foo.remote" &&
+ test_must_fail git config "branch.foo.merge" &&
+ test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
+ )
+'
+
+test_expect_success '"add" <path> <non-existent-branch> fails' '
+ test_must_fail git worktree add foo non-existent
+'
+
+test_expect_success '"add" <path> <branch> dwims' '
+ test_when_finished rm -rf repo_upstream repo_dwim foo &&
+ setup_remote_repo repo_upstream repo_dwim &&
+ git init repo_dwim &&
+ (
+ cd repo_dwim &&
+ git worktree add ../foo foo
+ ) &&
+ (
+ cd foo &&
+ test_branch_upstream foo repo_upstream foo &&
+ test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
+ )
+'
+
+test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' '
+ test_when_finished rm -rf repo_upstream repo_dwim foo &&
+ setup_remote_repo repo_upstream repo_dwim &&
+ git init repo_dwim &&
+ (
+ cd repo_dwim &&
+ git remote add repo_upstream2 ../repo_upstream &&
+ git fetch repo_upstream2 &&
+ test_must_fail git worktree add ../foo foo &&
+ git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo &&
+ git status -uno --porcelain >status.actual &&
+ test_must_be_empty status.actual
+ ) &&
+ (
+ cd foo &&
+ test_branch_upstream foo repo_upstream foo &&
+ test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
+ )
+'
+
+test_expect_success 'git worktree add does not match remote' '
+ test_when_finished rm -rf repo_a repo_b foo &&
+ setup_remote_repo repo_a repo_b &&
+ (
+ cd repo_b &&
+ git worktree add ../foo
+ ) &&
+ (
+ cd foo &&
+ test_must_fail git config "branch.foo.remote" &&
+ test_must_fail git config "branch.foo.merge" &&
+ ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
+ )
+'
+
+test_expect_success 'git worktree add --guess-remote sets up tracking' '
+ test_when_finished rm -rf repo_a repo_b foo &&
+ setup_remote_repo repo_a repo_b &&
+ (
+ cd repo_b &&
+ git worktree add --guess-remote ../foo
+ ) &&
+ (
+ cd foo &&
+ test_branch_upstream foo repo_a foo &&
+ test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
+ )
+'
+
+test_expect_success 'git worktree add with worktree.guessRemote sets up tracking' '
+ test_when_finished rm -rf repo_a repo_b foo &&
+ setup_remote_repo repo_a repo_b &&
+ (
+ cd repo_b &&
+ git config worktree.guessRemote true &&
+ git worktree add ../foo
+ ) &&
+ (
+ cd foo &&
+ test_branch_upstream foo repo_a foo &&
+ test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
+ )
+'
+
+test_expect_success 'git worktree --no-guess-remote option overrides config' '
+ test_when_finished rm -rf repo_a repo_b foo &&
+ setup_remote_repo repo_a repo_b &&
+ (
+ cd repo_b &&
+ git config worktree.guessRemote true &&
+ git worktree add --no-guess-remote ../foo
+ ) &&
+ (
+ cd foo &&
+ test_must_fail git config "branch.foo.remote" &&
+ test_must_fail git config "branch.foo.merge" &&
+ ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
+ )
+'
+
+post_checkout_hook () {
+ gitdir=${1:-.git}
+ test_when_finished "rm -f $gitdir/hooks/post-checkout" &&
+ mkdir -p $gitdir/hooks &&
+ write_script $gitdir/hooks/post-checkout <<-\EOF
+ {
+ echo $*
+ git rev-parse --git-dir --show-toplevel
+ } >hook.actual
+ EOF
+}
+
+test_expect_success '"add" invokes post-checkout hook (branch)' '
+ post_checkout_hook &&
+ {
+ echo $ZERO_OID $(git rev-parse HEAD) 1 &&
+ echo $(pwd)/.git/worktrees/gumby &&
+ echo $(pwd)/gumby
+ } >hook.expect &&
+ git worktree add gumby &&
+ test_cmp hook.expect gumby/hook.actual
+'
+
+test_expect_success '"add" invokes post-checkout hook (detached)' '
+ post_checkout_hook &&
+ {
+ echo $ZERO_OID $(git rev-parse HEAD) 1 &&
+ echo $(pwd)/.git/worktrees/grumpy &&
+ echo $(pwd)/grumpy
+ } >hook.expect &&
+ git worktree add --detach grumpy &&
+ test_cmp hook.expect grumpy/hook.actual
+'
+
+test_expect_success '"add --no-checkout" suppresses post-checkout hook' '
+ post_checkout_hook &&
+ rm -f hook.actual &&
+ git worktree add --no-checkout gloopy &&
+ test_path_is_missing gloopy/hook.actual
+'
+
+test_expect_success '"add" in other worktree invokes post-checkout hook' '
+ post_checkout_hook &&
+ {
+ echo $ZERO_OID $(git rev-parse HEAD) 1 &&
+ echo $(pwd)/.git/worktrees/guppy &&
+ echo $(pwd)/guppy
+ } >hook.expect &&
+ git -C gloopy worktree add --detach ../guppy &&
+ test_cmp hook.expect guppy/hook.actual
+'
+
+test_expect_success '"add" in bare repo invokes post-checkout hook' '
+ rm -rf bare &&
+ git clone --bare . bare &&
+ {
+ echo $ZERO_OID $(git --git-dir=bare rev-parse HEAD) 1 &&
+ echo $(pwd)/bare/worktrees/goozy &&
+ echo $(pwd)/goozy
+ } >hook.expect &&
+ post_checkout_hook bare &&
+ git -C bare worktree add --detach ../goozy &&
+ test_cmp hook.expect goozy/hook.actual
+'
+
+test_expect_success '"add" an existing but missing worktree' '
+ git worktree add --detach pneu &&
+ test_must_fail git worktree add --detach pneu &&
+ rm -fr pneu &&
+ test_must_fail git worktree add --detach pneu &&
+ git worktree add --force --detach pneu
+'
+
+test_expect_success '"add" an existing locked but missing worktree' '
+ git worktree add --detach gnoo &&
+ git worktree lock gnoo &&
+ test_when_finished "git worktree unlock gnoo || :" &&
+ rm -fr gnoo &&
+ test_must_fail git worktree add --detach gnoo &&
+ test_must_fail git worktree add --force --detach gnoo &&
+ git worktree add --force --force --detach gnoo
+'
test_done