203cfaa156a409925b450a9be55488e91dbcca80
1#!/bin/sh
2#
3# Copyright (c) 2007 Andy Parkins
4#
5
6test_description='for-each-ref test'
7
8. ./test-lib.sh
9. "$TEST_DIRECTORY"/lib-gpg.sh
10
11# Mon Jul 3 23:18:43 2006 +0000
12datestamp=1151968723
13setdate_and_increment () {
14 GIT_COMMITTER_DATE="$datestamp +0200"
15 datestamp=$(expr "$datestamp" + 1)
16 GIT_AUTHOR_DATE="$datestamp +0200"
17 datestamp=$(expr "$datestamp" + 1)
18 export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
19}
20
21test_expect_success setup '
22 setdate_and_increment &&
23 echo "Using $datestamp" > one &&
24 git add one &&
25 git commit -m "Initial" &&
26 setdate_and_increment &&
27 git tag -a -m "Tagging at $datestamp" testtag &&
28 git update-ref refs/remotes/origin/master master &&
29 git remote add origin nowhere &&
30 git config branch.master.remote origin &&
31 git config branch.master.merge refs/heads/master &&
32 git remote add myfork elsewhere &&
33 git config remote.pushdefault myfork &&
34 git config push.default current
35'
36
37test_atom() {
38 case "$1" in
39 head) ref=refs/heads/master ;;
40 tag) ref=refs/tags/testtag ;;
41 sym) ref=refs/heads/sym ;;
42 *) ref=$1 ;;
43 esac
44 printf '%s\n' "$3" >expected
45 test_expect_${4:-success} $PREREQ "basic atom: $1 $2" "
46 git for-each-ref --format='%($2)' $ref >actual &&
47 sanitize_pgp <actual >actual.clean &&
48 test_cmp expected actual.clean
49 "
50}
51
52test_atom head refname refs/heads/master
53test_atom head refname:short master
54test_atom head refname:lstrip=1 heads/master
55test_atom head refname:lstrip=2 master
56test_atom head refname:lstrip=-1 master
57test_atom head refname:lstrip=-2 heads/master
58test_atom head upstream refs/remotes/origin/master
59test_atom head upstream:short origin/master
60test_atom head upstream:lstrip=2 origin/master
61test_atom head upstream:lstrip=-2 origin/master
62test_atom head push refs/remotes/myfork/master
63test_atom head push:short myfork/master
64test_atom head push:lstrip=1 remotes/myfork/master
65test_atom head push:lstrip=-1 master
66test_atom head objecttype commit
67test_atom head objectsize 171
68test_atom head objectname $(git rev-parse refs/heads/master)
69test_atom head objectname:short $(git rev-parse --short refs/heads/master)
70test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master)
71test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/master)
72test_atom head tree $(git rev-parse refs/heads/master^{tree})
73test_atom head parent ''
74test_atom head numparent 0
75test_atom head object ''
76test_atom head type ''
77test_atom head '*objectname' ''
78test_atom head '*objecttype' ''
79test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
80test_atom head authorname 'A U Thor'
81test_atom head authoremail '<author@example.com>'
82test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200'
83test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200'
84test_atom head committername 'C O Mitter'
85test_atom head committeremail '<committer@example.com>'
86test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200'
87test_atom head tag ''
88test_atom head tagger ''
89test_atom head taggername ''
90test_atom head taggeremail ''
91test_atom head taggerdate ''
92test_atom head creator 'C O Mitter <committer@example.com> 1151968723 +0200'
93test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200'
94test_atom head subject 'Initial'
95test_atom head contents:subject 'Initial'
96test_atom head body ''
97test_atom head contents:body ''
98test_atom head contents:signature ''
99test_atom head contents 'Initial
100'
101test_atom head HEAD '*'
102
103test_atom tag refname refs/tags/testtag
104test_atom tag refname:short testtag
105test_atom tag upstream ''
106test_atom tag push ''
107test_atom tag objecttype tag
108test_atom tag objectsize 154
109test_atom tag objectname $(git rev-parse refs/tags/testtag)
110test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
111test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master)
112test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/master)
113test_atom tag tree ''
114test_atom tag parent ''
115test_atom tag numparent ''
116test_atom tag object $(git rev-parse refs/tags/testtag^0)
117test_atom tag type 'commit'
118test_atom tag '*objectname' 'ea122842f48be4afb2d1fc6a4b96c05885ab7463'
119test_atom tag '*objecttype' 'commit'
120test_atom tag author ''
121test_atom tag authorname ''
122test_atom tag authoremail ''
123test_atom tag authordate ''
124test_atom tag committer ''
125test_atom tag committername ''
126test_atom tag committeremail ''
127test_atom tag committerdate ''
128test_atom tag tag 'testtag'
129test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200'
130test_atom tag taggername 'C O Mitter'
131test_atom tag taggeremail '<committer@example.com>'
132test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200'
133test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200'
134test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200'
135test_atom tag subject 'Tagging at 1151968727'
136test_atom tag contents:subject 'Tagging at 1151968727'
137test_atom tag body ''
138test_atom tag contents:body ''
139test_atom tag contents:signature ''
140test_atom tag contents 'Tagging at 1151968727
141'
142test_atom tag HEAD ' '
143
144test_expect_success 'Check invalid atoms names are errors' '
145 test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
146'
147
148test_expect_success 'Check format specifiers are ignored in naming date atoms' '
149 git for-each-ref --format="%(authordate)" refs/heads &&
150 git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
151 git for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
152 git for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
153'
154
155test_expect_success 'Check valid format specifiers for date fields' '
156 git for-each-ref --format="%(authordate:default)" refs/heads &&
157 git for-each-ref --format="%(authordate:relative)" refs/heads &&
158 git for-each-ref --format="%(authordate:short)" refs/heads &&
159 git for-each-ref --format="%(authordate:local)" refs/heads &&
160 git for-each-ref --format="%(authordate:iso8601)" refs/heads &&
161 git for-each-ref --format="%(authordate:rfc2822)" refs/heads
162'
163
164test_expect_success 'Check invalid format specifiers are errors' '
165 test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
166'
167
168test_expect_success 'arguments to %(objectname:short=) must be positive integers' '
169 test_must_fail git for-each-ref --format="%(objectname:short=0)" &&
170 test_must_fail git for-each-ref --format="%(objectname:short=-1)" &&
171 test_must_fail git for-each-ref --format="%(objectname:short=foo)"
172'
173
174test_date () {
175 f=$1 &&
176 committer_date=$2 &&
177 author_date=$3 &&
178 tagger_date=$4 &&
179 cat >expected <<-EOF &&
180 'refs/heads/master' '$committer_date' '$author_date'
181 'refs/tags/testtag' '$tagger_date'
182 EOF
183 (
184 git for-each-ref --shell \
185 --format="%(refname) %(committerdate${f:+:$f}) %(authordate${f:+:$f})" \
186 refs/heads &&
187 git for-each-ref --shell \
188 --format="%(refname) %(taggerdate${f:+:$f})" \
189 refs/tags
190 ) >actual &&
191 test_cmp expected actual
192}
193
194test_expect_success 'Check unformatted date fields output' '
195 test_date "" \
196 "Tue Jul 4 01:18:43 2006 +0200" \
197 "Tue Jul 4 01:18:44 2006 +0200" \
198 "Tue Jul 4 01:18:45 2006 +0200"
199'
200
201test_expect_success 'Check format "default" formatted date fields output' '
202 test_date default \
203 "Tue Jul 4 01:18:43 2006 +0200" \
204 "Tue Jul 4 01:18:44 2006 +0200" \
205 "Tue Jul 4 01:18:45 2006 +0200"
206'
207
208test_expect_success 'Check format "default-local" date fields output' '
209 test_date default-local "Mon Jul 3 23:18:43 2006" "Mon Jul 3 23:18:44 2006" "Mon Jul 3 23:18:45 2006"
210'
211
212# Don't know how to do relative check because I can't know when this script
213# is going to be run and can't fake the current time to git, and hence can't
214# provide expected output. Instead, I'll just make sure that "relative"
215# doesn't exit in error
216test_expect_success 'Check format "relative" date fields output' '
217 f=relative &&
218 (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
219 git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual
220'
221
222# We just check that this is the same as "relative" for now.
223test_expect_success 'Check format "relative-local" date fields output' '
224 test_date relative-local \
225 "$(git for-each-ref --format="%(committerdate:relative)" refs/heads)" \
226 "$(git for-each-ref --format="%(authordate:relative)" refs/heads)" \
227 "$(git for-each-ref --format="%(taggerdate:relative)" refs/tags)"
228'
229
230test_expect_success 'Check format "short" date fields output' '
231 test_date short 2006-07-04 2006-07-04 2006-07-04
232'
233
234test_expect_success 'Check format "short-local" date fields output' '
235 test_date short-local 2006-07-03 2006-07-03 2006-07-03
236'
237
238test_expect_success 'Check format "local" date fields output' '
239 test_date local \
240 "Mon Jul 3 23:18:43 2006" \
241 "Mon Jul 3 23:18:44 2006" \
242 "Mon Jul 3 23:18:45 2006"
243'
244
245test_expect_success 'Check format "iso8601" date fields output' '
246 test_date iso8601 \
247 "2006-07-04 01:18:43 +0200" \
248 "2006-07-04 01:18:44 +0200" \
249 "2006-07-04 01:18:45 +0200"
250'
251
252test_expect_success 'Check format "iso8601-local" date fields output' '
253 test_date iso8601-local "2006-07-03 23:18:43 +0000" "2006-07-03 23:18:44 +0000" "2006-07-03 23:18:45 +0000"
254'
255
256test_expect_success 'Check format "rfc2822" date fields output' '
257 test_date rfc2822 \
258 "Tue, 4 Jul 2006 01:18:43 +0200" \
259 "Tue, 4 Jul 2006 01:18:44 +0200" \
260 "Tue, 4 Jul 2006 01:18:45 +0200"
261'
262
263test_expect_success 'Check format "rfc2822-local" date fields output' '
264 test_date rfc2822-local "Mon, 3 Jul 2006 23:18:43 +0000" "Mon, 3 Jul 2006 23:18:44 +0000" "Mon, 3 Jul 2006 23:18:45 +0000"
265'
266
267test_expect_success 'Check format "raw" date fields output' '
268 test_date raw "1151968723 +0200" "1151968724 +0200" "1151968725 +0200"
269'
270
271test_expect_success 'Check format "raw-local" date fields output' '
272 test_date raw-local "1151968723 +0000" "1151968724 +0000" "1151968725 +0000"
273'
274
275test_expect_success 'Check format of strftime date fields' '
276 echo "my date is 2006-07-04" >expected &&
277 git for-each-ref \
278 --format="%(authordate:format:my date is %Y-%m-%d)" \
279 refs/heads >actual &&
280 test_cmp expected actual
281'
282
283test_expect_success 'Check format of strftime-local date fields' '
284 echo "my date is 2006-07-03" >expected &&
285 git for-each-ref \
286 --format="%(authordate:format-local:my date is %Y-%m-%d)" \
287 refs/heads >actual &&
288 test_cmp expected actual
289'
290
291test_expect_success 'exercise strftime with odd fields' '
292 echo >expected &&
293 git for-each-ref --format="%(authordate:format:)" refs/heads >actual &&
294 test_cmp expected actual &&
295 long="long format -- $_z40$_z40$_z40$_z40$_z40$_z40$_z40" &&
296 echo $long >expected &&
297 git for-each-ref --format="%(authordate:format:$long)" refs/heads >actual &&
298 test_cmp expected actual
299'
300
301cat >expected <<\EOF
302refs/heads/master
303refs/remotes/origin/master
304refs/tags/testtag
305EOF
306
307test_expect_success 'Verify ascending sort' '
308 git for-each-ref --format="%(refname)" --sort=refname >actual &&
309 test_cmp expected actual
310'
311
312
313cat >expected <<\EOF
314refs/tags/testtag
315refs/remotes/origin/master
316refs/heads/master
317EOF
318
319test_expect_success 'Verify descending sort' '
320 git for-each-ref --format="%(refname)" --sort=-refname >actual &&
321 test_cmp expected actual
322'
323
324cat >expected <<\EOF
325'refs/heads/master'
326'refs/remotes/origin/master'
327'refs/tags/testtag'
328EOF
329
330test_expect_success 'Quoting style: shell' '
331 git for-each-ref --shell --format="%(refname)" >actual &&
332 test_cmp expected actual
333'
334
335test_expect_success 'Quoting style: perl' '
336 git for-each-ref --perl --format="%(refname)" >actual &&
337 test_cmp expected actual
338'
339
340test_expect_success 'Quoting style: python' '
341 git for-each-ref --python --format="%(refname)" >actual &&
342 test_cmp expected actual
343'
344
345cat >expected <<\EOF
346"refs/heads/master"
347"refs/remotes/origin/master"
348"refs/tags/testtag"
349EOF
350
351test_expect_success 'Quoting style: tcl' '
352 git for-each-ref --tcl --format="%(refname)" >actual &&
353 test_cmp expected actual
354'
355
356for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
357 test_expect_success "more than one quoting style: $i" "
358 git for-each-ref $i 2>&1 | (read line &&
359 case \$line in
360 \"error: more than one quoting style\"*) : happy;;
361 *) false
362 esac)
363 "
364done
365
366test_expect_success 'setup for upstream:track[short]' '
367 test_commit two
368'
369
370test_atom head upstream:track '[ahead 1]'
371test_atom head upstream:trackshort '>'
372test_atom head upstream:track,nobracket 'ahead 1'
373test_atom head upstream:nobracket,track 'ahead 1'
374test_atom head push:track '[ahead 1]'
375test_atom head push:trackshort '>'
376
377test_expect_success 'Check that :track[short] cannot be used with other atoms' '
378 test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null &&
379 test_must_fail git for-each-ref --format="%(refname:trackshort)" 2>/dev/null
380'
381
382test_expect_success 'Check that :track[short] works when upstream is invalid' '
383 cat >expected <<-\EOF &&
384 [gone]
385
386 EOF
387 test_when_finished "git config branch.master.merge refs/heads/master" &&
388 git config branch.master.merge refs/heads/does-not-exist &&
389 git for-each-ref \
390 --format="%(upstream:track)$LF%(upstream:trackshort)" \
391 refs/heads >actual &&
392 test_cmp expected actual
393'
394
395test_expect_success 'Check for invalid refname format' '
396 test_must_fail git for-each-ref --format="%(refname:INVALID)"
397'
398
399get_color ()
400{
401 git config --get-color no.such.slot "$1"
402}
403
404cat >expected <<EOF
405$(git rev-parse --short refs/heads/master) $(get_color green)master$(get_color reset)
406$(git rev-parse --short refs/remotes/origin/master) $(get_color green)origin/master$(get_color reset)
407$(git rev-parse --short refs/tags/testtag) $(get_color green)testtag$(get_color reset)
408$(git rev-parse --short refs/tags/two) $(get_color green)two$(get_color reset)
409EOF
410
411test_expect_success 'Check %(color:...) ' '
412 git for-each-ref --format="%(objectname:short) %(color:green)%(refname:short)" >actual &&
413 test_cmp expected actual
414'
415
416cat >expected <<\EOF
417heads/master
418tags/master
419EOF
420
421test_expect_success 'Check ambiguous head and tag refs (strict)' '
422 git config --bool core.warnambiguousrefs true &&
423 git checkout -b newtag &&
424 echo "Using $datestamp" > one &&
425 git add one &&
426 git commit -m "Branch" &&
427 setdate_and_increment &&
428 git tag -m "Tagging at $datestamp" master &&
429 git for-each-ref --format "%(refname:short)" refs/heads/master refs/tags/master >actual &&
430 test_cmp expected actual
431'
432
433cat >expected <<\EOF
434heads/master
435master
436EOF
437
438test_expect_success 'Check ambiguous head and tag refs (loose)' '
439 git config --bool core.warnambiguousrefs false &&
440 git for-each-ref --format "%(refname:short)" refs/heads/master refs/tags/master >actual &&
441 test_cmp expected actual
442'
443
444cat >expected <<\EOF
445heads/ambiguous
446ambiguous
447EOF
448
449test_expect_success 'Check ambiguous head and tag refs II (loose)' '
450 git checkout master &&
451 git tag ambiguous testtag^0 &&
452 git branch ambiguous testtag^0 &&
453 git for-each-ref --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual &&
454 test_cmp expected actual
455'
456
457test_expect_success 'an unusual tag with an incomplete line' '
458
459 git tag -m "bogo" bogo &&
460 bogo=$(git cat-file tag bogo) &&
461 bogo=$(printf "%s" "$bogo" | git mktag) &&
462 git tag -f bogo "$bogo" &&
463 git for-each-ref --format "%(body)" refs/tags/bogo
464
465'
466
467test_expect_success 'create tag with subject and body content' '
468 cat >>msg <<-\EOF &&
469 the subject line
470
471 first body line
472 second body line
473 EOF
474 git tag -F msg subject-body
475'
476test_atom refs/tags/subject-body subject 'the subject line'
477test_atom refs/tags/subject-body body 'first body line
478second body line
479'
480test_atom refs/tags/subject-body contents 'the subject line
481
482first body line
483second body line
484'
485
486test_expect_success 'create tag with multiline subject' '
487 cat >msg <<-\EOF &&
488 first subject line
489 second subject line
490
491 first body line
492 second body line
493 EOF
494 git tag -F msg multiline
495'
496test_atom refs/tags/multiline subject 'first subject line second subject line'
497test_atom refs/tags/multiline contents:subject 'first subject line second subject line'
498test_atom refs/tags/multiline body 'first body line
499second body line
500'
501test_atom refs/tags/multiline contents:body 'first body line
502second body line
503'
504test_atom refs/tags/multiline contents:signature ''
505test_atom refs/tags/multiline contents 'first subject line
506second subject line
507
508first body line
509second body line
510'
511
512test_expect_success GPG 'create signed tags' '
513 git tag -s -m "" signed-empty &&
514 git tag -s -m "subject line" signed-short &&
515 cat >msg <<-\EOF &&
516 subject line
517
518 body contents
519 EOF
520 git tag -s -F msg signed-long
521'
522
523sig='-----BEGIN PGP SIGNATURE-----
524-----END PGP SIGNATURE-----
525'
526
527PREREQ=GPG
528test_atom refs/tags/signed-empty subject ''
529test_atom refs/tags/signed-empty contents:subject ''
530test_atom refs/tags/signed-empty body "$sig"
531test_atom refs/tags/signed-empty contents:body ''
532test_atom refs/tags/signed-empty contents:signature "$sig"
533test_atom refs/tags/signed-empty contents "$sig"
534
535test_atom refs/tags/signed-short subject 'subject line'
536test_atom refs/tags/signed-short contents:subject 'subject line'
537test_atom refs/tags/signed-short body "$sig"
538test_atom refs/tags/signed-short contents:body ''
539test_atom refs/tags/signed-short contents:signature "$sig"
540test_atom refs/tags/signed-short contents "subject line
541$sig"
542
543test_atom refs/tags/signed-long subject 'subject line'
544test_atom refs/tags/signed-long contents:subject 'subject line'
545test_atom refs/tags/signed-long body "body contents
546$sig"
547test_atom refs/tags/signed-long contents:body 'body contents
548'
549test_atom refs/tags/signed-long contents:signature "$sig"
550test_atom refs/tags/signed-long contents "subject line
551
552body contents
553$sig"
554
555cat >expected <<EOF
556$(git rev-parse refs/tags/bogo) <committer@example.com> refs/tags/bogo
557$(git rev-parse refs/tags/master) <committer@example.com> refs/tags/master
558EOF
559
560test_expect_success 'Verify sort with multiple keys' '
561 git for-each-ref --format="%(objectname) %(taggeremail) %(refname)" --sort=objectname --sort=taggeremail \
562 refs/tags/bogo refs/tags/master > actual &&
563 test_cmp expected actual
564'
565
566
567test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
568 test_when_finished "git checkout master" &&
569 git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
570 sed -e "s/^\* / /" actual >expect &&
571 git checkout --orphan HEAD &&
572 git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
573 test_cmp expect actual
574'
575
576cat >trailers <<EOF
577Reviewed-by: A U Thor <author@example.com>
578Signed-off-by: A U Thor <author@example.com>
579EOF
580
581test_expect_success 'basic atom: head contents:trailers' '
582 echo "Some contents" > two &&
583 git add two &&
584 git commit -F - <<-EOF &&
585 trailers: this commit message has trailers
586
587 Some message contents
588
589 $(cat trailers)
590 EOF
591 git for-each-ref --format="%(contents:trailers)" refs/heads/master >actual &&
592 sanitize_pgp <actual >actual.clean &&
593 # git for-each-ref ends with a blank line
594 cat >expect <<-EOF &&
595 $(cat trailers)
596
597 EOF
598 test_cmp expect actual.clean
599'
600
601test_expect_success 'Add symbolic ref for the following tests' '
602 git symbolic-ref refs/heads/sym refs/heads/master
603'
604
605cat >expected <<EOF
606refs/heads/master
607EOF
608
609test_expect_success 'Verify usage of %(symref) atom' '
610 git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
611 test_cmp expected actual
612'
613
614cat >expected <<EOF
615heads/master
616EOF
617
618test_expect_success 'Verify usage of %(symref:short) atom' '
619 git for-each-ref --format="%(symref:short)" refs/heads/sym >actual &&
620 test_cmp expected actual
621'
622
623cat >expected <<EOF
624master
625heads/master
626EOF
627
628test_expect_success 'Verify usage of %(symref:lstrip) atom' '
629 git for-each-ref --format="%(symref:lstrip=2)" refs/heads/sym > actual &&
630 git for-each-ref --format="%(symref:lstrip=-2)" refs/heads/sym >> actual &&
631 test_cmp expected actual
632'
633
634test_done