| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='prune $GIT_DIR/worktrees' |
| 4 | |
| 5 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
| 6 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
| 7 | |
| 8 | . ./test-lib.sh |
| 9 | |
| 10 | test_expect_success initialize ' |
| 11 | git commit --allow-empty -m init |
| 12 | ' |
| 13 | |
| 14 | test_expect_success 'worktree prune on normal repo' ' |
| 15 | git worktree prune && |
| 16 | test_must_fail git worktree prune abc |
| 17 | ' |
| 18 | |
| 19 | test_expect_success 'prune files inside $GIT_DIR/worktrees' ' |
| 20 | mkdir .git/worktrees && |
| 21 | : >.git/worktrees/abc && |
| 22 | git worktree prune --verbose 2>actual && |
| 23 | cat >expect <<EOF && |
| 24 | Removing worktrees/abc: not a valid directory |
| 25 | EOF |
| 26 | test_cmp expect actual && |
| 27 | test_path_is_missing .git/worktrees/abc && |
| 28 | test_path_is_missing .git/worktrees |
| 29 | ' |
| 30 | |
| 31 | test_expect_success 'prune directories without gitdir' ' |
| 32 | mkdir -p .git/worktrees/def/abc && |
| 33 | : >.git/worktrees/def/def && |
| 34 | cat >expect <<EOF && |
| 35 | Removing worktrees/def: gitdir file does not exist |
| 36 | EOF |
| 37 | git worktree prune --verbose 2>actual && |
| 38 | test_cmp expect actual && |
| 39 | test_path_is_missing .git/worktrees/def && |
| 40 | test_path_is_missing .git/worktrees |
| 41 | ' |
| 42 | |
| 43 | test_expect_success SANITY 'prune directories with unreadable gitdir' ' |
| 44 | mkdir -p .git/worktrees/def/abc && |
| 45 | : >.git/worktrees/def/def && |
| 46 | : >.git/worktrees/def/gitdir && |
| 47 | chmod u-r .git/worktrees/def/gitdir && |
| 48 | git worktree prune --verbose 2>actual && |
| 49 | test_grep "Removing worktrees/def: unable to read gitdir file" actual && |
| 50 | test_path_is_missing .git/worktrees/def && |
| 51 | test_path_is_missing .git/worktrees |
| 52 | ' |
| 53 | |
| 54 | test_expect_success 'prune directories with invalid gitdir' ' |
| 55 | mkdir -p .git/worktrees/def/abc && |
| 56 | : >.git/worktrees/def/def && |
| 57 | : >.git/worktrees/def/gitdir && |
| 58 | git worktree prune --verbose 2>actual && |
| 59 | test_grep "Removing worktrees/def: invalid gitdir file" actual && |
| 60 | test_path_is_missing .git/worktrees/def && |
| 61 | test_path_is_missing .git/worktrees |
| 62 | ' |
| 63 | |
| 64 | test_expect_success 'prune directories with gitdir pointing to nowhere' ' |
| 65 | mkdir -p .git/worktrees/def/abc && |
| 66 | : >.git/worktrees/def/def && |
| 67 | echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir && |
| 68 | git worktree prune --verbose 2>actual && |
| 69 | test_grep "Removing worktrees/def: gitdir file points to non-existent location" actual && |
| 70 | test_path_is_missing .git/worktrees/def && |
| 71 | test_path_is_missing .git/worktrees |
| 72 | ' |
| 73 | |
| 74 | test_expect_success 'not prune locked checkout' ' |
| 75 | test_when_finished rm -r .git/worktrees && |
| 76 | mkdir -p .git/worktrees/ghi && |
| 77 | : >.git/worktrees/ghi/locked && |
| 78 | git worktree prune && |
| 79 | test_path_is_dir .git/worktrees/ghi |
| 80 | ' |
| 81 | |
| 82 | test_expect_success 'not prune recent checkouts' ' |
| 83 | test_when_finished rm -r .git/worktrees && |
| 84 | git worktree add jlm HEAD && |
| 85 | test_path_is_dir .git/worktrees/jlm && |
| 86 | rm -rf jlm && |
| 87 | git worktree prune --verbose --expire=2.days.ago && |
| 88 | test_path_is_dir .git/worktrees/jlm |
| 89 | ' |
| 90 | |
| 91 | test_expect_success 'not prune proper checkouts' ' |
| 92 | test_when_finished rm -r .git/worktrees && |
| 93 | git worktree add --detach "$PWD/nop" main && |
| 94 | git worktree prune && |
| 95 | test_path_is_dir .git/worktrees/nop |
| 96 | ' |
| 97 | |
| 98 | test_expect_success 'prune duplicate (linked/linked)' ' |
| 99 | test_when_finished rm -fr .git/worktrees w1 w2 && |
| 100 | git worktree add --detach w1 && |
| 101 | git worktree add --detach w2 && |
| 102 | sed "s/w2/w1/" .git/worktrees/w2/gitdir >.git/worktrees/w2/gitdir.new && |
| 103 | mv .git/worktrees/w2/gitdir.new .git/worktrees/w2/gitdir && |
| 104 | git worktree prune --verbose 2>actual && |
| 105 | test_grep "duplicate entry" actual && |
| 106 | test_path_is_dir .git/worktrees/w1 && |
| 107 | test_path_is_missing .git/worktrees/w2 |
| 108 | ' |
| 109 | |
| 110 | test_expect_success 'prune duplicate (main/linked)' ' |
| 111 | test_when_finished rm -fr repo wt && |
| 112 | test_create_repo repo && |
| 113 | test_commit -C repo x && |
| 114 | git -C repo worktree add --detach ../wt && |
| 115 | rm -fr wt && |
| 116 | mv repo wt && |
| 117 | git -C wt worktree prune --verbose 2>actual && |
| 118 | test_grep "duplicate entry" actual && |
| 119 | test_path_is_missing .git/worktrees/wt |
| 120 | ' |
| 121 | |
| 122 | test_expect_success 'not prune proper worktrees inside linked worktree with relative paths' ' |
| 123 | test_when_finished rm -rf repo wt_ext && |
| 124 | git init repo && |
| 125 | ( |
| 126 | cd repo && |
| 127 | git config worktree.useRelativePaths true && |
| 128 | echo content >file && |
| 129 | git add file && |
| 130 | git commit -m msg && |
| 131 | git worktree add ../wt_ext && |
| 132 | git worktree add wt_int && |
| 133 | cd wt_int && |
| 134 | git worktree prune -v >out && |
| 135 | test_must_be_empty out && |
| 136 | cd ../../wt_ext && |
| 137 | git worktree prune -v >out && |
| 138 | test_must_be_empty out |
| 139 | ) |
| 140 | ' |
| 141 | |
| 142 | test_done |