Merge branch 'jn/v0-with-extensions-fix' into master
[git] / t / t2403-worktree-move.sh
1 #!/bin/sh
2
3 test_description='test git worktree move, remove, lock and unlock'
4
5 . ./test-lib.sh
6
7 test_expect_success 'setup' '
8         test_commit init &&
9         git worktree add source &&
10         git worktree list --porcelain >out &&
11         grep "^worktree" out >actual &&
12         cat <<-EOF >expected &&
13         worktree $(pwd)
14         worktree $(pwd)/source
15         EOF
16         test_cmp expected actual
17 '
18
19 test_expect_success 'lock main worktree' '
20         test_must_fail git worktree lock .
21 '
22
23 test_expect_success 'lock linked worktree' '
24         git worktree lock --reason hahaha source &&
25         echo hahaha >expected &&
26         test_cmp expected .git/worktrees/source/locked
27 '
28
29 test_expect_success 'lock linked worktree from another worktree' '
30         rm .git/worktrees/source/locked &&
31         git worktree add elsewhere &&
32         git -C elsewhere worktree lock --reason hahaha ../source &&
33         echo hahaha >expected &&
34         test_cmp expected .git/worktrees/source/locked
35 '
36
37 test_expect_success 'lock worktree twice' '
38         test_must_fail git worktree lock source &&
39         echo hahaha >expected &&
40         test_cmp expected .git/worktrees/source/locked
41 '
42
43 test_expect_success 'lock worktree twice (from the locked worktree)' '
44         test_must_fail git -C source worktree lock . &&
45         echo hahaha >expected &&
46         test_cmp expected .git/worktrees/source/locked
47 '
48
49 test_expect_success 'unlock main worktree' '
50         test_must_fail git worktree unlock .
51 '
52
53 test_expect_success 'unlock linked worktree' '
54         git worktree unlock source &&
55         test_path_is_missing .git/worktrees/source/locked
56 '
57
58 test_expect_success 'unlock worktree twice' '
59         test_must_fail git worktree unlock source &&
60         test_path_is_missing .git/worktrees/source/locked
61 '
62
63 test_expect_success 'move non-worktree' '
64         mkdir abc &&
65         test_must_fail git worktree move abc def
66 '
67
68 test_expect_success 'move locked worktree' '
69         git worktree lock source &&
70         test_when_finished "git worktree unlock source" &&
71         test_must_fail git worktree move source destination
72 '
73
74 test_expect_success 'move worktree' '
75         git worktree move source destination &&
76         test_path_is_missing source &&
77         git worktree list --porcelain >out &&
78         grep "^worktree.*/destination$" out &&
79         ! grep "^worktree.*/source$" out &&
80         git -C destination log --format=%s >actual2 &&
81         echo init >expected2 &&
82         test_cmp expected2 actual2
83 '
84
85 test_expect_success 'move main worktree' '
86         test_must_fail git worktree move . def
87 '
88
89 test_expect_success 'move worktree to another dir' '
90         mkdir some-dir &&
91         git worktree move destination some-dir &&
92         test_when_finished "git worktree move some-dir/destination destination" &&
93         test_path_is_missing destination &&
94         git worktree list --porcelain >out &&
95         grep "^worktree.*/some-dir/destination$" out &&
96         git -C some-dir/destination log --format=%s >actual2 &&
97         echo init >expected2 &&
98         test_cmp expected2 actual2
99 '
100
101 test_expect_success 'move locked worktree (force)' '
102         test_when_finished "
103                 git worktree unlock flump || :
104                 git worktree remove flump || :
105                 git worktree unlock ploof || :
106                 git worktree remove ploof || :
107                 " &&
108         git worktree add --detach flump &&
109         git worktree lock flump &&
110         test_must_fail git worktree move flump ploof" &&
111         test_must_fail git worktree move --force flump ploof" &&
112         git worktree move --force --force flump ploof
113 '
114
115 test_expect_success 'refuse to move worktree atop existing path' '
116         >bobble &&
117         git worktree add --detach beeble &&
118         test_must_fail git worktree move beeble bobble
119 '
120
121 test_expect_success 'move atop existing but missing worktree' '
122         git worktree add --detach gnoo &&
123         git worktree add --detach pneu &&
124         rm -fr pneu &&
125         test_must_fail git worktree move gnoo pneu &&
126         git worktree move --force gnoo pneu &&
127
128         git worktree add --detach nu &&
129         git worktree lock nu &&
130         rm -fr nu &&
131         test_must_fail git worktree move pneu nu &&
132         test_must_fail git worktree --force move pneu nu &&
133         git worktree move --force --force pneu nu
134 '
135
136 test_expect_success 'move a repo with uninitialized submodule' '
137         git init withsub &&
138         (
139                 cd withsub &&
140                 test_commit initial &&
141                 git submodule add "$PWD"/.git sub &&
142                 git commit -m withsub &&
143                 git worktree add second HEAD &&
144                 git worktree move second third
145         )
146 '
147
148 test_expect_success 'not move a repo with initialized submodule' '
149         (
150                 cd withsub &&
151                 git -C third submodule update &&
152                 test_must_fail git worktree move third forth
153         )
154 '
155
156 test_expect_success 'remove main worktree' '
157         test_must_fail git worktree remove .
158 '
159
160 test_expect_success 'remove locked worktree' '
161         git worktree lock destination &&
162         test_when_finished "git worktree unlock destination" &&
163         test_must_fail git worktree remove destination
164 '
165
166 test_expect_success 'remove worktree with dirty tracked file' '
167         echo dirty >>destination/init.t &&
168         test_when_finished "git -C destination checkout init.t" &&
169         test_must_fail git worktree remove destination
170 '
171
172 test_expect_success 'remove worktree with untracked file' '
173         : >destination/untracked &&
174         test_must_fail git worktree remove destination
175 '
176
177 test_expect_success 'force remove worktree with untracked file' '
178         git worktree remove --force destination &&
179         test_path_is_missing destination
180 '
181
182 test_expect_success 'remove missing worktree' '
183         git worktree add to-be-gone &&
184         test -d .git/worktrees/to-be-gone &&
185         mv to-be-gone gone &&
186         git worktree remove to-be-gone &&
187         test_path_is_missing .git/worktrees/to-be-gone
188 '
189
190 test_expect_success 'NOT remove missing-but-locked worktree' '
191         git worktree add gone-but-locked &&
192         git worktree lock gone-but-locked &&
193         test -d .git/worktrees/gone-but-locked &&
194         mv gone-but-locked really-gone-now &&
195         test_must_fail git worktree remove gone-but-locked &&
196         test_path_is_dir .git/worktrees/gone-but-locked
197 '
198
199 test_expect_success 'proper error when worktree not found' '
200         for i in noodle noodle/bork
201         do
202                 test_must_fail git worktree lock $i 2>err &&
203                 test_i18ngrep "not a working tree" err || return 1
204         done
205 '
206
207 test_expect_success 'remove locked worktree (force)' '
208         git worktree add --detach gumby &&
209         test_when_finished "git worktree remove gumby || :" &&
210         git worktree lock gumby &&
211         test_when_finished "git worktree unlock gumby || :" &&
212         test_must_fail git worktree remove gumby &&
213         test_must_fail git worktree remove --force gumby &&
214         git worktree remove --force --force gumby
215 '
216
217 test_expect_success 'remove cleans up .git/worktrees when empty' '
218         git init moog &&
219         (
220                 cd moog &&
221                 test_commit bim &&
222                 git worktree add --detach goom &&
223                 test_path_exists .git/worktrees &&
224                 git worktree remove goom &&
225                 test_path_is_missing .git/worktrees
226         )
227 '
228
229 test_expect_success 'remove a repo with uninitialized submodule' '
230         (
231                 cd withsub &&
232                 git worktree add to-remove HEAD &&
233                 git worktree remove to-remove
234         )
235 '
236
237 test_expect_success 'not remove a repo with initialized submodule' '
238         (
239                 cd withsub &&
240                 git worktree add to-remove HEAD &&
241                 git -C to-remove submodule update &&
242                 test_must_fail git worktree remove to-remove
243         )
244 '
245
246 test_done