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