t4129: don't fail if setgid is set in the test directory
[git] / t / t6302-for-each-ref-filter.sh
1 #!/bin/sh
2
3 test_description='test for-each-refs usage of ref-filter APIs'
4
5 . ./test-lib.sh
6 . "$TEST_DIRECTORY"/lib-gpg.sh
7
8 test_expect_success 'setup some history and refs' '
9         test_commit one &&
10         git branch -M main &&
11         test_commit two &&
12         test_commit three &&
13         git checkout -b side &&
14         test_commit four &&
15         git tag -m "An annotated tag" annotated-tag &&
16         git tag -m "Annonated doubly" doubly-annotated-tag annotated-tag &&
17
18         # Note that these "signed" tags might not actually be signed.
19         # Tests which care about the distinction should be marked
20         # with the GPG prereq.
21         if test_have_prereq GPG
22         then
23                 sign=-s
24         else
25                 sign=
26         fi &&
27         git tag $sign -m "A signed tag" signed-tag &&
28         git tag $sign -m "Signed doubly" doubly-signed-tag signed-tag &&
29
30         git checkout main &&
31         git update-ref refs/odd/spot main
32 '
33
34 test_expect_success 'filtering with --points-at' '
35         cat >expect <<-\EOF &&
36         refs/heads/main
37         refs/odd/spot
38         refs/tags/three
39         EOF
40         git for-each-ref --format="%(refname)" --points-at=main >actual &&
41         test_cmp expect actual
42 '
43
44 test_expect_success 'check signed tags with --points-at' '
45         sed -e "s/Z$//" >expect <<-\EOF &&
46         refs/heads/side Z
47         refs/tags/annotated-tag four
48         refs/tags/four Z
49         refs/tags/signed-tag four
50         EOF
51         git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
52         test_cmp expect actual
53 '
54
55 test_expect_success 'filtering with --merged' '
56         cat >expect <<-\EOF &&
57         refs/heads/main
58         refs/odd/spot
59         refs/tags/one
60         refs/tags/three
61         refs/tags/two
62         EOF
63         git for-each-ref --format="%(refname)" --merged=main >actual &&
64         test_cmp expect actual
65 '
66
67 test_expect_success 'filtering with --no-merged' '
68         cat >expect <<-\EOF &&
69         refs/heads/side
70         refs/tags/annotated-tag
71         refs/tags/doubly-annotated-tag
72         refs/tags/doubly-signed-tag
73         refs/tags/four
74         refs/tags/signed-tag
75         EOF
76         git for-each-ref --format="%(refname)" --no-merged=main >actual &&
77         test_cmp expect actual
78 '
79
80 test_expect_success 'filtering with --contains' '
81         cat >expect <<-\EOF &&
82         refs/heads/main
83         refs/heads/side
84         refs/odd/spot
85         refs/tags/annotated-tag
86         refs/tags/doubly-annotated-tag
87         refs/tags/doubly-signed-tag
88         refs/tags/four
89         refs/tags/signed-tag
90         refs/tags/three
91         refs/tags/two
92         EOF
93         git for-each-ref --format="%(refname)" --contains=two >actual &&
94         test_cmp expect actual
95 '
96
97 test_expect_success 'filtering with --no-contains' '
98         cat >expect <<-\EOF &&
99         refs/tags/one
100         EOF
101         git for-each-ref --format="%(refname)" --no-contains=two >actual &&
102         test_cmp expect actual
103 '
104
105 test_expect_success 'filtering with --contains and --no-contains' '
106         cat >expect <<-\EOF &&
107         refs/tags/two
108         EOF
109         git for-each-ref --format="%(refname)" --contains=two --no-contains=three >actual &&
110         test_cmp expect actual
111 '
112
113 test_expect_success '%(color) must fail' '
114         test_must_fail git for-each-ref --format="%(color)%(refname)"
115 '
116
117 test_expect_success 'left alignment is default' '
118         cat >expect <<-\EOF &&
119         refname is refs/heads/main    |refs/heads/main
120         refname is refs/heads/side    |refs/heads/side
121         refname is refs/odd/spot      |refs/odd/spot
122         refname is refs/tags/annotated-tag|refs/tags/annotated-tag
123         refname is refs/tags/doubly-annotated-tag|refs/tags/doubly-annotated-tag
124         refname is refs/tags/doubly-signed-tag|refs/tags/doubly-signed-tag
125         refname is refs/tags/four     |refs/tags/four
126         refname is refs/tags/one      |refs/tags/one
127         refname is refs/tags/signed-tag|refs/tags/signed-tag
128         refname is refs/tags/three    |refs/tags/three
129         refname is refs/tags/two      |refs/tags/two
130         EOF
131         git for-each-ref --format="%(align:30)refname is %(refname)%(end)|%(refname)" >actual &&
132         test_cmp expect actual
133 '
134
135 test_expect_success 'middle alignment' '
136         cat >expect <<-\EOF &&
137         |  refname is refs/heads/main  |refs/heads/main
138         |  refname is refs/heads/side  |refs/heads/side
139         |   refname is refs/odd/spot   |refs/odd/spot
140         |refname is refs/tags/annotated-tag|refs/tags/annotated-tag
141         |refname is refs/tags/doubly-annotated-tag|refs/tags/doubly-annotated-tag
142         |refname is refs/tags/doubly-signed-tag|refs/tags/doubly-signed-tag
143         |  refname is refs/tags/four   |refs/tags/four
144         |   refname is refs/tags/one   |refs/tags/one
145         |refname is refs/tags/signed-tag|refs/tags/signed-tag
146         |  refname is refs/tags/three  |refs/tags/three
147         |   refname is refs/tags/two   |refs/tags/two
148         EOF
149         git for-each-ref --format="|%(align:middle,30)refname is %(refname)%(end)|%(refname)" >actual &&
150         test_cmp expect actual
151 '
152
153 test_expect_success 'right alignment' '
154         cat >expect <<-\EOF &&
155         |    refname is refs/heads/main|refs/heads/main
156         |    refname is refs/heads/side|refs/heads/side
157         |      refname is refs/odd/spot|refs/odd/spot
158         |refname is refs/tags/annotated-tag|refs/tags/annotated-tag
159         |refname is refs/tags/doubly-annotated-tag|refs/tags/doubly-annotated-tag
160         |refname is refs/tags/doubly-signed-tag|refs/tags/doubly-signed-tag
161         |     refname is refs/tags/four|refs/tags/four
162         |      refname is refs/tags/one|refs/tags/one
163         |refname is refs/tags/signed-tag|refs/tags/signed-tag
164         |    refname is refs/tags/three|refs/tags/three
165         |      refname is refs/tags/two|refs/tags/two
166         EOF
167         git for-each-ref --format="|%(align:30,right)refname is %(refname)%(end)|%(refname)" >actual &&
168         test_cmp expect actual
169 '
170
171 cat >expect <<-\EOF
172 |        refname is refs/heads/main        |refs/heads/main
173 |        refname is refs/heads/side        |refs/heads/side
174 |         refname is refs/odd/spot         |refs/odd/spot
175 |    refname is refs/tags/annotated-tag    |refs/tags/annotated-tag
176 |refname is refs/tags/doubly-annotated-tag |refs/tags/doubly-annotated-tag
177 |  refname is refs/tags/doubly-signed-tag  |refs/tags/doubly-signed-tag
178 |        refname is refs/tags/four         |refs/tags/four
179 |         refname is refs/tags/one         |refs/tags/one
180 |     refname is refs/tags/signed-tag      |refs/tags/signed-tag
181 |        refname is refs/tags/three        |refs/tags/three
182 |         refname is refs/tags/two         |refs/tags/two
183 EOF
184
185 test_align_permutations() {
186         while read -r option
187         do
188                 test_expect_success "align:$option" '
189                         git for-each-ref --format="|%(align:$option)refname is %(refname)%(end)|%(refname)" >actual &&
190                         test_cmp expect actual
191                 '
192         done
193 }
194
195 test_align_permutations <<-\EOF
196         middle,42
197         42,middle
198         position=middle,42
199         42,position=middle
200         middle,width=42
201         width=42,middle
202         position=middle,width=42
203         width=42,position=middle
204 EOF
205
206 # Last one wins (silently) when multiple arguments of the same type are given
207
208 test_align_permutations <<-\EOF
209         32,width=42,middle
210         width=30,42,middle
211         width=42,position=right,middle
212         42,right,position=middle
213 EOF
214
215 # Individual atoms inside %(align:...) and %(end) must not be quoted.
216
217 test_expect_success 'alignment with format quote' "
218         cat >expect <<-\EOF &&
219         |'       '\''main| A U Thor'\''       '|
220         |'       '\''side| A U Thor'\''       '|
221         |'     '\''odd/spot| A U Thor'\''     '|
222         |'      '\''annotated-tag| '\''       '|
223         |'   '\''doubly-annotated-tag| '\''   '|
224         |'    '\''doubly-signed-tag| '\''     '|
225         |'       '\''four| A U Thor'\''       '|
226         |'       '\''one| A U Thor'\''        '|
227         |'        '\''signed-tag| '\''        '|
228         |'      '\''three| A U Thor'\''       '|
229         |'       '\''two| A U Thor'\''        '|
230         EOF
231         git for-each-ref --shell --format=\"|%(align:30,middle)'%(refname:short)| %(authorname)'%(end)|\" >actual &&
232         test_cmp expect actual
233 "
234
235 test_expect_success 'nested alignment with quote formatting' "
236         cat >expect <<-\EOF &&
237         |'           main               '|
238         |'           side               '|
239         |'       odd/spot               '|
240         |'  annotated-tag               '|
241         |'doubly-annotated-tag          '|
242         |'doubly-signed-tag             '|
243         |'           four               '|
244         |'            one               '|
245         |'     signed-tag               '|
246         |'          three               '|
247         |'            two               '|
248         EOF
249         git for-each-ref --shell --format='|%(align:30,left)%(align:15,right)%(refname:short)%(end)%(end)|' >actual &&
250         test_cmp expect actual
251 "
252
253 test_expect_success 'check `%(contents:lines=1)`' '
254         cat >expect <<-\EOF &&
255         main |three
256         side |four
257         odd/spot |three
258         annotated-tag |An annotated tag
259         doubly-annotated-tag |Annonated doubly
260         doubly-signed-tag |Signed doubly
261         four |four
262         one |one
263         signed-tag |A signed tag
264         three |three
265         two |two
266         EOF
267         git for-each-ref --format="%(refname:short) |%(contents:lines=1)" >actual &&
268         test_cmp expect actual
269 '
270
271 test_expect_success 'check `%(contents:lines=0)`' '
272         cat >expect <<-\EOF &&
273         main |
274         side |
275         odd/spot |
276         annotated-tag |
277         doubly-annotated-tag |
278         doubly-signed-tag |
279         four |
280         one |
281         signed-tag |
282         three |
283         two |
284         EOF
285         git for-each-ref --format="%(refname:short) |%(contents:lines=0)" >actual &&
286         test_cmp expect actual
287 '
288
289 test_expect_success 'check `%(contents:lines=99999)`' '
290         cat >expect <<-\EOF &&
291         main |three
292         side |four
293         odd/spot |three
294         annotated-tag |An annotated tag
295         doubly-annotated-tag |Annonated doubly
296         doubly-signed-tag |Signed doubly
297         four |four
298         one |one
299         signed-tag |A signed tag
300         three |three
301         two |two
302         EOF
303         git for-each-ref --format="%(refname:short) |%(contents:lines=99999)" >actual &&
304         test_cmp expect actual
305 '
306
307 test_expect_success '`%(contents:lines=-1)` should fail' '
308         test_must_fail git for-each-ref --format="%(refname:short) |%(contents:lines=-1)"
309 '
310
311 test_expect_success 'setup for version sort' '
312         test_commit foo1.3 &&
313         test_commit foo1.6 &&
314         test_commit foo1.10
315 '
316
317 test_expect_success 'version sort' '
318         git for-each-ref --sort=version:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
319         cat >expect <<-\EOF &&
320         foo1.3
321         foo1.6
322         foo1.10
323         EOF
324         test_cmp expect actual
325 '
326
327 test_expect_success 'version sort (shortened)' '
328         git for-each-ref --sort=v:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
329         cat >expect <<-\EOF &&
330         foo1.3
331         foo1.6
332         foo1.10
333         EOF
334         test_cmp expect actual
335 '
336
337 test_expect_success 'reverse version sort' '
338         git for-each-ref --sort=-version:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
339         cat >expect <<-\EOF &&
340         foo1.10
341         foo1.6
342         foo1.3
343         EOF
344         test_cmp expect actual
345 '
346
347 test_expect_success 'improper usage of %(if), %(then), %(else) and %(end) atoms' '
348         test_must_fail git for-each-ref --format="%(if)" &&
349         test_must_fail git for-each-ref --format="%(then) %(end)" &&
350         test_must_fail git for-each-ref --format="%(else) %(end)" &&
351         test_must_fail git for-each-ref --format="%(if) %(else) %(end)" &&
352         test_must_fail git for-each-ref --format="%(if) %(then) %(then) %(end)" &&
353         test_must_fail git for-each-ref --format="%(then) %(else) %(end)" &&
354         test_must_fail git for-each-ref --format="%(if) %(else) %(end)" &&
355         test_must_fail git for-each-ref --format="%(if) %(then) %(else)" &&
356         test_must_fail git for-each-ref --format="%(if) %(else) %(then) %(end)" &&
357         test_must_fail git for-each-ref --format="%(if) %(then) %(else) %(else) %(end)" &&
358         test_must_fail git for-each-ref --format="%(if) %(end)"
359 '
360
361 test_expect_success 'check %(if)...%(then)...%(end) atoms' '
362         git for-each-ref --format="%(refname)%(if)%(authorname)%(then) Author: %(authorname)%(end)" >actual &&
363         cat >expect <<-\EOF &&
364         refs/heads/main Author: A U Thor
365         refs/heads/side Author: A U Thor
366         refs/odd/spot Author: A U Thor
367         refs/tags/annotated-tag
368         refs/tags/doubly-annotated-tag
369         refs/tags/doubly-signed-tag
370         refs/tags/foo1.10 Author: A U Thor
371         refs/tags/foo1.3 Author: A U Thor
372         refs/tags/foo1.6 Author: A U Thor
373         refs/tags/four Author: A U Thor
374         refs/tags/one Author: A U Thor
375         refs/tags/signed-tag
376         refs/tags/three Author: A U Thor
377         refs/tags/two Author: A U Thor
378         EOF
379         test_cmp expect actual
380 '
381
382 test_expect_success 'check %(if)...%(then)...%(else)...%(end) atoms' '
383         git for-each-ref --format="%(if)%(authorname)%(then)%(authorname)%(else)No author%(end): %(refname)" >actual &&
384         cat >expect <<-\EOF &&
385         A U Thor: refs/heads/main
386         A U Thor: refs/heads/side
387         A U Thor: refs/odd/spot
388         No author: refs/tags/annotated-tag
389         No author: refs/tags/doubly-annotated-tag
390         No author: refs/tags/doubly-signed-tag
391         A U Thor: refs/tags/foo1.10
392         A U Thor: refs/tags/foo1.3
393         A U Thor: refs/tags/foo1.6
394         A U Thor: refs/tags/four
395         A U Thor: refs/tags/one
396         No author: refs/tags/signed-tag
397         A U Thor: refs/tags/three
398         A U Thor: refs/tags/two
399         EOF
400         test_cmp expect actual
401 '
402 test_expect_success 'ignore spaces in %(if) atom usage' '
403         git for-each-ref --format="%(refname:short): %(if)%(HEAD)%(then)Head ref%(else)Not Head ref%(end)" >actual &&
404         cat >expect <<-\EOF &&
405         main: Head ref
406         side: Not Head ref
407         odd/spot: Not Head ref
408         annotated-tag: Not Head ref
409         doubly-annotated-tag: Not Head ref
410         doubly-signed-tag: Not Head ref
411         foo1.10: Not Head ref
412         foo1.3: Not Head ref
413         foo1.6: Not Head ref
414         four: Not Head ref
415         one: Not Head ref
416         signed-tag: Not Head ref
417         three: Not Head ref
418         two: Not Head ref
419         EOF
420         test_cmp expect actual
421 '
422
423 test_expect_success 'check %(if:equals=<string>)' '
424         git for-each-ref --format="%(if:equals=main)%(refname:short)%(then)Found main%(else)Not main%(end)" refs/heads/ >actual &&
425         cat >expect <<-\EOF &&
426         Found main
427         Not main
428         EOF
429         test_cmp expect actual
430 '
431
432 test_expect_success 'check %(if:notequals=<string>)' '
433         git for-each-ref --format="%(if:notequals=main)%(refname:short)%(then)Not main%(else)Found main%(end)" refs/heads/ >actual &&
434         cat >expect <<-\EOF &&
435         Found main
436         Not main
437         EOF
438         test_cmp expect actual
439 '
440
441 test_expect_success '--merged is compatible with --no-merged' '
442         git for-each-ref --merged HEAD --no-merged HEAD
443 '
444
445 test_expect_success 'validate worktree atom' '
446         cat >expect <<-EOF &&
447         main: $(pwd)
448         main_worktree: $(pwd)/worktree_dir
449         side: not checked out
450         EOF
451         git worktree add -b main_worktree worktree_dir main &&
452         git for-each-ref --format="%(refname:short): %(if)%(worktreepath)%(then)%(worktreepath)%(else)not checked out%(end)" refs/heads/ >actual &&
453         rm -r worktree_dir &&
454         git worktree prune &&
455         test_cmp expect actual
456 '
457
458 test_done