| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='test git worktree repair' |
| 4 | |
| 5 | . ./test-lib.sh |
| 6 | |
| 7 | test_expect_success setup ' |
| 8 | test_commit init |
| 9 | ' |
| 10 | |
| 11 | test_expect_success 'skip missing worktree' ' |
| 12 | test_when_finished "git worktree prune" && |
| 13 | git worktree add --detach missing && |
| 14 | rm -rf missing && |
| 15 | git worktree repair >out 2>err && |
| 16 | test_must_be_empty out && |
| 17 | test_must_be_empty err |
| 18 | ' |
| 19 | |
| 20 | test_expect_success 'worktree path not directory' ' |
| 21 | test_when_finished "git worktree prune" && |
| 22 | git worktree add --detach notdir && |
| 23 | rm -rf notdir && |
| 24 | >notdir && |
| 25 | test_must_fail git worktree repair >out 2>err && |
| 26 | test_must_be_empty out && |
| 27 | test_grep "not a directory" err |
| 28 | ' |
| 29 | |
| 30 | test_expect_success "don't clobber .git repo" ' |
| 31 | test_when_finished "rm -rf repo && git worktree prune" && |
| 32 | git worktree add --detach repo && |
| 33 | rm -rf repo && |
| 34 | test_create_repo repo && |
| 35 | test_must_fail git worktree repair >out 2>err && |
| 36 | test_must_be_empty out && |
| 37 | test_grep ".git is not a file" err |
| 38 | ' |
| 39 | |
| 40 | test_corrupt_gitfile () { |
| 41 | butcher=$1 && |
| 42 | problem=$2 && |
| 43 | repairdir=${3:-.} && |
| 44 | test_when_finished 'rm -rf corrupt && git worktree prune' && |
| 45 | git worktree add --detach corrupt && |
| 46 | git -C corrupt rev-parse --absolute-git-dir >expect && |
| 47 | eval "$butcher" && |
| 48 | git -C "$repairdir" worktree repair 2>err && |
| 49 | test_grep "$problem" err && |
| 50 | git -C corrupt rev-parse --absolute-git-dir >actual && |
| 51 | test_cmp expect actual |
| 52 | } |
| 53 | |
| 54 | test_expect_success 'repair missing .git file' ' |
| 55 | test_corrupt_gitfile "rm -f corrupt/.git" ".git file broken" |
| 56 | ' |
| 57 | |
| 58 | test_expect_success 'repair bogus .git file' ' |
| 59 | test_corrupt_gitfile "echo \"gitdir: /nowhere\" >corrupt/.git" \ |
| 60 | ".git file broken" |
| 61 | ' |
| 62 | |
| 63 | test_expect_success 'repair incorrect .git file' ' |
| 64 | test_when_finished "rm -rf other && git worktree prune" && |
| 65 | test_create_repo other && |
| 66 | other=$(git -C other rev-parse --absolute-git-dir) && |
| 67 | test_corrupt_gitfile "echo \"gitdir: $other\" >corrupt/.git" \ |
| 68 | ".git file incorrect" |
| 69 | ' |
| 70 | |
| 71 | test_expect_success 'repair .git file from main/.git' ' |
| 72 | test_corrupt_gitfile "rm -f corrupt/.git" ".git file broken" .git |
| 73 | ' |
| 74 | |
| 75 | test_expect_success 'repair .git file from linked worktree' ' |
| 76 | test_when_finished "rm -rf other && git worktree prune" && |
| 77 | git worktree add --detach other && |
| 78 | test_corrupt_gitfile "rm -f corrupt/.git" ".git file broken" other |
| 79 | ' |
| 80 | |
| 81 | test_expect_success 'repair .git file from bare.git' ' |
| 82 | test_when_finished "rm -rf bare.git corrupt && git worktree prune" && |
| 83 | git clone --bare . bare.git && |
| 84 | git -C bare.git worktree add --detach ../corrupt && |
| 85 | git -C corrupt rev-parse --absolute-git-dir >expect && |
| 86 | rm -f corrupt/.git && |
| 87 | git -C bare.git worktree repair && |
| 88 | git -C corrupt rev-parse --absolute-git-dir >actual && |
| 89 | test_cmp expect actual |
| 90 | ' |
| 91 | |
| 92 | test_expect_success 'invalid worktree path' ' |
| 93 | test_must_fail git worktree repair /notvalid >out 2>err && |
| 94 | test_must_be_empty out && |
| 95 | test_grep "not a valid path" err |
| 96 | ' |
| 97 | |
| 98 | test_expect_success 'repo not found; .git not file' ' |
| 99 | test_when_finished "rm -rf not-a-worktree" && |
| 100 | test_create_repo not-a-worktree && |
| 101 | test_must_fail git worktree repair not-a-worktree >out 2>err && |
| 102 | test_must_be_empty out && |
| 103 | test_grep ".git is not a file" err |
| 104 | ' |
| 105 | |
| 106 | test_expect_success 'repo not found; .git not referencing repo' ' |
| 107 | test_when_finished "rm -rf side not-a-repo && git worktree prune" && |
| 108 | git worktree add --detach side && |
| 109 | sed s,\.git/worktrees/side$,not-a-repo, side/.git >side/.newgit && |
| 110 | mv side/.newgit side/.git && |
| 111 | mkdir not-a-repo && |
| 112 | test_must_fail git worktree repair side 2>err && |
| 113 | test_grep ".git file does not reference a repository" err |
| 114 | ' |
| 115 | |
| 116 | test_expect_success 'repo not found; .git file broken' ' |
| 117 | test_when_finished "rm -rf orig moved && git worktree prune" && |
| 118 | git worktree add --detach orig && |
| 119 | echo /invalid >orig/.git && |
| 120 | mv orig moved && |
| 121 | test_must_fail git worktree repair moved >out 2>err && |
| 122 | test_must_be_empty out && |
| 123 | test_grep ".git file broken" err |
| 124 | ' |
| 125 | |
| 126 | test_expect_success 'repair broken gitdir' ' |
| 127 | test_when_finished "rm -rf orig moved && git worktree prune" && |
| 128 | git worktree add --detach orig && |
| 129 | sed s,orig/\.git$,moved/.git, .git/worktrees/orig/gitdir >expect && |
| 130 | rm .git/worktrees/orig/gitdir && |
| 131 | mv orig moved && |
| 132 | git worktree repair moved 2>err && |
| 133 | test_cmp expect .git/worktrees/orig/gitdir && |
| 134 | test_grep "gitdir unreadable" err |
| 135 | ' |
| 136 | |
| 137 | test_expect_success 'repair incorrect gitdir' ' |
| 138 | test_when_finished "rm -rf orig moved && git worktree prune" && |
| 139 | git worktree add --detach orig && |
| 140 | sed s,orig/\.git$,moved/.git, .git/worktrees/orig/gitdir >expect && |
| 141 | mv orig moved && |
| 142 | git worktree repair moved 2>err && |
| 143 | test_cmp expect .git/worktrees/orig/gitdir && |
| 144 | test_grep "gitdir incorrect" err |
| 145 | ' |
| 146 | |
| 147 | test_expect_success 'repair gitdir (implicit) from linked worktree' ' |
| 148 | test_when_finished "rm -rf orig moved && git worktree prune" && |
| 149 | git worktree add --detach orig && |
| 150 | sed s,orig/\.git$,moved/.git, .git/worktrees/orig/gitdir >expect && |
| 151 | mv orig moved && |
| 152 | git -C moved worktree repair 2>err && |
| 153 | test_cmp expect .git/worktrees/orig/gitdir && |
| 154 | test_grep "gitdir incorrect" err |
| 155 | ' |
| 156 | |
| 157 | test_expect_success 'unable to repair gitdir (implicit) from main worktree' ' |
| 158 | test_when_finished "rm -rf orig moved && git worktree prune" && |
| 159 | git worktree add --detach orig && |
| 160 | cat .git/worktrees/orig/gitdir >expect && |
| 161 | mv orig moved && |
| 162 | git worktree repair 2>err && |
| 163 | test_cmp expect .git/worktrees/orig/gitdir && |
| 164 | test_must_be_empty err |
| 165 | ' |
| 166 | |
| 167 | test_expect_success 'repair multiple gitdir files' ' |
| 168 | test_when_finished "rm -rf orig1 orig2 moved1 moved2 && |
| 169 | git worktree prune" && |
| 170 | git worktree add --detach orig1 && |
| 171 | git worktree add --detach orig2 && |
| 172 | sed s,orig1/\.git$,moved1/.git, .git/worktrees/orig1/gitdir >expect1 && |
| 173 | sed s,orig2/\.git$,moved2/.git, .git/worktrees/orig2/gitdir >expect2 && |
| 174 | mv orig1 moved1 && |
| 175 | mv orig2 moved2 && |
| 176 | git worktree repair moved1 moved2 2>err && |
| 177 | test_cmp expect1 .git/worktrees/orig1/gitdir && |
| 178 | test_cmp expect2 .git/worktrees/orig2/gitdir && |
| 179 | test_grep "gitdir incorrect:.*orig1/gitdir$" err && |
| 180 | test_grep "gitdir incorrect:.*orig2/gitdir$" err |
| 181 | ' |
| 182 | |
| 183 | test_expect_success 'repair moved main and linked worktrees' ' |
| 184 | test_when_finished "rm -rf main side mainmoved sidemoved" && |
| 185 | test_create_repo main && |
| 186 | test_commit -C main init && |
| 187 | git -C main worktree add --detach ../side && |
| 188 | sed "s,side/\.git$,sidemoved/.git," \ |
| 189 | main/.git/worktrees/side/gitdir >expect-gitdir && |
| 190 | sed "s,main/.git/worktrees/side$,mainmoved/.git/worktrees/side," \ |
| 191 | side/.git >expect-gitfile && |
| 192 | mv main mainmoved && |
| 193 | mv side sidemoved && |
| 194 | git -C mainmoved worktree repair ../sidemoved && |
| 195 | test_cmp expect-gitdir mainmoved/.git/worktrees/side/gitdir && |
| 196 | test_cmp expect-gitfile sidemoved/.git |
| 197 | ' |
| 198 | |
| 199 | test_expect_success 'repair copied main and linked worktrees' ' |
| 200 | test_when_finished "rm -rf orig dup" && |
| 201 | mkdir -p orig && |
| 202 | git -C orig init main && |
| 203 | test_commit -C orig/main nothing && |
| 204 | git -C orig/main worktree add ../linked && |
| 205 | cp orig/main/.git/worktrees/linked/gitdir orig/main.expect && |
| 206 | cp orig/linked/.git orig/linked.expect && |
| 207 | cp -R orig dup && |
| 208 | sed "s,orig/linked/\.git$,dup/linked/.git," orig/main.expect >dup/main.expect && |
| 209 | sed "s,orig/main/\.git/worktrees/linked$,dup/main/.git/worktrees/linked," \ |
| 210 | orig/linked.expect >dup/linked.expect && |
| 211 | git -C dup/main worktree repair ../linked && |
| 212 | test_cmp orig/main.expect orig/main/.git/worktrees/linked/gitdir && |
| 213 | test_cmp orig/linked.expect orig/linked/.git && |
| 214 | test_cmp dup/main.expect dup/main/.git/worktrees/linked/gitdir && |
| 215 | test_cmp dup/linked.expect dup/linked/.git |
| 216 | ' |
| 217 | |
| 218 | test_expect_success 'repair worktree with relative path with missing gitfile' ' |
| 219 | test_when_finished "rm -rf main wt" && |
| 220 | test_create_repo main && |
| 221 | git -C main config worktree.useRelativePaths true && |
| 222 | test_commit -C main init && |
| 223 | git -C main worktree add --detach ../wt && |
| 224 | rm wt/.git && |
| 225 | test_path_is_missing wt/.git && |
| 226 | git -C main worktree repair && |
| 227 | echo "gitdir: ../main/.git/worktrees/wt" >expect && |
| 228 | test_cmp expect wt/.git |
| 229 | ' |
| 230 | |
| 231 | test_expect_success 'repair absolute worktree to use relative paths' ' |
| 232 | test_when_finished "rm -rf main side sidemoved" && |
| 233 | test_create_repo main && |
| 234 | test_commit -C main init && |
| 235 | git -C main worktree add --detach ../side && |
| 236 | echo "../../../../sidemoved/.git" >expect-gitdir && |
| 237 | echo "gitdir: ../main/.git/worktrees/side" >expect-gitfile && |
| 238 | mv side sidemoved && |
| 239 | git -C main worktree repair --relative-paths ../sidemoved && |
| 240 | test_cmp expect-gitdir main/.git/worktrees/side/gitdir && |
| 241 | test_cmp expect-gitfile sidemoved/.git |
| 242 | ' |
| 243 | |
| 244 | test_expect_success 'repair relative worktree to use absolute paths' ' |
| 245 | test_when_finished "rm -rf main side sidemoved" && |
| 246 | test_create_repo main && |
| 247 | test_commit -C main init && |
| 248 | git -C main worktree add --relative-paths --detach ../side && |
| 249 | echo "$(pwd)/sidemoved/.git" >expect-gitdir && |
| 250 | echo "gitdir: $(pwd)/main/.git/worktrees/side" >expect-gitfile && |
| 251 | mv side sidemoved && |
| 252 | git -C main worktree repair ../sidemoved && |
| 253 | test_cmp expect-gitdir main/.git/worktrees/side/gitdir && |
| 254 | test_cmp expect-gitfile sidemoved/.git |
| 255 | ' |
| 256 | |
| 257 | test_done |