3 test_description
='test for-each-refs usage of ref-filter APIs'
5 TEST_PASSES_SANITIZE_LEAK
=true
7 .
"$TEST_DIRECTORY"/lib-gpg.sh
9 test_expect_success
'setup some history and refs' '
14 git checkout -b side &&
16 git tag -m "An annotated tag" annotated-tag &&
17 git tag -m "Annonated doubly" doubly-annotated-tag annotated-tag &&
19 # Note that these "signed" tags might not actually be signed.
20 # Tests which care about the distinction should be marked
21 # with the GPG prereq.
22 if test_have_prereq GPG
28 git tag $sign -m "A signed tag" signed-tag &&
29 git tag $sign -m "Signed doubly" doubly-signed-tag signed-tag &&
32 git update-ref refs/odd/spot main
35 test_expect_success
'--include-root-refs pattern prints pseudorefs' '
36 cat >expect <<-\EOF &&
42 refs/tags/annotated-tag
43 refs/tags/doubly-annotated-tag
44 refs/tags/doubly-signed-tag
51 git update-ref ORIG_HEAD main &&
52 git for-each-ref --format="%(refname)" --include-root-refs >actual &&
53 test_cmp expect actual
56 test_expect_success
'--include-root-refs pattern does not print special refs' '
57 test_when_finished "rm -rf repo" &&
61 test_commit initial &&
62 git rev-parse HEAD >.git/MERGE_HEAD &&
63 git for-each-ref --format="%(refname)" --include-root-refs >actual &&
66 $(git symbolic-ref HEAD)
69 test_cmp expect actual
73 test_expect_success
'--include-root-refs with other patterns' '
74 cat >expect <<-\EOF &&
78 git update-ref ORIG_HEAD main &&
79 git for-each-ref --format="%(refname)" --include-root-refs "*HEAD" >actual &&
80 test_cmp expect actual
83 test_expect_success
'--include-root-refs omits dangling symrefs' '
84 test_when_finished "rm -rf repo" &&
88 test_commit initial &&
89 git symbolic-ref DANGLING_HEAD refs/heads/missing &&
92 $(git symbolic-ref HEAD)
95 git for-each-ref --format="%(refname)" --include-root-refs >actual &&
96 test_cmp expect actual
100 test_expect_success
'filtering with --points-at' '
101 cat >expect <<-\EOF &&
106 git for-each-ref --format="%(refname)" --points-at=main >actual &&
107 test_cmp expect actual
110 test_expect_success
'check signed tags with --points-at' '
111 sed -e "s/Z$//" >expect <<-\EOF &&
113 refs/tags/annotated-tag four
114 refs/tags/doubly-annotated-tag four
115 refs/tags/doubly-signed-tag four
117 refs/tags/signed-tag four
119 git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
120 test_cmp expect actual
123 test_expect_success
'filtering with --merged' '
124 cat >expect <<-\EOF &&
131 git for-each-ref --format="%(refname)" --merged=main >actual &&
132 test_cmp expect actual
135 test_expect_success
'filtering with --no-merged' '
136 cat >expect <<-\EOF &&
138 refs/tags/annotated-tag
139 refs/tags/doubly-annotated-tag
140 refs/tags/doubly-signed-tag
144 git for-each-ref --format="%(refname)" --no-merged=main >actual &&
145 test_cmp expect actual
148 test_expect_success
'filtering with --contains' '
149 cat >expect <<-\EOF &&
153 refs/tags/annotated-tag
154 refs/tags/doubly-annotated-tag
155 refs/tags/doubly-signed-tag
161 git for-each-ref --format="%(refname)" --contains=two >actual &&
162 test_cmp expect actual
165 test_expect_success
'filtering with --no-contains' '
166 cat >expect <<-\EOF &&
169 git for-each-ref --format="%(refname)" --no-contains=two >actual &&
170 test_cmp expect actual
173 test_expect_success
'filtering with --contains and --no-contains' '
174 cat >expect <<-\EOF &&
177 git for-each-ref --format="%(refname)" --contains=two --no-contains=three >actual &&
178 test_cmp expect actual
181 test_expect_success
'%(color) must fail' '
182 test_must_fail git for-each-ref --format="%(color)%(refname)"
185 test_expect_success
'%(color:#aa22ac) must succeed' '
186 test_when_finished rm -rf test &&
190 test_commit initial &&
191 git branch -M main &&
192 cat >expect <<-\EOF &&
196 git remote add origin nowhere &&
197 git config branch.main.remote origin &&
198 git config branch.main.merge refs/heads/main &&
199 git for-each-ref --format="%(color:#aa22ac)%(refname)" >actual &&
200 test_cmp expect actual
204 test_expect_success
'left alignment is default' '
205 cat >expect <<-\EOF &&
206 refname is refs/heads/main |refs/heads/main
207 refname is refs/heads/side |refs/heads/side
208 refname is refs/odd/spot |refs/odd/spot
209 refname is refs/tags/annotated-tag|refs/tags/annotated-tag
210 refname is refs/tags/doubly-annotated-tag|refs/tags/doubly-annotated-tag
211 refname is refs/tags/doubly-signed-tag|refs/tags/doubly-signed-tag
212 refname is refs/tags/four |refs/tags/four
213 refname is refs/tags/one |refs/tags/one
214 refname is refs/tags/signed-tag|refs/tags/signed-tag
215 refname is refs/tags/three |refs/tags/three
216 refname is refs/tags/two |refs/tags/two
218 git for-each-ref --format="%(align:30)refname is %(refname)%(end)|%(refname)" >actual &&
219 test_cmp expect actual
222 test_expect_success
'middle alignment' '
223 cat >expect <<-\EOF &&
224 | refname is refs/heads/main |refs/heads/main
225 | refname is refs/heads/side |refs/heads/side
226 | refname is refs/odd/spot |refs/odd/spot
227 |refname is refs/tags/annotated-tag|refs/tags/annotated-tag
228 |refname is refs/tags/doubly-annotated-tag|refs/tags/doubly-annotated-tag
229 |refname is refs/tags/doubly-signed-tag|refs/tags/doubly-signed-tag
230 | refname is refs/tags/four |refs/tags/four
231 | refname is refs/tags/one |refs/tags/one
232 |refname is refs/tags/signed-tag|refs/tags/signed-tag
233 | refname is refs/tags/three |refs/tags/three
234 | refname is refs/tags/two |refs/tags/two
236 git for-each-ref --format="|%(align:middle,30)refname is %(refname)%(end)|%(refname)" >actual &&
237 test_cmp expect actual
240 test_expect_success
'right alignment' '
241 cat >expect <<-\EOF &&
242 | refname is refs/heads/main|refs/heads/main
243 | refname is refs/heads/side|refs/heads/side
244 | refname is refs/odd/spot|refs/odd/spot
245 |refname is refs/tags/annotated-tag|refs/tags/annotated-tag
246 |refname is refs/tags/doubly-annotated-tag|refs/tags/doubly-annotated-tag
247 |refname is refs/tags/doubly-signed-tag|refs/tags/doubly-signed-tag
248 | refname is refs/tags/four|refs/tags/four
249 | refname is refs/tags/one|refs/tags/one
250 |refname is refs/tags/signed-tag|refs/tags/signed-tag
251 | refname is refs/tags/three|refs/tags/three
252 | refname is refs/tags/two|refs/tags/two
254 git for-each-ref --format="|%(align:30,right)refname is %(refname)%(end)|%(refname)" >actual &&
255 test_cmp expect actual
259 | refname is refs/heads/main |refs/heads/main
260 | refname is refs/heads/side |refs/heads/side
261 | refname is refs/odd/spot |refs/odd/spot
262 | refname is refs/tags/annotated-tag |refs/tags/annotated-tag
263 |refname is refs/tags/doubly-annotated-tag |refs/tags/doubly-annotated-tag
264 | refname is refs/tags/doubly-signed-tag |refs/tags/doubly-signed-tag
265 | refname is refs/tags/four |refs/tags/four
266 | refname is refs/tags/one |refs/tags/one
267 | refname is refs/tags/signed-tag |refs/tags/signed-tag
268 | refname is refs/tags/three |refs/tags/three
269 | refname is refs/tags/two |refs/tags/two
272 test_align_permutations() {
275 test_expect_success "align:$option" '
276 git for-each-ref --format="|%(align:$option)refname is %(refname)%(end)|%(refname)" >actual &&
277 test_cmp expect actual
282 test_align_permutations <<-\
EOF
289 position=middle,width=42
290 width=42,position=middle
293 # Last one wins (silently) when multiple arguments of the same type are given
295 test_align_permutations <<-\EOF
298 width=42,position=right,middle
299 42,right,position=middle
302 # Individual atoms inside %(align:...) and %(end) must not be quoted.
304 test_expect_success 'alignment with format quote' "
305 cat >expect <<-\EOF &&
306 |' '\''main| A U Thor'\'' '|
307 |' '\''side| A U Thor'\'' '|
308 |' '\''odd/spot| A U Thor'\'' '|
309 |' '\''annotated-tag| '\'' '|
310 |' '\''doubly-annotated-tag| '\'' '|
311 |' '\''doubly-signed-tag| '\'' '|
312 |' '\''four| A U Thor'\'' '|
313 |' '\''one| A U Thor'\'' '|
314 |' '\''signed-tag| '\'' '|
315 |' '\''three| A U Thor'\'' '|
316 |' '\''two| A U Thor'\'' '|
318 git for-each-ref --shell --format=\"|%(align:30,middle)'%(refname:short)| %(authorname)'%(end)|\" >actual &&
319 test_cmp expect actual
322 test_expect_success 'nested alignment with quote formatting' "
323 cat >expect <<-\EOF &&
328 |'doubly-annotated-tag '|
329 |'doubly-signed-tag '|
336 git for-each-ref --shell --format='|%(align:30,left)%(align:15,right)%(refname:short)%(end)%(end)|' >actual &&
337 test_cmp expect actual
340 test_expect_success 'check `%(contents:lines=1)`' '
341 cat >expect <<-\EOF &&
345 annotated-tag |An annotated tag
346 doubly-annotated-tag |Annonated doubly
347 doubly-signed-tag |Signed doubly
350 signed-tag |A signed tag
354 git for-each-ref --format="%(refname:short) |%(contents:lines=1)" >actual &&
355 test_cmp expect actual
358 test_expect_success 'check `%(contents:lines=0)`' '
359 cat >expect <<-\EOF &&
364 doubly-annotated-tag |
372 git for-each-ref --format="%(refname:short) |%(contents:lines=0)" >actual &&
373 test_cmp expect actual
376 test_expect_success 'check `%(contents:lines=99999)`' '
377 cat >expect <<-\EOF &&
381 annotated-tag |An annotated tag
382 doubly-annotated-tag |Annonated doubly
383 doubly-signed-tag |Signed doubly
386 signed-tag |A signed tag
390 git for-each-ref --format="%(refname:short) |%(contents:lines=99999)" >actual &&
391 test_cmp expect actual
394 test_expect_success '`%(contents:lines=-1)` should fail' '
395 test_must_fail git for-each-ref --format="%(refname:short) |%(contents:lines=-1)"
398 test_expect_success 'setup for version sort' '
399 test_commit foo1.3 &&
400 test_commit foo1.6 &&
404 test_expect_success 'version sort' '
405 git for-each-ref --sort=version:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
406 cat >expect <<-\EOF &&
411 test_cmp expect actual
414 test_expect_success 'version sort (shortened)' '
415 git for-each-ref --sort=v:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
416 cat >expect <<-\EOF &&
421 test_cmp expect actual
424 test_expect_success 'reverse version sort' '
425 git for-each-ref --sort=-version:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
426 cat >expect <<-\EOF &&
431 test_cmp expect actual
434 test_expect_success 'improper usage of %(if), %(then), %(else) and %(end) atoms' '
435 test_must_fail git for-each-ref --format="%(if)" &&
436 test_must_fail git for-each-ref --format="%(then) %(end)" &&
437 test_must_fail git for-each-ref --format="%(else) %(end)" &&
438 test_must_fail git for-each-ref --format="%(if) %(else) %(end)" &&
439 test_must_fail git for-each-ref --format="%(if) %(then) %(then) %(end)" &&
440 test_must_fail git for-each-ref --format="%(then) %(else) %(end)" &&
441 test_must_fail git for-each-ref --format="%(if) %(else) %(end)" &&
442 test_must_fail git for-each-ref --format="%(if) %(then) %(else)" &&
443 test_must_fail git for-each-ref --format="%(if) %(else) %(then) %(end)" &&
444 test_must_fail git for-each-ref --format="%(if) %(then) %(else) %(else) %(end)" &&
445 test_must_fail git for-each-ref --format="%(if) %(end)"
448 test_expect_success 'check %(if)...%(then)...%(end) atoms' '
449 git for-each-ref --format="%(refname)%(if)%(authorname)%(then) Author: %(authorname)%(end)" >actual &&
450 cat >expect <<-\EOF &&
451 refs/heads/main Author: A U Thor
452 refs/heads/side Author: A U Thor
453 refs/odd/spot Author: A U Thor
454 refs/tags/annotated-tag
455 refs/tags/doubly-annotated-tag
456 refs/tags/doubly-signed-tag
457 refs/tags/foo1.10 Author: A U Thor
458 refs/tags/foo1.3 Author: A U Thor
459 refs/tags/foo1.6 Author: A U Thor
460 refs/tags/four Author: A U Thor
461 refs/tags/one Author: A U Thor
463 refs/tags/three Author: A U Thor
464 refs/tags/two Author: A U Thor
466 test_cmp expect actual
469 test_expect_success 'check %(if)...%(then)...%(else)...%(end) atoms' '
470 git for-each-ref --format="%(if)%(authorname)%(then)%(authorname)%(else)No author%(end): %(refname)" >actual &&
471 cat >expect <<-\EOF &&
472 A U Thor: refs/heads/main
473 A U Thor: refs/heads/side
474 A U Thor: refs/odd/spot
475 No author: refs/tags/annotated-tag
476 No author: refs/tags/doubly-annotated-tag
477 No author: refs/tags/doubly-signed-tag
478 A U Thor: refs/tags/foo1.10
479 A U Thor: refs/tags/foo1.3
480 A U Thor: refs/tags/foo1.6
481 A U Thor: refs/tags/four
482 A U Thor: refs/tags/one
483 No author: refs/tags/signed-tag
484 A U Thor: refs/tags/three
485 A U Thor: refs/tags/two
487 test_cmp expect actual
489 test_expect_success 'ignore spaces in %(if) atom usage' '
490 git for-each-ref --format="%(refname:short): %(if)%(HEAD)%(then)Head ref%(else)Not Head ref%(end)" >actual &&
491 cat >expect <<-\EOF &&
494 odd/spot: Not Head ref
495 annotated-tag: Not Head ref
496 doubly-annotated-tag: Not Head ref
497 doubly-signed-tag: Not Head ref
498 foo1.10: Not Head ref
503 signed-tag: Not Head ref
507 test_cmp expect actual
510 test_expect_success 'check %(if:equals=<string>)' '
511 git for-each-ref --format="%(if:equals=main)%(refname:short)%(then)Found main%(else)Not main%(end)" refs/heads/ >actual &&
512 cat >expect <<-\EOF &&
516 test_cmp expect actual
519 test_expect_success 'check %(if:notequals=<string>)' '
520 git for-each-ref --format="%(if:notequals=main)%(refname:short)%(then)Not main%(else)Found main%(end)" refs/heads/ >actual &&
521 cat >expect <<-\EOF &&
525 test_cmp expect actual
528 test_expect_success '--merged is compatible with --no-merged' '
529 git for-each-ref --merged HEAD --no-merged HEAD
532 test_expect_success 'validate worktree atom' '
533 cat >expect <<-EOF &&
535 main_worktree: $(pwd)/worktree_dir
536 side: not checked out
538 git worktree add -b main_worktree worktree_dir main &&
539 git for-each-ref --format="%(refname:short): %(if)%(worktreepath)%(then)%(worktreepath)%(else)not checked out%(end)" refs/heads/ >actual &&
540 rm -r worktree_dir &&
541 git worktree prune &&
542 test_cmp expect actual