chiark / gitweb /
test suite: In ad-hoc runs, honour DGIT_TEST_RETRY_COUNT
[dgit.git] / tests / lib
1 #
2
3 exec 2>&1
4 set -x
5 set -o pipefail
6
7 . tests/lib-core
8 . tests/lib-restricts
9
10 t-report-failure () {
11         set +x
12         rc=$1
13         cat <<END >&2
14 TEST FAILED
15 cwd: $PWD
16 funcs: ${FUNCNAME[*]}
17 lines: ${BASH_LINENO[*]}
18 files: ${BASH_SOURCE[*]}
19 END
20         exit 16
21 }
22
23 trap 'test $? = 0 || t-report-failure' EXIT
24
25 t-filter-out-git-hyphen-dir
26
27 t-set-intree
28
29 : ${DGIT_TEST_DEBUG=-D}
30 export DGIT_TEST_DEBUG
31
32 : ${DGIT_TEST_DISTRO+ ${distro=${DGIT_TEST_DISTRO}}}
33
34 export GIT_COMMITTER_DATE='1440253867 +0100'
35 export GIT_AUTHOR_DATE='1440253867 +0100'
36
37 root=`pwd`
38 troot=$root/tests
39 testname="${DGIT_TEST_TESTNAME-${0##*/}}"
40 export DGIT_TEST_TROOT=$troot
41
42 tmp=$ADTTMP
43 if [ x"$tmp" = x ]; then
44         mkdir -p tests/tmp
45         tmpbase=$troot/tmp
46         tmp=tests/tmp/$testname
47         rm -rf $tmp
48         mkdir $tmp
49 elif [ "x$DGIT_TEST_TMPBASE" != x ]; then
50         tmpbase="$DGIT_TEST_TMPBASE"
51 fi
52 cd $tmp
53
54 tmp=`pwd`
55
56 t-set-using-tmp
57
58 test -f $tmp/.save-env || \
59 env -0 >$tmp/.save-env
60
61 ln -f $troot/ssh ssh
62
63 export DEBCHANGE_VENDOR=dpkg
64
65 mkdir -p $tmp/incoming
66 cat <<END >$tmp/dput.cf
67 [test-dummy]
68 method                  = local
69 incoming                = $tmp/incoming
70 run_dinstall            = 0
71 END
72
73 : ${t_archive_method:=aq}
74 : ${tagpfx:=archive/test-dummy}
75 : ${suitespecs:=sid:unstable}
76
77 t-git-next-date () {
78         GIT_COMMITTER_DATE="$(( ${GIT_COMMITTER_DATE%% *} + 1 )) ${GIT_COMMITTER_DATE#* }"
79         GIT_AUTHOR_DATE="$GIT_COMMITTER_DATE"
80 }
81
82 t-expect-fail () {
83         local mpat="$1"; shift
84
85         set +o pipefail
86         LC_MESSAGES=C "$@" 2>&1 | tee $tmp/t.output
87         local ps="${PIPESTATUS[*]}"
88         set -o pipefail
89
90         case $ps in
91         "0 0")  fail "command unexpectedly succeeded (instead of: $mpat)" ;;
92         *" 0")  ;;
93         *)      fail "tee failed"  ;;
94         esac
95
96         t-grep-mpat "$mpat" $tmp/t.output
97 }
98
99 t-grep-mpat () {
100         local mpat="$1"
101         local file="$2"
102
103         local grepper=fgrep
104         case "$mpat" in
105         [A-Z]:*)
106                 case "$mpat" in
107                 E:*)    grepper=egrep   ;;
108                 F:*)    grepper=fgrep   ;;
109                 *)      fail "bad mpat prefix in $mpat";;
110                 esac
111                 mpat=${mpat#[A-Z]:}
112                 ;;
113         esac
114
115         $grepper -e "$mpat" "$file" ||
116                 fail "message not found"
117 }
118
119 t-expect-push-fail () {
120         local mpat="$1"; shift
121
122         local triedpush; triedpush=`git rev-parse HEAD`
123
124         t-reporefs pre-push
125         t-expect-fail "$mpat"  "$@"
126         t-reporefs post-push
127         diff $tmp/show-refs.{pre,post}-push
128
129         t-git-objects-not-present '' $triedpush
130
131         eval "$t_expect_push_fail_hook"
132 }
133
134 t-git-objects-not-present () {
135         # t-git-objects-not-present GITDIR|'' OBJID [...]
136         # specifying '' means the repo for package $p
137         local gitdir="${1-$dgitrepo}"
138         local obj
139         if ! [ -e "$gitdir" ]; then return; fi
140         for obj in "$@"; do
141                 GIT_DIR=$gitdir \
142                 t-expect-fail 'unable to find' \
143                 git cat-file -t $obj
144         done
145 }
146
147 t-reporefs () {
148         local whichoutput=$1; shift
149         local whichrepo=${1-$dgitrepo}
150         local outputfile="$tmp/show-refs.$whichoutput"
151         (set -e
152          exec >"$outputfile"
153          if test -d $whichrepo; then
154                 cd $whichrepo
155                 git show-ref |sort
156         fi)
157 }
158
159 t-untar () {
160         local tarfile=$1.tar
161         local edittree=$1.edit
162         if test -d "$edittree"; then
163                 cp -a "$edittree"/* .
164         else
165                 tar xf "$tarfile"
166         fi
167 }
168
169 t-worktree () {
170         rm -rf $p
171         t-untar $troot/worktrees/${p}_$1
172 }
173
174 t-select-package () {
175         p=$1
176         dgitrepo=$tmp/git/$p.git
177 }
178
179 t-git () {
180         t-select-package $1
181         v=$2
182         mkdir -p $tmp/git
183         local gs=$troot/git-srcs/${p}_$v.git
184         (set -e; cd $tmp/git; t-untar $gs)
185 }
186
187 t-git-none () {
188         mkdir -p $tmp/git
189         (set -e; cd $tmp/git; tar xf $troot/git-template.tar)
190 }
191
192 t-git-merge-base () {
193         git merge-base $1 $2 || test $? = 1
194 }
195
196 t-has-ancestor () {
197         # t-has-ancestor ANCESTOR
198         # (CHILD is implicit, HEAD)
199         local now;      now=`git rev-parse HEAD`
200         local ancestor; ancestor=`git rev-parse $1^{}`
201         local mbase;    mbase=`t-git-merge-base $ancestor $now`
202         if [ x$mbase != x$ancestor ]; then
203                 fail "not ff $ancestor..$now, $mbase != $ancestor"
204         fi
205 }
206
207 t-has-parent-or-is () {
208         # t-has-parent-or-is CHILD PARENT
209         local child=$1
210         local parent=$2
211         local parents
212         parents=$(git show --pretty=format:' %P %H ' "$child")
213         parent=$(git rev-parse "$parent~0")
214         case "$parents" in
215         *" $parent "*)  ;;
216         *)      fail "child $child lacks parent $parent" ;;
217         esac
218 }
219
220 t-prep-newpackage () {
221         t-select-package $1
222         v=$2
223         t-archive-none $p
224         t-git-none
225         t-worktree $v
226         cd $p
227         if ! git show-ref --verify --quiet refs/heads/master; then
228                 git branch -m dgit/sid master
229                 git remote rm dgit
230         fi
231         cd ..
232 }
233
234 t-archive-none () {
235         t-select-package $1
236         t-archive-none-$t_archive_method
237 }
238 t-archive-none-aq () {
239         mkdir -p $tmp/aq/dsc_in_suite $tmp/mirror/pool/main
240
241         : >$tmp/aq/suites
242         local jsondelim="["
243
244         local suitespec
245         for suitespec in $suitespecs; do
246                 local suite=${suitespec%%:*}
247                 local sname=${suitespec#*:}
248
249                 >$tmp/aq/package.$suite.$p
250                 t-aq-archive-updated $suite $p
251
252                 >$tmp/aq/package.new.$p
253                 t-aq-archive-updated new $p
254
255                 ln -sf $suite $tmp/aq/dsc_in_suite/$sname
256
257                 cat <<END >>$tmp/aq/suites
258 $jsondelim
259    {
260       "archive" : "ftp-master",
261       "codename" : "$suite",
262       "components" : [
263          "main",
264          "contrib",
265          "non-free"
266       ],
267       "name" : "$sname",
268       "dakname" : "$sname"
269 END
270
271                 jsondelim="   },"
272
273         done
274         cat <<END >>$tmp/aq/suites
275     }
276 ]
277 END
278 }
279
280 t-aq-archive-updated () {
281         local suite=$1
282         local p=$2
283         local suitedir=$tmp/aq/dsc_in_suite/$suite
284         mkdir -p $suitedir
285         perl <$tmp/aq/package.$suite.$p >$suitedir/$p -wne '
286                 use JSON;
287                 use strict;
288                 our @v;
289                 m{^(\S+) (\w+) ([^ \t/]+)/(\S+)} or die;
290                 push @v, {
291                         "version" => "$1",
292                         "sha256sum" => "$2",
293                         "component" => "$3",
294                         "filename" => "$4",
295                 };
296                 END {
297                         my $json = JSON->new->canonical();
298                         print $json->encode(\@v) or die $!;
299                 }
300         '
301 }
302
303 t-archive-process-incoming () {
304         local suite=$1
305         mv $tmp/incoming/${p}_* $tmp/mirror/pool/main/
306         t-archive-query "$suite"
307 }
308
309 t-archive-query () {
310         local suite=${1-sid}
311         local dscf=main/${p}_${v}.dsc
312         t-archive-query-$t_archive_method "$suite" "$p" "$v" "$dscf"
313 }
314 t-archive-query-aq () {
315         local suite=$1
316         local p=$2
317         local v=$3
318         local dscf=$4
319         local sha; sha=`sha256sum <$tmp/mirror/pool/$dscf`
320         echo "${v} ${sha%  -} $dscf" >>$tmp/aq/package.$suite.${p}
321         t-aq-archive-updated $suite $p
322 }
323
324 t-archive () {
325         t-archive-none $1
326         v=$2
327         local dscf=${p}_$2.dsc
328         rm -f $tmp/mirror/pool/main/${p}_*
329         ln $troot/pkg-srcs/${p}_${2%-*}* $tmp/mirror/pool/main/
330         t-archive-query $suite
331         rm -rf $tmp/extract
332         mkdir $tmp/extract
333         (set -e; cd $tmp/extract; dpkg-source -x ../mirror/pool/main/$dscf)
334 }
335
336 t-git-dir-time-passes () {
337         touch -d 'last year' $dgitrepo
338 }
339
340 t-git-dir-check () {
341         local gitdir=$dgitrepo
342         case "$1" in
343         enoent)
344                 if test -e "$gitdir"; then fail "$gitdir exists"; fi
345                 return
346                 ;;
347         public) wantstat='7[75]5' ;;
348         secret) wantstat='7[70]0' ;;
349         *)      fail "$1 t-git-dir-check ?" ;;
350         esac
351         gotstat=`stat -c%a $gitdir`
352         case "$gotstat" in
353         *$wantstat) return ;;
354         *)      fail "$gitdir has mode $gotstat, expected $wantstat" ;;
355         esac
356 }
357
358 t-expect-fsck-fail () {
359         echo >>$tmp/fsck.expected-errors "$1"
360 }
361
362 t-git-fsck () {
363         set +e
364         LC_MESSAGES=C git fsck --no-dangling --strict 2>&1 \
365                 | tee dgit-test-fsck.errs
366         ps="${PIPESTATUS[*]}"
367         set -e
368
369         local pats
370         if [ -f $tmp/fsck.expected-errors ]; then
371                 pats=(-w -f $tmp/fsck.expected-errors)
372         else
373                 test "$ps" = "0 0"
374         fi
375         pats+=(-e 'notice: HEAD points to an unborn branch')
376         pats+=(-e 'notice: No default references')
377
378         set +e
379         grep -v "${pats[@]}" dgit-test-fsck.errs
380         rc=$?
381         set -e
382         case $rc in
383         1) ;; # no unexpected errors
384         0) fail "unexpected messages from git-fsck" ;;
385         *) fail "grep of git-fsck failed" ;;
386         esac
387 }
388
389 t-fscks () {
390         (
391         shopt -s nullglob
392         for d in $tmp/*/.git $tmp/git/*.git; do
393                 cd "${d%/.git}"
394                 t-git-fsck
395         done
396         )
397 }
398
399 t-ok () {
400         : '========================================'
401         t-fscks
402         echo ok.
403 }
404
405 t-rm-dput-dropping () {
406         rm -f $tmp/${p}_${v}_*.upload
407 }
408
409 t-dgit () {
410         local dgit=${DGIT_TEST-dgit}
411         pwd >&2
412         : '
413 {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{'
414         $dgit --dgit=$dgit --dget:-u --dput:--config=$tmp/dput.cf \
415  ${dgit_config_debian_alias-"--config-lookup-explode=dgit-distro.debian.alias-canon"} \
416                 ${distro+${distro:+-d}}${distro--dtest-dummy} \
417                 $DGIT_TEST_OPTS $DGIT_TEST_DEBUG \
418                 -k39B13D8A $t_dgit_xopts "$@"
419         : '}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
420 '
421 }
422
423 t-dgit-manpage () {
424         local section=$1
425         local page=$2
426         (export LC_ALL=C.UTF-8
427          if [ "$DGIT_TEST_INTREE" ]; then
428                 make -C $DGIT_TEST_INTREE $page.$section.view
429          else
430                 man $section $page
431          fi)
432 }
433
434 t-diff-nogit () {
435         diff --exclude=.git --exclude=.pc -ruN $*
436 }
437
438 t-files-notexist () {
439         local f
440         for f in "$@"; do
441                 if [ -e $f ]; then
442                         fail "$f exists!"
443                 fi
444         done
445 }
446
447 t-cloned-fetched-good () {
448         t-diff-nogit ../extract/$p-${v%-*} .
449         t-clean-on-branch dgit/sid
450         t-refs-same-start
451         t-refs-same \
452                 refs/heads/dgit/sid \
453                 refs/remotes/dgit/dgit/sid
454         t-refs-notexist refs/dgit/unstable refs/remotes/dgit/dgit/unstable
455 }
456
457 t-output () {
458         printf "%s${1:+\n}" "$1" >$tmp/t.want
459         shift
460         "$@" >$tmp/t.got
461         diff $tmp/t.want $tmp/t.got
462 }
463
464 t-clean-on-branch () {
465         t-output "## $1" git status -b --porcelain
466 }
467
468 t-setup-done () {
469         local savevars=$1
470         local savedirs=$2
471         local importeval=$3
472
473         local import=IMPORT.${0##*/}
474         exec 4>$tmp/$import.new
475
476         local vn
477         for vn in $savevars; do
478                 perl >&4 -I. -MDebian::Dgit -e '
479                         printf "%s=%s\n", $ARGV[0], shellquote $ARGV[1]
480                 ' $vn "$(eval "printf '%s\n' \"\$$vn\"")"
481         done
482
483         (set -e; cd $tmp; tar cf $import.tar $savedirs)
484
485         printf >&4 "\n%s\n" "$importeval"
486
487         mv -f $tmp/$import.new $tmp/$import
488 }
489
490 t-setup-import () {
491         local setupname=$1
492
493         local setupsrc
494         local lock
495         if [ "x$tmpbase" = x ]; then
496                 # ADTTMP was set on entry to tests/lib, so we
497                 # are not sharing tmp area between tests
498                 setupsrc="$tmp"
499                 lock="$tmp/.dummy.lock"
500         else
501                 setupsrc="$tmpbase/$setupname"
502                 lock="$setupsrc.lock"
503         fi
504
505         local simport="$setupsrc/IMPORT.$setupname"
506
507         if ! [ -e "$simport" ]; then
508                 with-lock-ex -w "$lock" \
509                 xargs -0 -a $tmp/.save-env \
510                 bash -xec '
511                         cd "$1"; shift
512                         setupname="$1"; shift
513                         simport="$1"; shift
514                         if [ -e "$simport" ]; then exit 0; fi
515                         env - "$@" \
516                         "tests/setup/$setupname"
517                 ' x "$root" "$setupname" "$simport"
518         fi
519
520         if [ "x$setupsrc" != "x$tmp" ]; then
521                 (set -e; cd $tmp; tar xf "$simport.tar")
522         fi
523
524         . "$simport"
525 }
526
527 t-git-get-ref-exact () {
528         local ref=$1
529         # does not dereference, unlike t-git-get-ref
530         case "$ref" in
531         refs/*) ;;
532         *) fail "t-git-get-ref-exact bad $ref" ;;
533         esac
534         git for-each-ref --format='%(objectname)' "[r]efs/${ref#refs/}"
535 }
536
537 t-git-get-ref () {
538         local ref=$1
539         case "$ref" in
540         refs/*) ;;
541         *) fail "t-git-get-ref bad $ref" ;;
542         esac
543         (git show-ref -d $1 || test $? = 1) | perl -ne '
544                 $x = $1 if m#^(\w+) \Q'$1'\E(?:\^\{\})?$#;
545                 END { print "$x\n" if length $x; }
546         '
547 }
548
549 t-ref-same-exact () {
550         local name="$1"
551         local val; val=`t-git-get-ref-exact $name`
552         t-ref-same-val "$name" $val
553 }
554
555 t-ref-same () {
556         local name="$1"
557         local val; val=`t-git-get-ref $name`
558         t-ref-same-val "$name" $val
559 }
560
561 t-ref-head () {
562         local val; val=`git rev-parse HEAD`
563         t-ref-same-val HEAD $val
564 }
565
566 t-ref-same-val () {
567         local name="$1"
568         local val=$2
569         case "${t_ref_val-unset}" in
570         unset)          ;;
571         "$val")         ;;
572         *)              fail "ref varies: ($name)\
573  ${val:-nothing} != ${t_ref_val:-nothing} (${t_ref_names[*]})" ;;
574         esac
575         t_ref_val="$val"
576         t_ref_names+=("$name")
577 }
578
579 t-refs-same-start () {
580         unset t_ref_val
581         t_ref_names=()
582 }
583
584 t-refs-same () {
585         local g
586         for g in $*; do
587                 t-ref-same $g
588         done
589 }
590
591 t-refs-notexist () {
592         local val
593         for g in $*; do
594                 val=`t-git-get-ref $g`
595                 if [ "x$val" != x ]; then
596                         fail "ref $g unexpectedly exists ($val)"
597                 fi
598         done
599 }
600
601 t-v-tag () {
602         echo refs/tags/$tagpfx/${v//\~/_}
603 }
604
605 t-format-ref () {
606         git log -n1 --pretty=format:"$1" "$2"
607 }
608
609 t-sametree-parent () {
610         local ref=$1
611         local parent
612         local ctree; ctree=$(t-format-ref '%T' "$ref")
613         while :; do
614                 local psame=''
615                 for parent in $(t-format-ref '%P' "$ref"); do
616                         local ptree; ptree=$(t-format-ref '%T' "$parent")
617                         if [ "x$ptree" = "x$ctree" ]; then
618                                 psame+=" $parent"
619                         fi
620                 done
621                 case "$psame" in ""|" * *") break ;; esac
622                 ref="${psame# }"
623         done
624         echo "$ref"
625 }
626
627 t-check-pushed-master () {
628         local master; master=`t-git-get-ref refs/heads/master`
629         if [ x$master = x$t_ref_val ]; then return; fi
630         if [ x$master = x ]; then fail "failed to push master"; fi
631         # didn't update master, it must be not FF
632         local mbase; mbase=`t-git-merge-base $master $t_ref_val`
633         if [ x$mbase = x$master ]; then fail "failed to ff master"; fi
634 }
635
636 t-pushed-good () {
637         local branch=$1
638         local suite=${2:-sid}
639         t-refs-same \
640                 refs/heads/$branch
641         t-pushed-good-core
642 }
643         
644 t-pushed-good-core () {
645         t-ref-dsc-dgit
646         t-refs-same \
647                 `t-v-tag` \
648                 refs/remotes/dgit/dgit/$suite
649         t-refs-notexist \
650                 refs/heads/dgit/unstable \
651                 refs/remotes/dgit/dgit/unstable
652         (set -e; cd $dgitrepo
653          t-refs-same \
654                 refs/dgit/$suite \
655                 `t-v-tag`
656          ${t_check_pushed_master:- : NOT-DRS-NO-CHECK-PUSHED-MASTER}
657          t-refs-notexist \
658                 refs/dgit/unstable
659         )
660         git verify-tag `t-v-tag`
661 }
662
663 t-splitbrain-pushed-good--unpack () {
664         cd $tmp
665         rm -rf t-unpack
666         mkdir t-unpack
667         cd t-unpack
668         ln -s $tmp/mirror/pool/main/*.orig*.tar* .
669         ln -s $tmp/incoming/*.orig*.tar* . ||:
670         ln -s $incoming_dsc .
671         ln -s ${incoming_dsc/.dsc/.debian.tar}* .
672         dpkg-source "$@" -x *.dsc
673         cd */.
674         git init
675         git fetch ../../$p "refs/tags/*:refs/tags/*"
676 }
677
678 t-splitbrain-pushed-good--checkprep () {
679         git add -Af .
680         git rm --cached -r --ignore-unmatch .pc
681 }
682
683 t-splitbrain-pushed-good--checkdiff () {
684         local tag=$1
685         t-splitbrain-pushed-good--checkprep
686         t-output "" git diff --stat --cached $tag
687 }
688
689 t-splitbrain-pushed-good-start () {
690         dep14tag=refs/tags/test-dummy/${v//\~/_}
691         dgittag=$(t-v-tag)
692         t-output "" git status --porcelain
693         t-ref-head
694         t-refs-same $dep14tag
695         (set -e; cd $dgitrepo; t-refs-same $dep14tag)
696         git merge-base --is-ancestor $dep14tag $dgittag
697
698         t-refs-same-start
699         t-ref-same refs/heads/split.p
700         case "$(t-git-get-ref refs/heads/split.b)" in
701         "$t_ref_val") ;;
702         "$(git rev-parse refs/heads/split.p^0)") ;;
703         "$(git rev-parse refs/heads/split.p^1)") ;;
704         *) fail 'bad b/p' ;;
705         esac
706         t-pushed-good-core
707
708         t-incoming-dsc
709
710         t-splitbrain-pushed-good--unpack
711         t-splitbrain-pushed-good--checkdiff $dgittag
712 }
713 t-splitbrain-pushed-good-end-made-dep14 () {
714         t-splitbrain-pushed-good--checkdiff $dep14tag
715         cd $tmp/$p
716 }
717
718 t-splitbrain-rm-gitignore-patch () {
719         perl -i -pe '
720                 next unless $_ eq "auto-gitignore\n";
721                 die if $counter++;
722                 chomp;
723                 rename "debian/patches/$_", "../t-auto-gitignore" or die $!;
724                 $_ = "";
725         ' debian/patches/series
726 }
727
728 t-gbp-pushed-good () {
729         local suite=${1:-sid}
730         t-splitbrain-pushed-good-start
731
732         # Right, now we want to check that the maintainer tree and
733         # the dgit tree differ in exactly the ways we expect.  We
734         # achieve this by trying to reconstruct the maintainer tree
735         # from the dgit tree.
736
737         # So, unpack it withut the patches applied
738         t-splitbrain-pushed-good--unpack --skip-patches
739
740         # dgit might have added a .gitignore patch, which we need to
741         # drop and remove
742         t-splitbrain-rm-gitignore-patch
743
744         # Now the result should differ only in non-debian/ .gitignores
745         t-splitbrain-pushed-good--checkprep
746         git diff --cached --name-only $dep14tag >../changed
747         perl -ne '
748                 next if !m#^debian/# && m#(^|/)\.gitignore#;
749                 die "$_ mismatch";
750         ' <../changed
751
752         # If we actually apply the gitignore patch by hand, it
753         # should be perfect:
754         if [ -f ../t-auto-gitignore ]; then
755                 patch --backup-if-mismatch -p1 -u <../t-auto-gitignore
756         fi
757
758         t-splitbrain-pushed-good-end-made-dep14
759 }
760
761 t-unapplied-pushed-good () {
762         t-splitbrain-pushed-good-start
763         t-splitbrain-pushed-good--unpack --skip-patches
764         t-splitbrain-pushed-good-end-made-dep14
765 }
766
767 t-dpm-pushed-good () {
768         t-splitbrain-pushed-good-start
769         t-splitbrain-pushed-good--unpack
770         t-splitbrain-rm-gitignore-patch
771         t-splitbrain-pushed-good-end-made-dep14
772 }
773
774 t-commit-build-push-expect-log () {
775         local msg=$1
776         local mpat=$2
777         t-commit "$msg"
778         t-dgit build
779         LC_MESSAGES=C \
780         t-dgit push --new 2>&1 |tee $tmp/push.log
781         t-grep-mpat "$mpat" $tmp/push.log
782 }
783
784 t-822-field () {
785         local file=$1
786         local field=$2
787         perl -e '
788                 use Dpkg::Control::Hash;
789                 my $h = new Dpkg::Control::Hash allow_pgp=>1;
790                 $h->parse(\*STDIN,"'"$file"'");
791                 my $val = $h->{"'$field'"},"\n";
792                 die "'"$file $field"'" unless defined $val;
793                 print $val,"\n";
794         ' <$file
795 }
796
797 t-defdistro () {
798         export DGIT_TEST_DISTRO=''
799         distro=''
800         t-git-config dgit-suite.unstable.distro test-dummy
801 }
802
803 t-stunt-envvar () {
804         local var=$1
805         local tstunt=$2
806         eval '
807                 case "$'$var'" in
808                 "$tstunt:"*)    ;;
809                 *":$tstunt:"*)  ;;
810                 "")             '$var'="$tstunt" ;;
811                 *)              '$var'="$tstunt:$'$var'" ;;
812                 esac
813                 export '$var'
814         '
815 }
816
817 t-tstunt--save-real () {
818         local f="$1"
819         case "$f" in
820         */*) return ;;
821         esac
822
823         local rc
824         local real
825         set +e
826         real=$(
827                 p=":$PATH:"
828                 p="${p/:"$tmp/tstunt":/:}"
829                 p="${p%:}"
830                 p="${p#:}"
831                 PATH="$p"
832                 type -p "$f"
833         )
834         rc=$?
835         set -e
836
837         case $rc in
838         1)      return ;;
839         0)      ;;
840         *)      fail "did not find $f on PATH $PATH" ;;
841         esac
842
843         local varname=${f//[^_0-9a-zA-Z]/_}
844         varname=DGIT_TEST_REAL_${varname^^}
845
846         eval "
847                 : \${$varname:=\$real}
848                 export $varname
849         "
850 }
851
852 t-tstunt () {
853         local tstunt=$tmp/tstunt
854         t-stunt-envvar PATH $tstunt
855         t-stunt-envvar PERLLIB $tstunt
856         local f
857         for f in "$@"; do
858                 t-tstunt--save-real $f
859                 f="./$f"
860                 local d="$tstunt/${f%/*}"
861                 mkdir -p $d
862                 ln -sf "$troot/tstunt/$f" "$d"/.
863         done
864 }
865
866 t-tstunt-parsechangelog () {
867         t-tstunt dpkg-parsechangelog Dpkg/Changelog/Parse.pm
868 }
869
870 t-tstunt-lintian () {
871         t-tstunt lintian
872 }
873
874 t-tstunt-debuild () {
875         t-tstunt debuild
876 }
877
878 t-incoming-dsc () {
879         local dsc=${p}_${v}.dsc
880         incoming_dsc=$tmp/incoming/$dsc
881 }
882
883 t-ref-dsc-dgit () {
884         t-incoming-dsc
885         local val; val=`t-822-field $incoming_dsc Dgit`
886         val=$( perl -e '
887                 $_=shift @ARGV;
888                 die "Dgit $_ ?" unless m/^\w+\b/;
889                 print $&,"\n" or die $!;
890         ' "$val")
891         t-ref-same-val $incoming_dsc "$val"
892 }
893
894 t-apply-diff () {
895         local v1=$1
896         local v2=$2
897         (cd $troot/pkg-srcs;
898          debdiff ${p}_${v1}.dsc ${p}_${v2}.dsc || test $? = 1) \
899          | patch -p1 -u
900 }
901
902 t-gbp-unapplied-pq2qc () {
903         # does `gbp pq export'
904         # commits the resulting debian/patches on  qc/BRANCH
905         # leaves us on qc/BRANCH (eg "qc/quilt-tip"))
906         # qc/BRANCH is not fast-forwarding
907
908         gbp pq export
909
910         branch=`git symbolic-ref HEAD`
911         branch=${branch#refs/heads/}
912
913         case "$branch" in
914         */*) fail "unexpected branch $branch" ;;
915         esac
916
917         git branch -f qc/$branch
918         git checkout qc/$branch
919         git add debian/patches
920         git commit -m 'Commit patch queue'
921 }
922
923 t-git-pseudo-merge () {
924         # like   git merge -s ours
925         if [ ! "$git_pseuomerge_opts" ]; then
926                 if git merge --help \
927                  | grep -q allow-unrelated-histories; then
928                         git_pseuomerge_opts='--allow-unrelated-histories'
929                 fi
930                 git_pseuomerge_opts+=' -s ours'
931         fi
932         git merge $git_pseuomerge_opts "$@"
933 }
934
935 t-gbp-example-prep-no-ff () {
936         t-tstunt-parsechangelog
937         t-archive example 1.0-1
938         t-git-none
939         t-worktree 1.0
940
941         cd example
942
943         t-dgit fetch
944
945         git checkout -b patch-queue/quilt-tip-2 patch-queue/quilt-tip
946         gbp pq rebase
947
948         echo '/* some comment */' >>src.c
949         git add src.c
950         git commit -m 'Add a comment to an upstream file'
951
952         t-gbp-unapplied-pq2qc
953
954         t-commit 'some updates' 1.0-2
955 }
956
957 t-gbp-example-prep () {
958         t-gbp-example-prep-no-ff
959
960         t-git-pseudo-merge \
961                 -m 'Pseudo-merge to make descendant of archive' \
962                 remotes/dgit/dgit/sid
963 }
964
965 t-make-badcommit () {
966         badcommit=$(
967                 git cat-file commit HEAD | \
968                 perl -pe 's/^committer /commiter /' | \
969                 git hash-object -w -t commit --stdin
970         )
971         t-expect-fsck-fail $badcommit
972 }
973
974 t-commit () {
975         local msg=$1
976         v=${2:-${majorv:-1}.$revision}
977         dch --force-distribution -v$v --distribution ${3:-unstable} "$1"
978         git add debian/changelog
979         debcommit
980         revision=$(( ${revision-0} + 1 ))
981 }
982
983 t-git-config () {
984         git config --global "$@"
985 }
986
987 t-drs () {
988  t-git-config dgit-distro.test-dummy.git-url "ext::$troot/drs-git-ext %S "
989  t-git-config dgit-distro.test-dummy.git-check true
990  t-git-config dgit-distro.test-dummy.git-create true
991  t-git-config dgit-distro.test-dummy.dgit-tag-format new,old,maint
992         cp $troot/gnupg/{dd.gpg,dm.gpg,dm.txt} $tmp/.
993         cp $troot/suites $tmp/.
994         cp $troot/suites $tmp/suites-master
995
996         export t_check_pushed_master=t-check-pushed-master
997
998         drs_dispatch=$tmp/distro=test-dummy
999         mkdir $drs_dispatch
1000
1001         if [ "x$DGIT_TEST_INTREE" != x ]; then
1002                 ln -sf "$DGIT_TEST_INTREE" $drs_dispatch/dgit-live
1003         fi
1004
1005         ln -sf $tmp/git $drs_dispatch/repos
1006         ln -sf $tmp/suites $tmp/suites-master $tmp/dm.txt $drs_dispatch/
1007         mkdir -p $drs_dispatch/keyrings
1008         ln -sf $tmp/dd.gpg $drs_dispatch/keyrings/debian-keyring.gpg
1009         ln -sf $tmp/dm.gpg $drs_dispatch/keyrings/debian-maintainers.gpg
1010         ln -sf /bin/true $drs_dispatch/policy-hook
1011 }
1012
1013 t-newtag () {
1014  export tagpfx=archive/test-dummy
1015  t-git-config dgit-distro.test-dummy.dgit-tag-format new,maint
1016 }
1017 t-oldtag () {
1018  export tagpfx=test-dummy
1019  t-git-config dgit-distro.test-dummy.dgit-tag-format old
1020 }
1021
1022 t-dsd () {
1023         t-drs
1024  t-git-config dgit-distro.test-dummy.ssh "$troot/dsd-ssh"
1025  t-git-config dgit-distro.test-dummy.git-check ssh-cmd
1026  t-git-config dgit-distro.test-dummy.git-create true
1027  t-git-config dgit-distro.test-dummy.git-url \
1028                 "ext::$troot/dsd-ssh X %S /dgit/test-dummy/repos"
1029
1030  t-git-config dgit-distro.test-dummy.diverts.drs /drs
1031  t-git-config dgit-distro.test-dummy/drs.ssh "$troot/ssh"
1032  t-git-config dgit-distro.test-dummy/drs.git-url $tmp/git
1033  t-git-config dgit-distro.test-dummy/drs.git-check ssh-cmd
1034  t-git-config dgit-distro.test-dummy/drs.git-create ssh-cmd
1035
1036         echo 'no-such-package* drs' >$drs_dispatch/diverts
1037 }
1038
1039 t-policy-admin () {
1040         : '(((((((((((((((((((((((((((((((((((((((('
1041         ${DGIT_INFRA_PFX}dgit-repos-admin-debian --repos $tmp/git "$@"
1042         : '))))))))))))))))))))))))))))))))))))))))'
1043 }
1044
1045 t-policy-nonexist () {
1046         ln -sf no-such-file-or-directory $drs_dispatch/policy-hook
1047 }
1048
1049 t-make-hook-link () {
1050         local hook=$1 # in infra/
1051         local linkpath=$2
1052         hook=${DGIT_INFRA_PFX}$hook
1053         case $hook in
1054         */*)    ;;
1055         *)      hook=`type -P $hook` ;;
1056         esac
1057         ln -sf "$hook" $linkpath
1058 }
1059
1060 t-policy () {
1061         local policyhook=$1
1062         t-make-hook-link $policyhook $drs_dispatch/policy-hook
1063 }
1064
1065 t-debpolicy () {
1066         t-dsd
1067         t-policy dgit-repos-policy-debian
1068
1069         mkdir $tmp/git
1070         t-policy-admin create-db
1071 }
1072
1073 t-policy-periodic () {
1074         : '(((((((((((((((((((((((((((((((((((((((('
1075         ${DGIT_REPOS_SERVER_TEST-dgit-repos-server} \
1076                 test-dummy $drs_dispatch '' --cron
1077         : '))))))))))))))))))))))))))))))))))))))))'
1078 }
1079
1080 t-restrict () {
1081         local restriction=$1
1082         (cd $root; t-restriction-$restriction >&2)
1083 }
1084
1085 t-dependencies () {
1086         : "Hopefully installed: $*"
1087 }
1088
1089 t-chain-test () {
1090         local ct=$1
1091         local d=${0%/*}
1092         cd $root
1093         export DGIT_TEST_TESTNAME="$testname"
1094         export DGIT_TEST_TMPBASE="$tmpbase"
1095         export ADTTMP=$tmp
1096         exec "$d/$ct"
1097 }       
1098
1099 t-alt-test () {
1100         local t=${0##*/}
1101         t-${t%%-*}
1102         t-chain-test "${t#*-}"
1103 }
1104
1105 t-git-config dgit.default.old-dsc-distro test-dummy
1106
1107 case "$0" in
1108 */gnupg) ;;
1109 *)      t-setup-import gnupg    ;;
1110 esac