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