]> git.ipfire.org Git - thirdparty/git.git/blob - t/t2402-worktree-list.sh
worktree: teach `list` verbose mode
[thirdparty/git.git] / t / t2402-worktree-list.sh
1 #!/bin/sh
2
3 test_description='test git worktree list'
4
5 . ./test-lib.sh
6
7 test_expect_success 'setup' '
8 test_commit init
9 '
10
11 test_expect_success 'rev-parse --git-common-dir on main worktree' '
12 git rev-parse --git-common-dir >actual &&
13 echo .git >expected &&
14 test_cmp expected actual &&
15 mkdir sub &&
16 git -C sub rev-parse --git-common-dir >actual2 &&
17 echo ../.git >expected2 &&
18 test_cmp expected2 actual2
19 '
20
21 test_expect_success 'rev-parse --git-path objects linked worktree' '
22 echo "$(git rev-parse --show-toplevel)/.git/objects" >expect &&
23 test_when_finished "rm -rf linked-tree actual expect && git worktree prune" &&
24 git worktree add --detach linked-tree master &&
25 git -C linked-tree rev-parse --git-path objects >actual &&
26 test_cmp expect actual
27 '
28
29 test_expect_success '"list" all worktrees from main' '
30 echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect &&
31 test_when_finished "rm -rf here out actual expect && git worktree prune" &&
32 git worktree add --detach here master &&
33 echo "$(git -C here rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >>expect &&
34 git worktree list >out &&
35 sed "s/ */ /g" <out >actual &&
36 test_cmp expect actual
37 '
38
39 test_expect_success '"list" all worktrees from linked' '
40 echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect &&
41 test_when_finished "rm -rf here out actual expect && git worktree prune" &&
42 git worktree add --detach here master &&
43 echo "$(git -C here rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >>expect &&
44 git -C here worktree list >out &&
45 sed "s/ */ /g" <out >actual &&
46 test_cmp expect actual
47 '
48
49 test_expect_success '"list" all worktrees --porcelain' '
50 echo "worktree $(git rev-parse --show-toplevel)" >expect &&
51 echo "HEAD $(git rev-parse HEAD)" >>expect &&
52 echo "branch $(git symbolic-ref HEAD)" >>expect &&
53 echo >>expect &&
54 test_when_finished "rm -rf here actual expect && git worktree prune" &&
55 git worktree add --detach here master &&
56 echo "worktree $(git -C here rev-parse --show-toplevel)" >>expect &&
57 echo "HEAD $(git rev-parse HEAD)" >>expect &&
58 echo "detached" >>expect &&
59 echo >>expect &&
60 git worktree list --porcelain >actual &&
61 test_cmp expect actual
62 '
63
64 test_expect_success '"list" all worktrees with locked annotation' '
65 test_when_finished "rm -rf locked unlocked out && git worktree prune" &&
66 git worktree add --detach locked master &&
67 git worktree add --detach unlocked master &&
68 git worktree lock locked &&
69 test_when_finished "git worktree unlock locked" &&
70 git worktree list >out &&
71 grep "/locked *[0-9a-f].* locked$" out &&
72 ! grep "/unlocked *[0-9a-f].* locked$" out
73 '
74
75 test_expect_success '"list" all worktrees --porcelain with locked' '
76 test_when_finished "rm -rf locked1 locked2 unlocked out actual expect && git worktree prune" &&
77 echo "locked" >expect &&
78 echo "locked with reason" >>expect &&
79 git worktree add --detach locked1 &&
80 git worktree add --detach locked2 &&
81 # unlocked worktree should not be annotated with "locked"
82 git worktree add --detach unlocked &&
83 git worktree lock locked1 &&
84 test_when_finished "git worktree unlock locked1" &&
85 git worktree lock locked2 --reason "with reason" &&
86 test_when_finished "git worktree unlock locked2" &&
87 git worktree list --porcelain >out &&
88 grep "^locked" out >actual &&
89 test_cmp expect actual
90 '
91
92 test_expect_success '"list" all worktrees --porcelain with locked reason newline escaped' '
93 test_when_finished "rm -rf locked_lf locked_crlf out actual expect && git worktree prune" &&
94 printf "locked \"locked\\\\r\\\\nreason\"\n" >expect &&
95 printf "locked \"locked\\\\nreason\"\n" >>expect &&
96 git worktree add --detach locked_lf &&
97 git worktree add --detach locked_crlf &&
98 git worktree lock locked_lf --reason "$(printf "locked\nreason")" &&
99 test_when_finished "git worktree unlock locked_lf" &&
100 git worktree lock locked_crlf --reason "$(printf "locked\r\nreason")" &&
101 test_when_finished "git worktree unlock locked_crlf" &&
102 git worktree list --porcelain >out &&
103 grep "^locked" out >actual &&
104 test_cmp expect actual
105 '
106
107 test_expect_success '"list" all worktrees with prunable annotation' '
108 test_when_finished "rm -rf prunable unprunable out && git worktree prune" &&
109 git worktree add --detach prunable &&
110 git worktree add --detach unprunable &&
111 rm -rf prunable &&
112 git worktree list >out &&
113 grep "/prunable *[0-9a-f].* prunable$" out &&
114 ! grep "/unprunable *[0-9a-f].* prunable$"
115 '
116
117 test_expect_success '"list" all worktrees --porcelain with prunable' '
118 test_when_finished "rm -rf prunable out && git worktree prune" &&
119 git worktree add --detach prunable &&
120 rm -rf prunable &&
121 git worktree list --porcelain >out &&
122 sed -n "/^worktree .*\/prunable$/,/^$/p" <out >only_prunable &&
123 test_i18ngrep "^prunable gitdir file points to non-existent location$" only_prunable
124 '
125
126 test_expect_success '"list" all worktrees with prunable consistent with "prune"' '
127 test_when_finished "rm -rf prunable unprunable out && git worktree prune" &&
128 git worktree add --detach prunable &&
129 git worktree add --detach unprunable &&
130 rm -rf prunable &&
131 git worktree list >out &&
132 grep "/prunable *[0-9a-f].* prunable$" out &&
133 ! grep "/unprunable *[0-9a-f].* unprunable$" out &&
134 git worktree prune --verbose >out &&
135 test_i18ngrep "^Removing worktrees/prunable" out &&
136 test_i18ngrep ! "^Removing worktrees/unprunable" out
137 '
138
139 test_expect_success '"list" --verbose and --porcelain mutually exclusive' '
140 test_must_fail git worktree list --verbose --porcelain
141 '
142
143 test_expect_success '"list" all worktrees --verbose with locked' '
144 test_when_finished "rm -rf locked1 locked2 out actual expect && git worktree prune" &&
145 git worktree add locked1 --detach &&
146 git worktree add locked2 --detach &&
147 git worktree lock locked1 &&
148 test_when_finished "git worktree unlock locked1" &&
149 git worktree lock locked2 --reason "with reason" &&
150 test_when_finished "git worktree unlock locked2" &&
151 echo "$(git -C locked2 rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >expect &&
152 printf "\tlocked: with reason\n" >>expect &&
153 git worktree list --verbose >out &&
154 grep "/locked1 *[0-9a-f].* locked$" out &&
155 sed -n "s/ */ /g;/\/locked2 *[0-9a-f].*$/,/locked: .*$/p" <out >actual &&
156 test_cmp actual expect
157 '
158
159 test_expect_success '"list" all worktrees --verbose with prunable' '
160 test_when_finished "rm -rf prunable out actual expect && git worktree prune" &&
161 git worktree add prunable --detach &&
162 echo "$(git -C prunable rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >expect &&
163 printf "\tprunable: gitdir file points to non-existent location\n" >>expect &&
164 rm -rf prunable &&
165 git worktree list --verbose >out &&
166 sed -n "s/ */ /g;/\/prunable *[0-9a-f].*$/,/prunable: .*$/p" <out >actual &&
167 test_i18ncmp actual expect
168 '
169
170 test_expect_success 'bare repo setup' '
171 git init --bare bare1 &&
172 echo "data" >file1 &&
173 git add file1 &&
174 git commit -m"File1: add data" &&
175 git push bare1 master &&
176 git reset --hard HEAD^
177 '
178
179 test_expect_success '"list" all worktrees from bare main' '
180 test_when_finished "rm -rf there out actual expect && git -C bare1 worktree prune" &&
181 git -C bare1 worktree add --detach ../there master &&
182 echo "$(pwd)/bare1 (bare)" >expect &&
183 echo "$(git -C there rev-parse --show-toplevel) $(git -C there rev-parse --short HEAD) (detached HEAD)" >>expect &&
184 git -C bare1 worktree list >out &&
185 sed "s/ */ /g" <out >actual &&
186 test_cmp expect actual
187 '
188
189 test_expect_success '"list" all worktrees --porcelain from bare main' '
190 test_when_finished "rm -rf there actual expect && git -C bare1 worktree prune" &&
191 git -C bare1 worktree add --detach ../there master &&
192 echo "worktree $(pwd)/bare1" >expect &&
193 echo "bare" >>expect &&
194 echo >>expect &&
195 echo "worktree $(git -C there rev-parse --show-toplevel)" >>expect &&
196 echo "HEAD $(git -C there rev-parse HEAD)" >>expect &&
197 echo "detached" >>expect &&
198 echo >>expect &&
199 git -C bare1 worktree list --porcelain >actual &&
200 test_cmp expect actual
201 '
202
203 test_expect_success '"list" all worktrees from linked with a bare main' '
204 test_when_finished "rm -rf there out actual expect && git -C bare1 worktree prune" &&
205 git -C bare1 worktree add --detach ../there master &&
206 echo "$(pwd)/bare1 (bare)" >expect &&
207 echo "$(git -C there rev-parse --show-toplevel) $(git -C there rev-parse --short HEAD) (detached HEAD)" >>expect &&
208 git -C there worktree list >out &&
209 sed "s/ */ /g" <out >actual &&
210 test_cmp expect actual
211 '
212
213 test_expect_success 'bare repo cleanup' '
214 rm -rf bare1
215 '
216
217 test_expect_success 'broken main worktree still at the top' '
218 git init broken-main &&
219 (
220 cd broken-main &&
221 test_commit new &&
222 git worktree add linked &&
223 cat >expected <<-EOF &&
224 worktree $(pwd)
225 HEAD $ZERO_OID
226
227 EOF
228 cd linked &&
229 echo "worktree $(pwd)" >expected &&
230 echo "ref: .broken" >../.git/HEAD &&
231 git worktree list --porcelain >out &&
232 head -n 3 out >actual &&
233 test_cmp ../expected actual &&
234 git worktree list >out &&
235 head -n 1 out >actual.2 &&
236 grep -F "(error)" actual.2
237 )
238 '
239
240 test_expect_success 'linked worktrees are sorted' '
241 mkdir sorted &&
242 git init sorted/main &&
243 (
244 cd sorted/main &&
245 test_tick &&
246 test_commit new &&
247 git worktree add ../first &&
248 git worktree add ../second &&
249 git worktree list --porcelain >out &&
250 grep ^worktree out >actual
251 ) &&
252 cat >expected <<-EOF &&
253 worktree $(pwd)/sorted/main
254 worktree $(pwd)/sorted/first
255 worktree $(pwd)/sorted/second
256 EOF
257 test_cmp expected sorted/main/actual
258 '
259
260 test_expect_success 'worktree path when called in .git directory' '
261 git worktree list >list1 &&
262 git -C .git worktree list >list2 &&
263 test_cmp list1 list2
264 '
265
266 test_done