summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile14
-rwxr-xr-xtests/adhoc51
-rwxr-xr-xtests/drs-git-ext6
-rwxr-xr-xtests/dsd-ssh18
-rwxr-xr-xtests/enumerate-tests109
-rw-r--r--tests/lib943
-rw-r--r--tests/lib-build-modes235
-rw-r--r--tests/lib-core38
-rw-r--r--tests/lib-import-chk97
-rw-r--r--tests/lib-mirror42
-rw-r--r--tests/lib-orig-include-exclude67
-rw-r--r--tests/lib-reprepro97
-rw-r--r--tests/lib-restricts22
-rw-r--r--tests/pkg-srcs/example_1.0-1+absurd.debian.tar.xzbin0 -> 1416 bytes
-rw-r--r--tests/pkg-srcs/example_1.0-1+absurd.dsc22
-rw-r--r--tests/pkg-srcs/example_1.0-1.100.debian.tar.xzbin0 -> 2108 bytes
-rw-r--r--tests/pkg-srcs/example_1.0-1.100.dsc22
-rw-r--r--tests/pkg-srcs/example_1.0-1.debian.tar.xzbin0 -> 1304 bytes
-rw-r--r--tests/pkg-srcs/example_1.0-1.dsc22
-rw-r--r--tests/pkg-srcs/example_1.0.orig-docs.tar.gzbin0 -> 236 bytes
-rw-r--r--tests/pkg-srcs/example_1.0.orig.tar.gzbin0 -> 373 bytes
-rw-r--r--tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.debian.tar.gzbin0 -> 5182 bytes
-rw-r--r--tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.dsc22
-rw-r--r--tests/pkg-srcs/sunxi-tools_1.2.orig.tar.gzbin0 -> 35076 bytes
-rwxr-xr-xtests/run-all28
-rwxr-xr-xtests/setup/examplegit53
-rwxr-xr-xtests/setup/gnupg30
-rwxr-xr-xtests/tartree-edit145
-rwxr-xr-xtests/tests/absurd-gitapply17
-rwxr-xr-xtests/tests/badcommit-rewrite47
-rwxr-xr-xtests/tests/build-modes35
-rwxr-xr-xtests/tests/build-modes-asplit5
-rwxr-xr-xtests/tests/build-modes-gbp39
-rwxr-xr-xtests/tests/build-modes-gbp-asplit5
-rwxr-xr-xtests/tests/build-modes-sbuild18
-rwxr-xr-xtests/tests/clone-clogsigpipe10
-rwxr-xr-xtests/tests/clone-gitnosuite11
-rwxr-xr-xtests/tests/clone-nogit2
-rwxr-xr-xtests/tests/clone-reprepro33
-rwxr-xr-xtests/tests/debpolicy-dbretry67
-rwxr-xr-xtests/tests/debpolicy-newreject121
-rwxr-xr-xtests/tests/debpolicy-quilt-gbp4
-rwxr-xr-xtests/tests/defdistro-dsd-clone-drs14
-rwxr-xr-xtests/tests/defdistro-mirror5
-rwxr-xr-xtests/tests/defdistro-rpush4
-rwxr-xr-xtests/tests/defdistro-setup19
-rwxr-xr-xtests/tests/distropatches-reject81
-rwxr-xr-xtests/tests/downstream-gitless111
-rwxr-xr-xtests/tests/drs-clone-nogit2
-rwxr-xr-xtests/tests/drs-push-masterupdate50
-rwxr-xr-xtests/tests/drs-push-rejects79
-rwxr-xr-xtests/tests/dsd-clone-drs17
-rwxr-xr-xtests/tests/dsd-clone-nogit4
-rwxr-xr-xtests/tests/dsd-divert7
-rwxr-xr-xtests/tests/fetch-localgitonly6
-rwxr-xr-xtests/tests/fetch-somegit-notlast2
-rwxr-xr-xtests/tests/gbp-orig77
-rwxr-xr-xtests/tests/gitattributes256
-rwxr-xr-xtests/tests/gitconfig38
-rwxr-xr-xtests/tests/import-dsc100
-rwxr-xr-xtests/tests/import-maintmangle41
-rwxr-xr-xtests/tests/import-native69
-rwxr-xr-xtests/tests/import-nonnative17
-rwxr-xr-xtests/tests/import-tarbomb49
-rwxr-xr-xtests/tests/inarchivecopy79
-rwxr-xr-xtests/tests/mirror80
-rwxr-xr-xtests/tests/mirror-debnewgit26
-rwxr-xr-xtests/tests/mirror-private30
-rwxr-xr-xtests/tests/mismatches-contents24
-rwxr-xr-xtests/tests/mismatches-dscchanges34
-rwxr-xr-xtests/tests/multisuite57
-rwxr-xr-xtests/tests/newtag-clone-nogit4
-rwxr-xr-xtests/tests/oldnewtagalt25
-rwxr-xr-xtests/tests/oldtag-clone-nogit4
-rwxr-xr-xtests/tests/orig-include-exclude21
-rwxr-xr-xtests/tests/orig-include-exclude-chkquery33
-rwxr-xr-xtests/tests/overwrite-chkclog50
-rwxr-xr-xtests/tests/overwrite-junk22
-rwxr-xr-xtests/tests/overwrite-splitbrains27
-rwxr-xr-xtests/tests/overwrite-version20
-rwxr-xr-xtests/tests/protocol-compat83
-rwxr-xr-xtests/tests/push-buildproductsdir2
-rwxr-xr-xtests/tests/push-newpackage16
-rwxr-xr-xtests/tests/push-nextdgit2
-rwxr-xr-xtests/tests/quilt67
-rwxr-xr-xtests/tests/quilt-gbp61
-rwxr-xr-xtests/tests/quilt-gbp-build-modes13
-rwxr-xr-xtests/tests/quilt-gbp-build-modes-sbuild12
-rwxr-xr-xtests/tests/quilt-singlepatch39
-rwxr-xr-xtests/tests/quilt-splitbrains140
-rwxr-xr-xtests/tests/quilt-useremail27
-rwxr-xr-xtests/tests/rpush2
-rwxr-xr-xtests/tests/spelling16
-rwxr-xr-xtests/tests/tag-updates37
-rwxr-xr-xtests/tests/test-list-uptodate11
-rwxr-xr-xtests/tests/trustingpolicy-replay85
-rwxr-xr-xtests/tests/unrepresentable52
-rwxr-xr-xtests/tests/version-opt32
-rw-r--r--tests/tstunt/Dpkg/Changelog/Parse.pm71
-rwxr-xr-xtests/tstunt/debuild4
-rwxr-xr-xtests/tstunt/dpkg-parsechangelog78
-rwxr-xr-xtests/tstunt/gpg6
-rwxr-xr-xtests/tstunt/gpg-agent6
-rwxr-xr-xtests/tstunt/lintian3
-rwxr-xr-xtests/using-intree17
-rw-r--r--tests/worktrees/example_1.0.tarbin0 -> 122880 bytes
-rw-r--r--tests/worktrees/pari-extra_3-1.tarbin92160 -> 81920 bytes
-rw-r--r--tests/worktrees/pari-extra_drs.tarbin153600 -> 153600 bytes
-rw-r--r--tests/worktrees/ruby-rails-3.2_test.tarbin133120 -> 215040 bytes
109 files changed, 4833 insertions, 130 deletions
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..5bd3eee
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,14 @@
+# usage: tests/using-intree make -f tests/Makefile
+# (optionally setting TESTSCRIPTS='tests/tests/foo tests/tests/bar')
+
+TESTSCRIPTS ?= $(shell tests/enumerate-tests)
+TESTNAMES := $(notdir $(TESTSCRIPTS))
+
+all: $(foreach t,$(TESTNAMES),tests/tmp/$t.ok)
+ @echo "ALL PASSED"
+
+tests/tmp:
+ mkdir -p $@
+
+tests/tmp/%.ok: tests/tmp
+ tests/tests/$* >tests/tmp/$*.log 2>&1
diff --git a/tests/adhoc b/tests/adhoc
new file mode 100755
index 0000000..b45251f
--- /dev/null
+++ b/tests/adhoc
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# usage:
+# after tests/tests/some-test has been run (and maybe failed)
+# cd tests/tmp/some-test/blah
+# ../../adhoc ../../../dgit some options
+# or
+# after tests/tests/some-test has been run (and maybe failed)
+# cd tests/tmp/some-test/blah
+# ../../adhoc some rune run by some piece of infrastructure
+#
+# effects:
+# directly sets the env variables which arrange to use
+# programs etc. from the working tree
+
+ourname=adhoc
+
+case $0 in
+*/$ourname)
+ : ${DGIT_TEST_INTREE:=$(realpath "${0%/$ourname}/..")}
+ ;;
+*)
+ echo >&2 "$ourname must be invoked as .../$ourname not $0"
+ exit 127
+ ;;
+esac
+
+export DGIT_TEST_INTREE
+
+. $DGIT_TEST_INTREE/tests/lib-core
+
+t-set-intree
+
+pwd=$(realpath "$(pwd)")
+basis=$DGIT_TEST_INTREE/tests/tmp
+case "$pwd" in
+"$basis" | "$basis"/*)
+ testname=${pwd/"$basis/"/}
+ testname=${testname%%/*}
+ tmp="$basis/$testname"
+ ;;
+*)
+ fail "$ourname pwd must be inside some test (in $basis), not $pwd"
+ ;;
+esac
+
+export ADTTMP=$tmp
+
+t-set-using-tmp
+
+exec "$@"
diff --git a/tests/drs-git-ext b/tests/drs-git-ext
index 52e7817..ad27c9b 100755
--- a/tests/drs-git-ext
+++ b/tests/drs-git-ext
@@ -2,12 +2,14 @@
set -e
tmp=$DGIT_TEST_TMP
+: ${DGIT_DRS_DEBUG:=1}
+export DGIT_DRS_DEBUG
echo >&2 '(((((((((((((((((((((((((((((((((((((((('
set -x
export SSH_ORIGINAL_COMMAND="$*"
${DGIT_REPOS_SERVER_TEST-dgit-repos-server} \
- $tmp/suites \
+ test-dummy $tmp/distro=test-dummy \
$tmp/dd.gpg,a:$tmp/dm.gpg,m$tmp/dm.txt \
- $tmp/git \
+ --repos=$tmp/git --suites=$tmp/suites \
--ssh
: '))))))))))))))))))))))))))))))))))))))))'
diff --git a/tests/dsd-ssh b/tests/dsd-ssh
new file mode 100755
index 0000000..d5df5aa
--- /dev/null
+++ b/tests/dsd-ssh
@@ -0,0 +1,18 @@
+#!/bin/sh
+set -e
+
+echo >&2 '(((((((((((((((((((((((((((((((((((((((('
+set -x
+
+tmp=$DGIT_TEST_TMP
+cd /
+userhost="$1"; shift
+export SSH_ORIGINAL_COMMAND="$*"
+
+# undoes PERLLIB so that we rely on dgit-ssh-dispatch setting it
+# we have to compensate with -I so that dgit-ssh-dispatch finds Dgit.pm
+unset PERLLIB
+${DGIT_TEST_INTREE+perl -I}$DGIT_TEST_INTREE \
+${DGIT_SSH_DISPATCH_TEST-dgit-ssh-dispatch} -D $tmp
+
+: '))))))))))))))))))))))))))))))))))))))))'
diff --git a/tests/enumerate-tests b/tests/enumerate-tests
new file mode 100755
index 0000000..2c00f97
--- /dev/null
+++ b/tests/enumerate-tests
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+set -e
+
+. tests/lib-core
+. tests/lib-restricts
+
+mode=$1
+
+test-begin- () {
+ whynots=''
+}
+
+restriction- () {
+ set +e
+ whynot=$(t-restriction-$r)
+ rc=$?
+ whynot="${whynot//
+/ / }"
+ set -e
+ case "$rc.$whynot" in
+ 0.) ;;
+ 1.?*) whynots="$whynots${whynots:+; }$whynot" ;;
+ *) fail "restriction $r for $t gave $rc $whynot !"
+ esac
+}
+
+dependencies- () {
+ :
+}
+
+test-done- () {
+ case "$whynots" in
+ '') echo $t ;;
+ ?*) echo >&2 "SKIP $t $whynots" ;;
+ esac
+}
+
+finish- () {
+ :
+}
+
+test-begin-gencontrol () {
+ restrictions=''
+ dependencies=''
+}
+
+restriction-gencontrol () {
+ restrictions+=" $r"
+}
+
+dependencies-gencontrol () {
+ dependencies+=", $deps"
+}
+
+test-done-gencontrol () {
+ stanza=$(
+ add_Depends="$dependencies" \
+ perl <debian/tests/control.in -wpe '
+ if (/^(\w+):/) {
+ my $h = $1;
+ s{$}{ $ENV{"add_$h"} // "" }e;
+ }
+ '
+ case "$restrictions" in
+ ?*) echo "Restrictions:$restrictions" ;;
+ esac
+ )
+ key=$(printf "%s" "$stanza" | sha256sum)
+ key=${key%% *}
+ eval "
+ stanza_$key=\"\$stanza\"
+ tests_$key+=\" \${t#tests/tests/}\"
+ "
+ keys=" ${keys/ $key /}"
+ keys+=" $key "
+}
+
+finish-gencontrol () {
+ for key in $keys; do
+ eval "
+ stanza=\$stanza_$key
+ tests=\$tests_$key
+ "
+ printf "Tests:%s\n%s\n\n" "$tests" "$stanza"
+ done
+}
+
+seddery () {
+ local seddery=$1
+ sed <$t -n '
+ 20q;
+ /^: t-enumerate-tests-end$/q;
+ '"$seddery"'
+ '
+}
+
+for t in $(run-parts --list tests/tests); do
+ test-begin-$mode
+ for r in $(seddery 's/^t-restrict //p'); do
+ restriction-$mode
+ done
+ for deps in $(seddery 's/^t-dependencies //p'); do
+ dependencies-$mode
+ done
+ test-done-$mode
+done
+
+finish-$mode
diff --git a/tests/lib b/tests/lib
index e17be7f..e7ab334 100644
--- a/tests/lib
+++ b/tests/lib
@@ -2,6 +2,36 @@
exec 2>&1
set -x
+set -o pipefail
+
+. tests/lib-core
+. tests/lib-restricts
+
+t-report-failure () {
+ set +x
+ rc=$1
+ cat <<END >&2
+TEST FAILED
+funcs: ${FUNCNAME[*]}
+lines: ${BASH_LINENO[*]}
+files: ${BASH_SOURCE[*]}
+END
+ exit 16
+}
+
+trap 'test $? = 0 || t-report-failure' EXIT
+
+t-filter-out-git-hyphen-dir
+
+t-set-intree
+
+: ${DGIT_TEST_DEBUG=-D}
+export DGIT_TEST_DEBUG
+
+: ${DGIT_TEST_DISTRO+ ${distro=${DGIT_TEST_DISTRO}}}
+
+export GIT_COMMITTER_DATE='1440253867 +0100'
+export GIT_AUTHOR_DATE='1440253867 +0100'
root=`pwd`
troot=$root/tests
@@ -10,21 +40,25 @@ testname="${DGIT_TEST_TESTNAME-${0##*/}}"
tmp=$ADTTMP
if [ x"$tmp" = x ]; then
mkdir -p tests/tmp
+ tmpbase=$troot/tmp
tmp=tests/tmp/$testname
rm -rf $tmp
mkdir $tmp
+elif [ "x$DGIT_TEST_TMPBASE" != x ]; then
+ tmpbase="$DGIT_TEST_TMPBASE"
fi
cd $tmp
-export HOME=$tmp
tmp=`pwd`
-export DGIT_TEST_DUMMY_DIR=$tmp
+
+t-set-using-tmp
+
+test -f $tmp/.save-env || \
+env -0 >$tmp/.save-env
+
ln -f $troot/ssh ssh
-mkdir -p $tmp/gnupg
-cp $troot/gnupg/* $tmp/gnupg
-chmod go-rw $tmp/gnupg/*
-export GNUPGHOME=$tmp/gnupg
+export DEBCHANGE_VENDOR=dpkg
mkdir -p $tmp/incoming
cat <<END >$tmp/dput.cf
@@ -34,16 +68,97 @@ incoming = $tmp/incoming
run_dinstall = 0
END
-fail () {
- echo >&2 "failed: $*"
- exit 1
+: ${t_archive_method:=aq}
+: ${tagpfx:=archive/test-dummy}
+: ${suitespecs:=sid:unstable}
+
+t-git-next-date () {
+ GIT_COMMITTER_DATE="$(( ${GIT_COMMITTER_DATE%% *} + 1 )) ${GIT_COMMITTER_DATE#* }"
+ GIT_AUTHOR_DATE="$GIT_COMMITTER_DATE"
+}
+
+t-expect-fail () {
+ local mpat="$1"; shift
+
+ set +o pipefail
+ LC_MESSAGES=C "$@" 2>&1 | tee $tmp/t.output
+ local ps="${PIPESTATUS[*]}"
+ set -o pipefail
+
+ case $ps in
+ "0 0") fail "command unexpectedly succeeded (instead of: $mpat)" ;;
+ *" 0") ;;
+ *) fail "tee failed" ;;
+ esac
+
+ t-grep-mpat "$mpat" $tmp/t.output
+}
+
+t-grep-mpat () {
+ local mpat="$1"
+ local file="$2"
+
+ local grepper=fgrep
+ case "$mpat" in
+ [A-Z]:*)
+ case "$mpat" in
+ E:*) grepper=egrep ;;
+ F:*) grepper=fgrep ;;
+ *) fail "bad mpat prefix in $mpat";;
+ esac
+ mpat=${mpat#[A-Z]:}
+ ;;
+ esac
+
+ $grepper -e "$mpat" "$file" ||
+ fail "message not found"
+}
+
+t-expect-push-fail () {
+ local mpat="$1"; shift
+
+ local triedpush; triedpush=`git rev-parse HEAD`
+
+ t-reporefs pre-push
+ t-expect-fail "$mpat" "$@"
+ t-reporefs post-push
+ diff $tmp/show-refs.{pre,post}-push
+
+ t-git-objects-not-present '' $triedpush
+
+ eval "$t_expect_push_fail_hook"
+}
+
+t-git-objects-not-present () {
+ # t-git-objects-not-present GITDIR|'' OBJID [...]
+ # specifying '' means the repo for package $p
+ local gitdir="${1-$dgitrepo}"
+ local obj
+ if ! [ -e "$gitdir" ]; then return; fi
+ for obj in "$@"; do
+ GIT_DIR=$gitdir \
+ t-expect-fail 'unable to find' \
+ git cat-file -t $obj
+ done
+}
+
+t-reporefs () {
+ local whichoutput=$1; shift
+ local whichrepo=${1-$dgitrepo}
+ local outputfile="$tmp/show-refs.$whichoutput"
+ (set -e
+ exec >"$outputfile"
+ if test -d $whichrepo; then
+ cd $whichrepo
+ git show-ref |sort
+ fi)
}
t-untar () {
local tarfile=$1.tar
local edittree=$1.edit
if test -d "$edittree"; then
- cp -al "$edittree"/* .
+ cp -a "$edittree"/* .
else
tar xf "$tarfile"
fi
@@ -54,8 +169,13 @@ t-worktree () {
t-untar $troot/worktrees/${p}_$1
}
-t-git () {
+t-select-package () {
p=$1
+ dgitrepo=$tmp/git/$p.git
+}
+
+t-git () {
+ t-select-package $1
v=$2
mkdir -p $tmp/git
local gs=$troot/git-srcs/${p}_$v.git
@@ -67,56 +187,248 @@ t-git-none () {
(set -e; cd $tmp/git; tar xf $troot/git-template.tar)
}
+t-git-merge-base () {
+ git merge-base $1 $2 || test $? = 1
+}
+
t-has-ancestor () {
- local now=`git rev-parse HEAD`
- local ancestor=`git rev-parse $1^{}`
- local mbase=`git merge-base $ancestor $now`
+ # t-has-ancestor ANCESTOR
+ # (CHILD is implicit, HEAD)
+ local now; now=`git rev-parse HEAD`
+ local ancestor; ancestor=`git rev-parse $1^{}`
+ local mbase; mbase=`t-git-merge-base $ancestor $now`
if [ x$mbase != x$ancestor ]; then
fail "not ff $ancestor..$now, $mbase != $ancestor"
fi
-}
+}
+
+t-has-parent-or-is () {
+ # t-has-parent-or-is CHILD PARENT
+ local child=$1
+ local parent=$2
+ local parents
+ parents=$(git show --pretty=format:' %P %H ' "$child")
+ parent=$(git rev-parse "$parent~0")
+ case "$parents" in
+ *" $parent "*) ;;
+ *) fail "child $child lacks parent $parent" ;;
+ esac
+}
+
+t-prep-newpackage () {
+ t-select-package $1
+ v=$2
+ t-archive-none $p
+ t-git-none
+ t-worktree $v
+ cd $p
+ if ! git show-ref --verify --quiet refs/heads/master; then
+ git branch -m dgit/sid master
+ git remote rm dgit
+ fi
+ cd ..
+}
t-archive-none () {
- p=$1
- mkdir -p $tmp/aq $tmp/mirror
- echo sid >$tmp/aq/suite.unstable
+ t-select-package $1
+ t-archive-none-$t_archive_method
+}
+t-archive-none-aq () {
+ mkdir -p $tmp/aq/dsc_in_suite $tmp/mirror/pool/main
+
+ : >$tmp/aq/suites
+ local jsondelim="["
+
+ local suitespec
+ for suitespec in $suitespecs; do
+ local suite=${suitespec%%:*}
+ local sname=${suitespec#*:}
+
+ >$tmp/aq/package.$suite.$p
+ t-aq-archive-updated $suite $p
+
+ >$tmp/aq/package.new.$p
+ t-aq-archive-updated new $p
+
+ ln -sf $suite $tmp/aq/dsc_in_suite/$sname
+
+ cat <<END >>$tmp/aq/suites
+$jsondelim
+ {
+ "archive" : "ftp-master",
+ "codename" : "$suite",
+ "components" : [
+ "main",
+ "contrib",
+ "non-free"
+ ],
+ "name" : "$sname",
+ "dakname" : "$sname"
+END
+
+ jsondelim=" },"
+
+ done
+ cat <<END >>$tmp/aq/suites
+ }
+]
+END
+}
+
+t-aq-archive-updated () {
+ local suite=$1
+ local p=$2
+ local suitedir=$tmp/aq/dsc_in_suite/$suite
+ mkdir -p $suitedir
+ perl <$tmp/aq/package.$suite.$p >$suitedir/$p -wne '
+ use JSON;
+ use strict;
+ our @v;
+ m{^(\S+) (\w+) ([^ \t/]+)/(\S+)} or die;
+ push @v, {
+ "version" => "$1",
+ "sha256sum" => "$2",
+ "component" => "$3",
+ "filename" => "$4",
+ };
+ END {
+ my $json = JSON->new->canonical();
+ print $json->encode(\@v) or die $!;
+ }
+ '
}
t-archive-process-incoming () {
- mv incoming/${p}_${v}[._]* mirror/
- t-archive-query
+ local suite=$1
+ mv $tmp/incoming/${p}_* $tmp/mirror/pool/main/
+ t-archive-query "$suite"
}
t-archive-query () {
- local dscf=${p}_${v}.dsc
- echo "${v} $dscf" >>$tmp/aq/package.sid.${p}
+ local suite=${1-sid}
+ local dscf=main/${p}_${v}.dsc
+ t-archive-query-$t_archive_method "$suite" "$p" "$v" "$dscf"
+}
+t-archive-query-aq () {
+ local suite=$1
+ local p=$2
+ local v=$3
+ local dscf=$4
+ local sha; sha=`sha256sum <$tmp/mirror/pool/$dscf`
+ echo "${v} ${sha% -} $dscf" >>$tmp/aq/package.$suite.${p}
+ t-aq-archive-updated $suite $p
}
t-archive () {
t-archive-none $1
v=$2
local dscf=${p}_$2.dsc
- rm -f $tmp/mirror/${p}_*
- ln $troot/pkg-srcs/${p}_${2%-*}* $tmp/mirror/
- t-archive-query
+ rm -f $tmp/mirror/pool/main/${p}_*
+ ln $troot/pkg-srcs/${p}_${2%-*}* $tmp/mirror/pool/main/
+ t-archive-query $suite
rm -rf $tmp/extract
mkdir $tmp/extract
- (set -e; cd $tmp/extract; dpkg-source -x ../mirror/$dscf)
+ (set -e; cd $tmp/extract; dpkg-source -x ../mirror/pool/main/$dscf)
+}
+
+t-git-dir-time-passes () {
+ touch -d 'last year' $dgitrepo
+}
+
+t-git-dir-check () {
+ local gitdir=$dgitrepo
+ case "$1" in
+ enoent)
+ if test -e "$gitdir"; then fail "$gitdir exists"; fi
+ return
+ ;;
+ public) wantstat='7[75]5' ;;
+ secret) wantstat='7[70]0' ;;
+ *) fail "$1 t-git-dir-check ?" ;;
+ esac
+ gotstat=`stat -c%a $gitdir`
+ case "$gotstat" in
+ *$wantstat) return ;;
+ *) fail "$gitdir has mode $gotstat, expected $wantstat" ;;
+ esac
+}
+
+t-expect-fsck-fail () {
+ echo >>$tmp/fsck.expected-errors "$1"
+}
+
+t-git-fsck () {
+ set +e
+ LC_MESSAGES=C git fsck --no-dangling --strict 2>&1 \
+ | tee dgit-test-fsck.errs
+ ps="${PIPESTATUS[*]}"
+ set -e
+
+ local pats
+ if [ -f $tmp/fsck.expected-errors ]; then
+ pats=(-w -f $tmp/fsck.expected-errors)
+ else
+ test "$ps" = "0 0"
+ fi
+ pats+=(-e 'notice: HEAD points to an unborn branch')
+ pats+=(-e 'notice: No default references')
+
+ set +e
+ grep -v "${pats[@]}" dgit-test-fsck.errs
+ rc=$?
+ set -e
+ case $rc in
+ 1) ;; # no unexpected errors
+ 0) fail "unexpected messages from git-fsck" ;;
+ *) fail "grep of git-fsck failed" ;;
+ esac
+}
+
+t-fscks () {
+ (
+ shopt -s nullglob
+ for d in $tmp/*/.git $tmp/git/*.git; do
+ cd "$d"
+ t-git-fsck
+ done
+ )
+}
+
+t-ok () {
+ : '========================================'
+ t-fscks
+ echo ok.
+}
+
+t-rm-dput-dropping () {
+ rm -f $tmp/${p}_${v}_*.upload
}
t-dgit () {
local dgit=${DGIT_TEST-dgit}
+ pwd
: '
{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{'
$dgit --dgit=$dgit --dget:-u --dput:--config=$tmp/dput.cf \
- -dtest-dummy $DGIT_TEST_OPTS ${DGIT_TEST_DEBUG--D} \
- -k39B13D8A "$@"
+ ${dgit_config_debian_alias-"--config-lookup-explode=dgit-distro.debian.alias-canon"} \
+ ${distro+${distro:+-d}}${distro--dtest-dummy} \
+ $DGIT_TEST_OPTS $DGIT_TEST_DEBUG \
+ -k39B13D8A $t_dgit_xopts "$@"
: '}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
'
}
t-diff-nogit () {
- diff --exclude=.git -ruN $*
+ diff --exclude=.git --exclude=.pc -ruN $*
+}
+
+t-files-notexist () {
+ local f
+ for f in "$@"; do
+ if [ -e $f ]; then
+ fail "$f exists!"
+ fi
+ done
}
t-cloned-fetched-good () {
@@ -126,11 +438,11 @@ t-cloned-fetched-good () {
t-refs-same \
refs/heads/dgit/sid \
refs/remotes/dgit/dgit/sid
- t-refs-notexist dgit/unstable remotes/dgit/dgit/unstable
+ t-refs-notexist refs/dgit/unstable refs/remotes/dgit/dgit/unstable
}
t-output () {
- printf "%s\n" "$1" >$tmp/t.want
+ printf "%s${1:+\n}" "$1" >$tmp/t.want
shift
"$@" >$tmp/t.got
diff $tmp/t.want $tmp/t.got
@@ -140,38 +452,120 @@ t-clean-on-branch () {
t-output "## $1" git status -b --porcelain
}
+t-setup-done () {
+ local savevars=$1
+ local savedirs=$2
+ local importeval=$3
+
+ local import=IMPORT.${0##*/}
+ exec 4>$tmp/$import.new
+
+ local vn
+ for vn in $savevars; do
+ perl >&4 -I. -MDebian::Dgit -e '
+ printf "%s=%s\n", $ARGV[0], shellquote $ARGV[1]
+ ' $vn "$(eval "printf '%s\n' \"\$$vn\"")"
+ done
+
+ (set -e; cd $tmp; tar cf $import.tar $savedirs)
+
+ printf >&4 "\n%s\n" "$importeval"
+
+ mv -f $tmp/$import.new $tmp/$import
+}
+
+t-setup-import () {
+ local setupname=$1
+
+ local setupsrc
+ local lock
+ if [ "x$tmpbase" = x ]; then
+ # ADTTMP was set on entry to tests/lib, so we
+ # are not sharing tmp area between tests
+ setupsrc="$tmp"
+ lock="$tmp/.dummy.lock"
+ else
+ setupsrc="$tmpbase/$setupname"
+ lock="$setupsrc.lock"
+ fi
+
+ local simport="$setupsrc/IMPORT.$setupname"
+
+ if ! [ -e "$simport" ]; then
+ with-lock-ex -w "$lock" \
+ xargs -0 -a $tmp/.save-env \
+ bash -xec '
+ cd "$1"; shift
+ setupname="$1"; shift
+ simport="$1"; shift
+ if [ -e "$simport" ]; then exit 0; fi
+ env - "$@" \
+ "tests/setup/$setupname"
+ ' x "$root" "$setupname" "$simport"
+ fi
+
+ if [ "x$setupsrc" != "x$tmp" ]; then
+ (set -e; cd $tmp; tar xf "$simport.tar")
+ fi
+
+ . "$simport"
+}
+
+t-git-get-ref-exact () {
+ local ref=$1
+ # does not dereference, unlike t-git-get-ref
+ case "$ref" in
+ refs/*) ;;
+ *) fail "t-git-get-ref-exact bad $ref" ;;
+ esac
+ git for-each-ref --format='%(objectname)' "[r]efs/${ref#refs/}"
+}
+
t-git-get-ref () {
local ref=$1
- git show-ref -d $1 | perl -ne '
+ case "$ref" in
+ refs/*) ;;
+ *) fail "t-git-get-ref bad $ref" ;;
+ esac
+ (git show-ref -d $1 || test $? = 1) | perl -ne '
$x = $1 if m#^(\w+) \Q'$1'\E(?:\^\{\})?$#;
END { print "$x\n" if length $x; }
'
}
+t-ref-same-exact () {
+ local name="$1"
+ local val; val=`t-git-get-ref-exact $name`
+ t-ref-same-val "$name" $val
+}
+
t-ref-same () {
local name="$1"
- local val=`t-git-get-ref $name`
+ local val; val=`t-git-get-ref $name`
t-ref-same-val "$name" $val
}
t-ref-head () {
- local val=`git rev-parse HEAD`
+ local val; val=`git rev-parse HEAD`
t-ref-same-val HEAD $val
}
t-ref-same-val () {
local name="$1"
local val=$2
- case "$t_ref_val" in
- '') ;;
+ case "${t_ref_val-unset}" in
+ unset) ;;
"$val") ;;
- *) fail "ref varies: $name: $val != $t_ref_val" ;;
+ *) fail "ref varies: ($name)\
+ ${val:-nothing} != ${t_ref_val:-nothing} (${t_ref_names[*]})" ;;
esac
t_ref_val="$val"
+ t_ref_names+=("$name")
}
t-refs-same-start () {
- t_ref_val=''
+ unset t_ref_val
+ t_ref_names=()
}
t-refs-same () {
@@ -184,7 +578,7 @@ t-refs-same () {
t-refs-notexist () {
local val
for g in $*; do
- val=`t-git-get-ref $g >$tmp/t.refx`
+ val=`t-git-get-ref $g`
if [ "x$val" != x ]; then
fail "ref $g unexpectedly exists ($val)"
fi
@@ -192,29 +586,188 @@ t-refs-notexist () {
}
t-v-tag () {
- echo refs/tags/debian/${v//\~/_}
+ echo refs/tags/$tagpfx/${v//\~/_}
+}
+
+t-format-ref () {
+ git log -n1 --pretty=format:"$1" "$2"
+}
+
+t-sametree-parent () {
+ local ref=$1
+ local parent
+ local ctree; ctree=$(t-format-ref '%T' "$ref")
+ while :; do
+ local psame=''
+ for parent in $(t-format-ref '%P' "$ref"); do
+ local ptree; ptree=$(t-format-ref '%T' "$parent")
+ if [ "x$ptree" = "x$ctree" ]; then
+ psame+=" $parent"
+ fi
+ done
+ case "$psame" in ""|" * *") break ;; esac
+ ref="${psame# }"
+ done
+ echo "$ref"
+}
+
+t-check-pushed-master () {
+ local master; master=`t-git-get-ref refs/heads/master`
+ if [ x$master = x$t_ref_val ]; then return; fi
+ if [ x$master = x ]; then fail "failed to push master"; fi
+ # didn't update master, it must be not FF
+ local mbase; mbase=`t-git-merge-base $master $t_ref_val`
+ if [ x$mbase = x$master ]; then fail "failed to ff master"; fi
}
t-pushed-good () {
local branch=$1
+ local suite=${2:-sid}
+ t-refs-same \
+ refs/heads/$branch
+ t-pushed-good-core
+}
+
+t-pushed-good-core () {
t-ref-dsc-dgit
t-refs-same \
- refs/heads/$branch \
`t-v-tag` \
- refs/remotes/dgit/dgit/sid
+ refs/remotes/dgit/dgit/$suite
t-refs-notexist \
refs/heads/dgit/unstable \
refs/remotes/dgit/dgit/unstable
- (set -e; cd $tmp/git/$p.git
+ (set -e; cd $dgitrepo
t-refs-same \
- refs/dgit/sid \
+ refs/dgit/$suite \
`t-v-tag`
+ ${t_check_pushed_master:- : NOT-DRS-NO-CHECK-PUSHED-MASTER}
t-refs-notexist \
refs/dgit/unstable
)
git verify-tag `t-v-tag`
}
+t-splitbrain-pushed-good--unpack () {
+ cd $tmp
+ rm -rf t-unpack
+ mkdir t-unpack
+ cd t-unpack
+ ln -s $tmp/mirror/pool/main/*.orig*.tar* .
+ ln -s $tmp/incoming/*.orig*.tar* . ||:
+ ln -s $incoming_dsc .
+ ln -s ${incoming_dsc/.dsc/.debian.tar}* .
+ dpkg-source "$@" -x *.dsc
+ cd */.
+ git init
+ git fetch ../../$p "refs/tags/*:refs/tags/*"
+}
+
+t-splitbrain-pushed-good--checkprep () {
+ git add -Af .
+ git rm --cached -r --ignore-unmatch .pc
+}
+
+t-splitbrain-pushed-good--checkdiff () {
+ local tag=$1
+ t-splitbrain-pushed-good--checkprep
+ t-output "" git diff --stat --cached $tag
+}
+
+t-splitbrain-pushed-good-start () {
+ dep14tag=refs/tags/test-dummy/${v//\~/_}
+ dgittag=$(t-v-tag)
+ t-output "" git status --porcelain
+ t-ref-head
+ t-refs-same $dep14tag
+ (set -e; cd $dgitrepo; t-refs-same $dep14tag)
+ git merge-base --is-ancestor $dep14tag $dgittag
+
+ t-refs-same-start
+ t-ref-same refs/heads/split.p
+ case "$(t-git-get-ref refs/heads/split.b)" in
+ "$t_ref_val") ;;
+ "$(git rev-parse refs/heads/split.p^0)") ;;
+ "$(git rev-parse refs/heads/split.p^1)") ;;
+ *) fail 'bad b/p' ;;
+ esac
+ t-pushed-good-core
+
+ t-incoming-dsc
+
+ t-splitbrain-pushed-good--unpack
+ t-splitbrain-pushed-good--checkdiff $dgittag
+}
+t-splitbrain-pushed-good-end-made-dep14 () {
+ t-splitbrain-pushed-good--checkdiff $dep14tag
+ cd $tmp/$p
+}
+
+t-splitbrain-rm-gitignore-patch () {
+ perl -i -pe '
+ next unless $_ eq "auto-gitignore\n";
+ die if $counter++;
+ chomp;
+ rename "debian/patches/$_", "../t-auto-gitignore" or die $!;
+ $_ = "";
+ ' debian/patches/series
+}
+
+t-gbp-pushed-good () {
+ local suite=${1:-sid}
+ t-splitbrain-pushed-good-start
+
+ # Right, now we want to check that the maintainer tree and
+ # the dgit tree differ in exactly the ways we expect. We
+ # achieve this by trying to reconstruct the maintainer tree
+ # from the dgit tree.
+
+ # So, unpack it withut the patches applied
+ t-splitbrain-pushed-good--unpack --skip-patches
+
+ # dgit might have added a .gitignore patch, which we need to
+ # drop and remove
+ t-splitbrain-rm-gitignore-patch
+
+ # Now the result should differ only in non-debian/ .gitignores
+ t-splitbrain-pushed-good--checkprep
+ git diff --cached --name-only $dep14tag >../changed
+ perl -ne '
+ next if !m#^debian/# && m#(^|/)\.gitignore#;
+ die "$_ mismatch";
+ ' <../changed
+
+ # If we actually apply the gitignore patch by hand, it
+ # should be perfect:
+ if [ -f ../t-auto-gitignore ]; then
+ patch --backup-if-mismatch -p1 -u <../t-auto-gitignore
+ fi
+
+ t-splitbrain-pushed-good-end-made-dep14
+}
+
+t-unapplied-pushed-good () {
+ t-splitbrain-pushed-good-start
+ t-splitbrain-pushed-good--unpack --skip-patches
+ t-splitbrain-pushed-good-end-made-dep14
+}
+
+t-dpm-pushed-good () {
+ t-splitbrain-pushed-good-start
+ t-splitbrain-pushed-good--unpack
+ t-splitbrain-rm-gitignore-patch
+ t-splitbrain-pushed-good-end-made-dep14
+}
+
+t-commit-build-push-expect-log () {
+ local msg=$1
+ local mpat=$2
+ t-commit "$msg"
+ t-dgit build
+ LC_MESSAGES=C \
+ t-dgit push --new 2>&1 |tee $tmp/push.log
+ t-grep-mpat "$mpat" $tmp/push.log
+}
+
t-822-field () {
local file=$1
local field=$2
@@ -228,18 +781,190 @@ t-822-field () {
' <$file
}
-t-ref-dsc-dgit () {
+t-defdistro () {
+ export DGIT_TEST_DISTRO=''
+ distro=''
+ t-git-config dgit-suite.unstable.distro test-dummy
+}
+
+t-stunt-envvar () {
+ local var=$1
+ local tstunt=$2
+ eval '
+ case "$'$var'" in
+ "$tstunt:"*) ;;
+ *":$tstunt:"*) ;;
+ "") '$var'="$tstunt" ;;
+ *) '$var'="$tstunt:$'$var'" ;;
+ esac
+ export '$var'
+ '
+}
+
+t-tstunt--save-real () {
+ local f="$1"
+ case "$f" in
+ */*) return ;;
+ esac
+
+ local rc
+ local real
+ set +e
+ real=$(
+ p=":$PATH:"
+ p="${p/:"$tmp/tstunt":/:}"
+ p="${p%:}"
+ p="${p#:}"
+ PATH="$p"
+ type -p "$f"
+ )
+ rc=$?
+ set -e
+
+ case $rc in
+ 1) return ;;
+ 0) ;;
+ *) fail "did not find $f on PATH $PATH" ;;
+ esac
+
+ local varname=${f//[^_0-9a-zA-Z]/_}
+ varname=DGIT_TEST_REAL_${varname^^}
+
+ eval "
+ : \${$varname:=\$real}
+ export $varname
+ "
+}
+
+t-tstunt () {
+ local tstunt=$tmp/tstunt
+ t-stunt-envvar PATH $tstunt
+ t-stunt-envvar PERLLIB $tstunt
+ local f
+ for f in "$@"; do
+ t-tstunt--save-real $f
+ f="./$f"
+ local d="$tstunt/${f%/*}"
+ mkdir -p $d
+ ln -sf "$troot/tstunt/$f" "$d"/.
+ done
+}
+
+t-tstunt-parsechangelog () {
+ t-tstunt dpkg-parsechangelog Dpkg/Changelog/Parse.pm
+}
+
+t-tstunt-lintian () {
+ t-tstunt lintian
+}
+
+t-tstunt-debuild () {
+ t-tstunt debuild
+}
+
+t-incoming-dsc () {
local dsc=${p}_${v}.dsc
- local val=`t-822-field $tmp/incoming/$dsc Dgit`
- perl -e '$_=shift @ARGV; die "$dsc Dgit $_ ?" unless m/^\w+\b/;' "$val"
- t-ref-same-val $dsc "$val"
+ incoming_dsc=$tmp/incoming/$dsc
+}
+
+t-ref-dsc-dgit () {
+ t-incoming-dsc
+ local val; val=`t-822-field $incoming_dsc Dgit`
+ val=$( perl -e '
+ $_=shift @ARGV;
+ die "Dgit $_ ?" unless m/^\w+\b/;
+ print $&,"\n" or die $!;
+ ' "$val")
+ t-ref-same-val $incoming_dsc "$val"
}
t-apply-diff () {
local v1=$1
local v2=$2
- (cd $troot/pkg-srcs; debdiff ${p}_${v1}.dsc ${p}_${v2}.dsc) \
- | patch -p1 -u
+ (cd $troot/pkg-srcs;
+ debdiff ${p}_${v1}.dsc ${p}_${v2}.dsc || test $? = 1) \
+ | patch -p1 -u
+}
+
+t-gbp-unapplied-pq2qc () {
+ # does `gbp pq export'
+ # commits the resulting debian/patches on qc/BRANCH
+ # leaves us on qc/BRANCH (eg "qc/quilt-tip"))
+ # qc/BRANCH is not fast-forwarding
+
+ gbp pq export
+
+ branch=`git symbolic-ref HEAD`
+ branch=${branch#refs/heads/}
+
+ case "$branch" in
+ */*) fail "unexpected branch $branch" ;;
+ esac
+
+ git branch -f qc/$branch
+ git checkout qc/$branch
+ git add debian/patches
+ git commit -m 'Commit patch queue'
+}
+
+t-git-pseudo-merge () {
+ # like git merge -s ours
+ if [ ! "$git_pseuomerge_opts" ]; then
+ if git merge --help \
+ | grep -q allow-unrelated-histories; then
+ git_pseuomerge_opts='--allow-unrelated-histories'
+ fi
+ git_pseuomerge_opts+=' -s ours'
+ fi
+ git merge $git_pseuomerge_opts "$@"
+}
+
+t-gbp-example-prep-no-ff () {
+ t-tstunt-parsechangelog
+ t-archive example 1.0-1
+ t-git-none
+ t-worktree 1.0
+
+ cd example
+
+ t-dgit fetch
+
+ git checkout -b patch-queue/quilt-tip-2 patch-queue/quilt-tip
+ gbp pq rebase
+
+ echo '/* some comment */' >>src.c
+ git add src.c
+ git commit -m 'Add a comment to an upstream file'
+
+ t-gbp-unapplied-pq2qc
+
+ t-commit 'some updates' 1.0-2
+}
+
+t-gbp-example-prep () {
+ t-gbp-example-prep-no-ff
+
+ t-git-pseudo-merge \
+ -m 'Pseudo-merge to make descendant of archive' \
+ remotes/dgit/dgit/sid
+}
+
+t-make-badcommit () {
+ badcommit=$(
+ git cat-file commit HEAD | \
+ perl -pe 's/^committer /commiter /' | \
+ git hash-object -w -t commit --stdin
+ )
+ t-expect-fsck-fail $badcommit
+}
+
+t-commit () {
+ local msg=$1
+ v=${2:-${majorv:-1}.$revision}
+ dch --force-distribution -v$v --distribution ${3:-unstable} "$1"
+ git add debian/changelog
+ debcommit
+ revision=$(( ${revision-0} + 1 ))
}
t-git-config () {
@@ -248,18 +973,126 @@ t-git-config () {
t-drs () {
export DGIT_TEST_TROOT=$troot
- export DGIT_TEST_TMP=$tmp
t-git-config dgit-distro.test-dummy.git-url "ext::$troot/drs-git-ext %S "
t-git-config dgit-distro.test-dummy.git-check true
t-git-config dgit-distro.test-dummy.git-create true
- cp $root/tests/gnupg/{dd.gpg,dm.gpg,dm.txt} $tmp/.
- cp $root/tests/suites $tmp/.
+ t-git-config dgit-distro.test-dummy.dgit-tag-format new,old,maint
+ cp $troot/gnupg/{dd.gpg,dm.gpg,dm.txt} $tmp/.
+ cp $troot/suites $tmp/.
+ cp $troot/suites $tmp/suites-master
+
+ export t_check_pushed_master=t-check-pushed-master
+
+ drs_dispatch=$tmp/distro=test-dummy
+ mkdir $drs_dispatch
+
+ if [ "x$DGIT_TEST_INTREE" != x ]; then
+ ln -sf "$DGIT_TEST_INTREE" $drs_dispatch/dgit-live
+ fi
+
+ ln -sf $tmp/git $drs_dispatch/repos
+ ln -sf $tmp/suites $tmp/suites-master $tmp/dm.txt $drs_dispatch/
+ mkdir -p $drs_dispatch/keyrings
+ ln -sf $tmp/dd.gpg $drs_dispatch/keyrings/debian-keyring.gpg
+ ln -sf $tmp/dm.gpg $drs_dispatch/keyrings/debian-maintainers.gpg
+ ln -sf /bin/true $drs_dispatch/policy-hook
+}
+
+t-newtag () {
+ export tagpfx=archive/test-dummy
+ t-git-config dgit-distro.test-dummy.dgit-tag-format new,maint
+}
+t-oldtag () {
+ export tagpfx=test-dummy
+ t-git-config dgit-distro.test-dummy.dgit-tag-format old
}
-t-drs-test () {
+t-dsd () {
t-drs
+ t-git-config dgit-distro.test-dummy.ssh "$troot/dsd-ssh"
+ t-git-config dgit-distro.test-dummy.git-check ssh-cmd
+ t-git-config dgit-distro.test-dummy.git-create true
+ t-git-config dgit-distro.test-dummy.git-url \
+ "ext::$troot/dsd-ssh X %S /dgit/test-dummy/repos"
+
+ t-git-config dgit-distro.test-dummy.diverts.drs /drs
+ t-git-config dgit-distro.test-dummy/drs.ssh "$troot/ssh"
+ t-git-config dgit-distro.test-dummy/drs.git-url $tmp/git
+ t-git-config dgit-distro.test-dummy/drs.git-check ssh-cmd
+ t-git-config dgit-distro.test-dummy/drs.git-create ssh-cmd
+
+ echo 'no-such-package* drs' >$drs_dispatch/diverts
+}
+
+t-policy-admin () {
+ : '(((((((((((((((((((((((((((((((((((((((('
+ ${DGIT_INFRA_PFX}dgit-repos-admin-debian --repos $tmp/git "$@"
+ : '))))))))))))))))))))))))))))))))))))))))'
+}
+
+t-policy-nonexist () {
+ ln -sf no-such-file-or-directory $drs_dispatch/policy-hook
+}
+
+t-make-hook-link () {
+ local hook=$1 # in infra/
+ local linkpath=$2
+ hook=${DGIT_INFRA_PFX}$hook
+ case $hook in
+ */*) ;;
+ *) hook=`type -P $hook` ;;
+ esac
+ ln -sf "$hook" $linkpath
+}
+
+t-policy () {
+ local policyhook=$1
+ t-make-hook-link $policyhook $drs_dispatch/policy-hook
+}
+
+t-debpolicy () {
+ t-dsd
+ t-policy dgit-repos-policy-debian
+
+ mkdir $tmp/git
+ t-policy-admin create-db
+}
+
+t-policy-periodic () {
+ : '(((((((((((((((((((((((((((((((((((((((('
+ ${DGIT_REPOS_SERVER_TEST-dgit-repos-server} \
+ test-dummy $drs_dispatch '' --cron
+ : '))))))))))))))))))))))))))))))))))))))))'
+}
+
+t-restrict () {
+ local restriction=$1
+ (cd $root; t-restriction-$restriction >&2)
+}
+
+t-dependencies () {
+ : "Hopefully installed: $*"
+}
+
+t-chain-test () {
+ local ct=$1
+ local d=${0%/*}
cd $root
export DGIT_TEST_TESTNAME="$testname"
+ export DGIT_TEST_TMPBASE="$tmpbase"
export ADTTMP=$tmp
- exec "${0///drs-//}" "$@"
+ exec "$d/$ct"
+}
+
+t-alt-test () {
+ local t=${0##*/}
+ t-${t%%-*}
+ t-chain-test "${t#*-}"
}
+
+t-git-config dgit.default.old-dsc-distro test-dummy
+
+case "$0" in
+*/gnupg) ;;
+*) t-setup-import gnupg ;;
+esac
diff --git a/tests/lib-build-modes b/tests/lib-build-modes
new file mode 100644
index 0000000..ee2975d
--- /dev/null
+++ b/tests/lib-build-modes
@@ -0,0 +1,235 @@
+
+bm-prep-ownpackage-branches () {
+ cat <<'END' >$tmp/stunt-git
+#!/bin/sh -e
+case "$*" in
+*clean*) echo >&2 "BUILD-MODES PROGRAM git $*" ;;
+esac
+exec git "$@"
+END
+ chmod +x $tmp/stunt-git
+
+ bm_branches="$1"
+}
+
+bm-prep () {
+ t-tstunt-parsechangelog
+
+ t-prep-newpackage example 1.0
+
+ cd $p
+
+ git checkout -b bad-build-deps indep-arch
+ perl -pe 's/Build-Depends.*/$&, x-dgit-no-such-package/' \
+ -i debian/control
+ git commit -a -m bad-build-deps
+
+ bm-prep-ownpackage-branches 'indep-arch bad-build-deps'
+
+ if zgrep 'dpkg-buildpackage: Make dependency checks fatal for -S' \
+ /usr/share/doc/dpkg-dev/changelog.gz; then
+ dpkgbuildpackage_deps_for_clean=true
+ else
+ dpkgbuildpackage_deps_for_clean=false
+ fi
+
+ cleanmodes_default="git none dpkg-source dpkg-source-d"
+ cleanmodes_all="$cleanmodes_default git-ff check"
+ cleanmodes="$cleanmodes_default"
+}
+
+bm-gbp-example-acts () {
+ t-gbp-example-prep
+
+ git checkout -b for-build-modes qc/quilt-tip-2
+ # build-modes cannot cope with branches containing /
+
+ bm-prep-ownpackage-branches for-build-modes
+
+ cleanmodes='git dpkg-source'
+
+ for act in "$@"; do
+ bm-guess-e-source-e-targets "$act"
+ real_act="--quilt=gbp $act"
+ case "$act" in
+ sbuild*) bm_quirk_after_act=bm-quirk-sbuild-after-act ;;
+ gbp-*) real_act="$real_act --git-ignore-branch" ;;
+ *) bm_quirk_after_act='' ;;
+ esac
+ bm-act-iterate
+ done
+}
+
+bm-guess-e-source-e-targets () {
+ local some_act=$1
+ case "$some_act" in
+ sbuild*" --no-arch-all"*)
+ e_source=true; e_targets='build-arch binary-arch' ;;
+ build-source)
+ e_source=true; e_targets='' ;;
+ *" -b") e_source=false; e_targets='build binary' ;;
+ *" -B") e_source=false; e_targets='build-arch binary-arch' ;;
+ *" -A") e_source=false; e_targets='build-indep binary-indep' ;;
+ *" -S") e_source=true; e_targets=' ' ;;
+ *" -F") e_source=true; e_targets='build binary' ;;
+ *" -G") e_source=true; e_targets='build-arch binary-arch' ;;
+ *" -g") e_source=true; e_targets='build-indep binary-indep' ;;
+ *) e_source=true; e_targets='build binary' ;;
+ esac
+}
+
+bm-quirk-sbuild-after-act () {
+ # sbuild likes to run the package clean target in the chroot,
+ # which isn't necessary in our case. We don't disable it in
+ # dgit because we want to do what sbuild does, in case there
+ # are packages which don't build unless their clean target was
+ # run. We know it must be running it in the chroot because we
+ # provide sbuild with the dsc, not the tree, so we simply
+ # ignore all executions of the clean target by schroot.
+ local arch; arch=$(dpkg-architecture -qDEB_BUILD_ARCH)
+ local sblog=../example_${v}_$arch.build
+ if [ -e $sblog ]; then
+ sed '
+ s/^EXAMPLE RULES TARGET clean/HOOK SUPPRESSED &/;
+ ' <$sblog >>$bmlog
+ else
+ echo "SBUILD LOG FILE ($sblog) MISSING"
+ fi
+}
+
+bm-report-test () {
+ local desc=$1; shift
+ if "$@"; then
+ echo >&4 "$desc EXISTS"
+ else
+ echo >&4 "$desc MISSING"
+ fi
+}
+
+bm-build-deps-ok () {
+ case "$branch" in
+ *bad-build-deps*) return 1 ;;
+ *) return 0 ;;
+ esac
+}
+
+bm-compute-expected () {
+ require_fail=unexpect # or required
+ tolerate_fail=unexpect # or tolerate
+
+ exec 4>$bmexp
+ echo >&4 "$heading"
+
+ case $cleanmode in
+ git) echo >&4 'BUILD-MODES PROGRAM git clean -xdf' ;;
+ git-ff) echo >&4 'BUILD-MODES PROGRAM git clean -xdff' ;;
+ check) echo >&4 'BUILD-MODES PROGRAM git clean -xdn' ;;
+ dpkg-source-d) echo >&4 "EXAMPLE RULES TARGET clean" ;;
+ dpkg-source) bm-build-deps-ok || tolerate_fail=tolerate
+ echo >&4 "EXAMPLE RULES TARGET clean"
+ ;;
+ none) ;;
+ *) fail "t-compute-expected-run $cleanmode ??" ;;
+ esac
+
+ if [ "x$e_targets" != x ]; then
+ # e_targets can be " " to mean `/may/ fail due to b-d'
+ bm-build-deps-ok || tolerate_fail=tolerate
+ fi
+
+ for t in $e_targets; do
+ bm-build-deps-ok || require_fail=required
+ echo >&4 "EXAMPLE RULES TARGET $t"
+ done
+
+ bm-report-test "SOURCE FILE" $e_source
+ bm-report-test "SOURCE IN CHANGES" $e_source
+ bm-report-test "DEBS IN CHANGES" expr "$e_targets" : '.*binary.*'
+
+ exec 4>&-
+}
+
+bm-run-one () {
+ local args="$DGIT_TEST_BM_BASEARGS --clean=$cleanmode $real_act"
+
+ bmid="$act,$cleanmode,$branch"
+ bmid=${bmid// /_}
+
+ rm -f ../${p}_{v}_*.changes
+
+ heading="===== [$bmid] dgit $args ====="
+
+ bmlog=$tmp/run.$bmid.output
+ bmexp=$tmp/run.$bmid.expected
+ bmgot=$tmp/run.$bmid.results
+
+ bm-compute-expected
+
+ git checkout $branch
+ git clean -xdf # since we might not do any actual cleaning
+
+ dsc="../example_$v.dsc"
+ rm -f $dsc
+
+ set +o pipefail
+ t-dgit --rm-old-changes --git=$tmp/stunt-git $args 2>&1 | tee $bmlog
+ local ps="${PIPESTATUS[*]}"
+ set -o pipefail
+
+ $bm_quirk_after_act
+
+ exec 4>$bmgot
+ echo >&4 "$heading"
+
+ case $ps in
+ "0 0") actual_status=success ;;
+ *" 0") actual_status=failure; echo >&4 "OPERATION FAILED"; ;;
+ *) fail "tee failed" ;;
+ esac
+
+ case "$require_fail-$tolerate_fail-$actual_status" in
+ required-********-failure) echo >>$bmexp "REQUIRED FAILURE" ;;
+ ********-tolerate-failure) echo >>$bmexp "TOLERATED FAILURE" ;;
+ unexpect-********-success) ;;
+ *) fail "RF=$require_fail TF=$tolerate_fail AS=$actual_status" ;;
+ esac
+
+ egrep >&4 '^EXAMPLE RULES TARGET|^BUILD-MODES' $bmlog || [ $? = 1 ]
+
+ bm-report-test "SOURCE FILE" [ -e $dsc ]
+
+ if [ $actual_status = success ]; then
+ local changes; changes=$(echo ../example_${v}_*.changes)
+ case "$changes" in
+ *' '*) fail "build generated ambiguous .changes: $changes" ;;
+ esac
+
+ perl -ne 'print if m/^files:/i ... m/^\S/' \
+ <$changes >$changes.files
+
+ bm-report-test "SOURCE IN CHANGES" grep '\.dsc$' $changes.files
+ bm-report-test "DEBS IN CHANGES" grep '\.deb$' $changes.files
+ fi
+
+ exec 4>&-
+
+ $bm_quirk_before_diff
+
+ [ $actual_status = failure ] || diff -U10 $bmexp $bmgot
+}
+
+bm-act-iterate () {
+ for cleanmode in $cleanmodes; do
+ for branch in $bm_branches; do
+ bm-run-one
+ done
+ done
+ : bm-act-iterate done.
+}
+
+bm-alwayssplit () {
+ local t=${0##*/}
+ DGIT_TEST_BM_BASEARGS+=' --always-split-source-build'
+ export DGIT_TEST_BM_BASEARGS
+ t-chain-test "${t%%-asplit}"
+}
diff --git a/tests/lib-core b/tests/lib-core
new file mode 100644
index 0000000..6cdffeb
--- /dev/null
+++ b/tests/lib-core
@@ -0,0 +1,38 @@
+#
+
+fail () {
+ echo >&2 "failed: $*"
+ exit 1
+}
+
+t-set-intree () {
+ if [ "x$DGIT_TEST_INTREE" = x ]; then return; fi
+ : ${DGIT_TEST:=$DGIT_TEST_INTREE/dgit}
+ : ${DGIT_BADCOMMIT_FIXUP:=$DGIT_TEST_INTREE/dgit-badcommit-fixup}
+ : ${DGIT_REPOS_SERVER_TEST:=$DGIT_TEST_INTREE/infra/dgit-repos-server}
+ : ${DGIT_SSH_DISPATCH_TEST:=$DGIT_TEST_INTREE/infra/dgit-ssh-dispatch}
+ : ${DGIT_INFRA_PFX:=$DGIT_TEST_INTREE${DGIT_TEST_INTREE:+/infra/}}
+ export DGIT_TEST DGIT_BADCOMMIT_FIXUP
+ export DGIT_REPOS_SERVER_TEST DGIT_SSH_DISPATCH_TEST
+ export PERLLIB="$DGIT_TEST_INTREE${PERLLIB:+:}${PERLLIB}"
+}
+
+t-set-using-tmp () {
+ export HOME=$tmp
+ export DGIT_TEST_DUMMY_DIR=$tmp
+ export DGIT_TEST_TMP=$tmp
+ export GNUPGHOME=$tmp/nonexistent
+ git config --global user.email 'dgit-test@debian.example.net'
+ git config --global user.name 'dgit test git user'
+}
+
+t-filter-out-git-hyphen-dir () {
+ local pathent; pathent=$(type -p git-rev-parse ||:)
+ case "$pathent" in '') return ;; esac
+ pathent=${pathent%/*}
+ local path=":$PATH:"
+ path="${path//:$pathent:/}"
+ path="${path#:}"
+ path="${path%:}"
+ PATH="$path"
+}
diff --git a/tests/lib-import-chk b/tests/lib-import-chk
new file mode 100644
index 0000000..88984c1
--- /dev/null
+++ b/tests/lib-import-chk
@@ -0,0 +1,97 @@
+
+t-import-chk-authorship () {
+ perl -ne 'print $1,"\n" if m/^ -- (\S.*\>) /' debian/changelog \
+ | sort -u \
+ > $tmp/authorship.changelog
+ ${import_chk_changelog_massage:-:} $tmp/authorship.changelog
+ git log --pretty=format:'%an <%ae>%n%cn <%ce>' \
+ | sort -u \
+ > $tmp/authorship.commits
+ diff $tmp/authorship.{changelog,commits}
+}
+
+t-import-chk1 () {
+ p=$1
+ v=$2
+
+ t-archive $p $v
+}
+t-import-chk2() {
+ t-git-none
+ rm -rf $p
+ t-dgit --no-rm-on-error clone $p
+
+ # And now we make an update using the same orig tarball, and
+ # check that the orig import is stable.
+
+ cd $p
+
+ t-import-chk-authorship
+
+ git branch first-import
+
+ m='Commit for import check'
+ echo "$m" >>import-check
+
+ v=${v%-*}-99
+ dch -v $v -D unstable -m "$m"
+
+ git add import-check debian/changelog
+ git commit -m "$m"
+
+ t-dgit -wgf quilt-fixup
+ t-dgit -wgf build-source
+
+ # The resulting .dsc does not have a Dgit line (because dgit push
+ # puts that in). So we just shove it in the archive now
+
+ ln ../${p}_${v}.* $tmp/mirror/pool/main/
+ t-archive-query
+
+ t-dgit fetch
+
+ git branch first-2nd-import remotes/dgit/dgit/sid
+
+ t-git-next-date
+
+ git update-ref refs/remotes/dgit/dgit/sid first-import
+
+ t-dgit fetch
+
+ t-refs-same-start
+ t-ref-same refs/remotes/dgit/dgit/sid
+ t-ref-same refs/heads/first-2nd-import
+
+ for orig in ../${p}_${v%-*}.orig*.tar.*; do
+ tar -atf $orig | LC_ALL=C sort >../files.o
+ pfx=$(perl <../files.o -ne '
+ while (<>) {
+ m#^([^/]+/)# or exit 0;
+ $x //= $1;
+ $x eq $1 or exit 0;
+ }
+ print "$x\n";
+ ')
+ perl -i~ -pe '
+ s#^\Q'"$pfx"'\E##;
+ $_="" if m/^$/ || m#/$# || m#^\.git/#;
+ ' ../files.o
+ orig=${orig#../}
+ pat="^Import ${orig//./\\.}\$"
+ t-refs-same-start
+ for start in first-import first-2nd-import; do
+ git log --pretty='tformat:%H' --grep "$pat" $start \
+ >../t.imp
+ test $(wc -l <../t.imp) = 1
+ imp=$(cat ../t.imp)
+ t-ref-same-val "$orig $start" "$imp"
+ done
+ git ls-tree -r --name-only "$t_ref_val:" \
+ | sort >../files.g
+ diff ../files.{o,g}
+ done
+ cd ..
+}
+
+t-import-chk() { t-import-chk1 "$@"; t-import-chk2; }
+
diff --git a/tests/lib-mirror b/tests/lib-mirror
new file mode 100644
index 0000000..25f0f90
--- /dev/null
+++ b/tests/lib-mirror
@@ -0,0 +1,42 @@
+
+t-mirror-setup () {
+ # p must be set already
+
+ reposmirror=$tmp/git-mirror
+ pmirror=$reposmirror/$p.git
+ queuedir=$tmp/git/_mirror-queue
+
+ mkdir $reposmirror
+
+ mirror_hook=$drs_dispatch/mirror-hook
+ t-make-hook-link dgit-mirror-rsync $mirror_hook
+
+ >$drs_dispatch/mirror-settings
+ t-mirror-set remoterepos="$reposmirror"
+
+ t-mirror-hook setup
+}
+
+t-mirror-set () {
+ echo >>$drs_dispatch/mirror-settings "$1"
+}
+
+t-mirror-hook () {
+ : '(((((((((((((((((((((((((((((((((((((((('
+ "$mirror_hook" "$drs_dispatch" "$@"
+ : '))))))))))))))))))))))))))))))))))))))))'
+}
+
+t-check-mirrored () {
+ t-reporefs master
+ t-reporefs mirror $pmirror
+ diff $tmp/show-refs.{master,mirror}
+ cat $queuedir/$p.log ||:
+ t-files-notexist $queuedir/$p.{n,a,lock,err}
+}
+
+t-check-not-mirrored () {
+ # uses previous t-reporefs-master
+ t-reporefs mirror $pmirror
+ diff $tmp/show-refs.{master,mirror}
+}
diff --git a/tests/lib-orig-include-exclude b/tests/lib-orig-include-exclude
new file mode 100644
index 0000000..104cf0b
--- /dev/null
+++ b/tests/lib-orig-include-exclude
@@ -0,0 +1,67 @@
+# designed to be .'d
+
+t-tstunt-parsechangelog
+
+t-archive example 1.0-1
+t-git-none
+
+t-dgit clone $p
+
+origs='orig orig-docs'
+usvsns='1.0 1.1'
+
+for o in $origs; do
+ cp ${p}_{1.0,1.1}.${o}.tar.gz
+done
+
+mkdir -p "$tmp/aq/file_in_archive/%"
+
+cd $p
+
+test-push-1 () {
+ v=$1
+ ch=$2
+ suite=$3
+
+ t-commit $v $v $suite
+ t-dgit $ch build
+}
+
+test-push-2 () {
+ $test_push_2_hook
+ t-dgit $ch "$@" push
+}
+
+test-push-1 1.0-2 --ch:-sa
+
+grep orig ../${p}_${v}_*.changes
+
+test-push-2
+
+origs_findls () {
+ find $tmp/mirror -name '*orig*' -ls \
+ | perl -pe 's/^(\s*\d+\s+\d+\s+\S+\s)\s*\d+(\s)/$1$2/'
+}
+
+# check that dgit stripped out the orig update
+origs_findls >../before
+
+t-archive-process-incoming sid
+
+origs_findls >../after
+diff -u ../before ../after
+
+test-push-1 1.1-1.2 --ch:-sd
+
+test-push-2
+
+t-archive-process-incoming sid
+
+cd ..
+mkdir get
+cd get
+
+t-dgit clone $p
+# ^ checks that all the origs are there, ie that dgit added the origs
+
+cd ..
diff --git a/tests/lib-reprepro b/tests/lib-reprepro
new file mode 100644
index 0000000..0a688f6
--- /dev/null
+++ b/tests/lib-reprepro
@@ -0,0 +1,97 @@
+# -*- bash -*-
+
+t-reprepro () {
+
+ t_archive_method=reprepro
+
+ t-reprepro-cfg
+}
+
+t-reprepro-cfg () {
+ local rrinst=$1
+ local rrdistro=${2:-test-dummy}
+
+ local etcapt=$tmp/${rrinst}etc-apt
+ local mir=$tmp/${rrinst}mirror
+
+ t-git-config dgit-distro.$rrdistro.archive-query aptget:
+ t-git-config dgit-distro.$rrdistro.mirror file://$mir/
+
+ mkdir $etcapt
+ cat >$etcapt/conf <<END
+Dir::Etc "$etcapt";
+END
+ export APT_CONFIG=$etcapt/conf
+ gpg --export Hannibal >han.pgp
+ fakeroot apt-key add <han.pgp
+ mkdir $etcapt/apt.conf.d
+}
+
+t-archive-none-reprepro () { # hook called by t-archive-none
+ t-reprepro-setup
+ t-reprepro-regen
+ local rrinst=
+}
+t-archive-query-reprepro () { # hook called by t-archive-query
+ local suite=$1
+ local p=$2
+ local v=$3
+ local dscf=$4
+ local rrinst=
+ t-reprepro-includedsc $suite $tmp/mirror/pool/$dscf "$rrinst"
+}
+
+t-reprepro-setup () {
+ local rrinst=$1
+
+ local mir=$tmp/${rrinst}mirror
+ local rrc=$mir/conf
+ mkdir -p $rrc
+ mkdir -p $mir/pool/main
+
+ exec 3>$rrc/distributions
+
+ local arch; arch=`dpkg --print-architecture`
+
+ for suitespec in $suitespecs; do
+ local suite=${suitespec%%:*}
+ local sname=${suitespec#*:}
+
+ mkdir -p $mir/dists
+ if [ $sname != $suite ]; then
+ rm -f $mir/dists/$sname
+ ln -s $suite $mir/dists/$sname
+ fi
+
+ cat >&3 <<END
+Suite: $sname
+Codename: $suite
+Components: main
+Architectures: source binary-$arch
+SignWith: Hannibal
+
+END
+ done
+}
+
+t-reprepro-includedsc () {
+ local suite=$1
+ local dscf=$2
+ local rrinst=$3
+ t-reprepro--run includedsc $suite $dscf
+}
+
+t-reprepro--run () {
+ # caller is supposed to have set rrinst
+ local mir=$tmp/${rrinst}mirror
+ reprepro \
+ --outdir $mir \
+ --basedir $mir \
+ "$@"
+}
+
+t-reprepro-regen () {
+ local rrinst=$1
+
+ t-reprepro--run export
+}
diff --git a/tests/lib-restricts b/tests/lib-restricts
new file mode 100644
index 0000000..bffe13a
--- /dev/null
+++ b/tests/lib-restricts
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+t-restriction-x-dgit-intree-only () {
+ if [ "x$DGIT_TEST_INTREE" != x ]; then return 0; fi
+ echo 'running installed package version'
+ return 1
+}
+
+t-restriction-x-dgit-git-only () {
+ if test -d .git; then return 0; fi
+ echo 'not running out of git clone'
+ return 1
+}
+
+t-restriction-x-dgit-schroot-build () {
+ schroot -l -c build 2>&1 >/dev/null || return 1
+}
+
+t-restriction-x-dgit-unfinished () {
+ echo 'unfinished test, or unfinished feature'
+ return 1
+}
diff --git a/tests/pkg-srcs/example_1.0-1+absurd.debian.tar.xz b/tests/pkg-srcs/example_1.0-1+absurd.debian.tar.xz
new file mode 100644
index 0000000..9a2dd12
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0-1+absurd.debian.tar.xz
Binary files differ
diff --git a/tests/pkg-srcs/example_1.0-1+absurd.dsc b/tests/pkg-srcs/example_1.0-1+absurd.dsc
new file mode 100644
index 0000000..1ab743d
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0-1+absurd.dsc
@@ -0,0 +1,22 @@
+Format: 3.0 (quilt)
+Source: example
+Binary: example
+Architecture: all
+Version: 1.0-1+absurd
+Maintainer: Ian Jackson <ijackson@chiark.greenend.org.uk>
+Standards-Version: 3.9.4.0
+Build-Depends: debhelper (>= 8)
+Package-List:
+ example deb devel extra arch=all
+Checksums-Sha1:
+ 2bc730f941db49de57e9678fb0b07bd95507bb44 236 example_1.0.orig-docs.tar.gz
+ 4bff9170ce9b10cb59937195c5ae2c73719fe150 373 example_1.0.orig.tar.gz
+ dafb6f0db0580179ff246dba1dc2892246e84a2c 1416 example_1.0-1+absurd.debian.tar.xz
+Checksums-Sha256:
+ ad9671f6b25cdd9f0573f803f702448a45a45183db1d79701aa760bccbeed29c 236 example_1.0.orig-docs.tar.gz
+ a3ef7c951152f3ec754f96fd483457aa88ba06df3084e6f1cc7c25b669567c17 373 example_1.0.orig.tar.gz
+ 4003c34398894e46823bb3fda69f4351dbd5649e321259cde266a135f0428c51 1416 example_1.0-1+absurd.debian.tar.xz
+Files:
+ cb0cb5487b1e5bcb82547396b4fe93e5 236 example_1.0.orig-docs.tar.gz
+ 599f47808a7754c66aea3cda1b3208d6 373 example_1.0.orig.tar.gz
+ 0e88c1ed094f09ee7bf57607132d55ee 1416 example_1.0-1+absurd.debian.tar.xz
diff --git a/tests/pkg-srcs/example_1.0-1.100.debian.tar.xz b/tests/pkg-srcs/example_1.0-1.100.debian.tar.xz
new file mode 100644
index 0000000..ea8ec34
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0-1.100.debian.tar.xz
Binary files differ
diff --git a/tests/pkg-srcs/example_1.0-1.100.dsc b/tests/pkg-srcs/example_1.0-1.100.dsc
new file mode 100644
index 0000000..5b075b5
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0-1.100.dsc
@@ -0,0 +1,22 @@
+Format: 3.0 (quilt)
+Source: example
+Binary: example
+Architecture: all
+Version: 1.0-1.100
+Maintainer: Ian Jackson <ijackson@chiark.greenend.org.uk>
+Standards-Version: 3.9.4.0
+Build-Depends: debhelper (>= 8)
+Package-List:
+ example deb devel extra arch=all
+Checksums-Sha1:
+ 2bc730f941db49de57e9678fb0b07bd95507bb44 236 example_1.0.orig-docs.tar.gz
+ 4bff9170ce9b10cb59937195c5ae2c73719fe150 373 example_1.0.orig.tar.gz
+ 86c31eba5e08c1765f8e557b97e59d7e1fd9c208 2108 example_1.0-1.100.debian.tar.xz
+Checksums-Sha256:
+ ad9671f6b25cdd9f0573f803f702448a45a45183db1d79701aa760bccbeed29c 236 example_1.0.orig-docs.tar.gz
+ a3ef7c951152f3ec754f96fd483457aa88ba06df3084e6f1cc7c25b669567c17 373 example_1.0.orig.tar.gz
+ 163f1a753f0ea382148df8d9553240d503781badf03c600946f1400534da1349 2108 example_1.0-1.100.debian.tar.xz
+Files:
+ cb0cb5487b1e5bcb82547396b4fe93e5 236 example_1.0.orig-docs.tar.gz
+ 599f47808a7754c66aea3cda1b3208d6 373 example_1.0.orig.tar.gz
+ 4b7f5d286eff2608107c77c96584a01a 2108 example_1.0-1.100.debian.tar.xz
diff --git a/tests/pkg-srcs/example_1.0-1.debian.tar.xz b/tests/pkg-srcs/example_1.0-1.debian.tar.xz
new file mode 100644
index 0000000..84ca563
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0-1.debian.tar.xz
Binary files differ
diff --git a/tests/pkg-srcs/example_1.0-1.dsc b/tests/pkg-srcs/example_1.0-1.dsc
new file mode 100644
index 0000000..bb65f6e
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0-1.dsc
@@ -0,0 +1,22 @@
+Format: 3.0 (quilt)
+Source: example
+Binary: example
+Architecture: all
+Version: 1.0-1
+Maintainer: Ian Jackson <ijackson@chiark.greenend.org.uk>
+Standards-Version: 3.9.4.0
+Build-Depends: debhelper (>= 8)
+Package-List:
+ example deb devel extra arch=all
+Checksums-Sha1:
+ 2bc730f941db49de57e9678fb0b07bd95507bb44 236 example_1.0.orig-docs.tar.gz
+ 4bff9170ce9b10cb59937195c5ae2c73719fe150 373 example_1.0.orig.tar.gz
+ f2398be1e588e10d11b20ee9bc5ca0eb16e4c158 1304 example_1.0-1.debian.tar.xz
+Checksums-Sha256:
+ ad9671f6b25cdd9f0573f803f702448a45a45183db1d79701aa760bccbeed29c 236 example_1.0.orig-docs.tar.gz
+ a3ef7c951152f3ec754f96fd483457aa88ba06df3084e6f1cc7c25b669567c17 373 example_1.0.orig.tar.gz
+ fd97c0fb879bfa8084f24a0d0f808a56beb533f17d92c808dc293ff297007925 1304 example_1.0-1.debian.tar.xz
+Files:
+ cb0cb5487b1e5bcb82547396b4fe93e5 236 example_1.0.orig-docs.tar.gz
+ 599f47808a7754c66aea3cda1b3208d6 373 example_1.0.orig.tar.gz
+ fd7840d249ee3dba5bdc3dcde7217bbe 1304 example_1.0-1.debian.tar.xz
diff --git a/tests/pkg-srcs/example_1.0.orig-docs.tar.gz b/tests/pkg-srcs/example_1.0.orig-docs.tar.gz
new file mode 100644
index 0000000..f8427aa
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0.orig-docs.tar.gz
Binary files differ
diff --git a/tests/pkg-srcs/example_1.0.orig.tar.gz b/tests/pkg-srcs/example_1.0.orig.tar.gz
new file mode 100644
index 0000000..e5d2cf3
--- /dev/null
+++ b/tests/pkg-srcs/example_1.0.orig.tar.gz
Binary files differ
diff --git a/tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.debian.tar.gz b/tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.debian.tar.gz
new file mode 100644
index 0000000..c376961
--- /dev/null
+++ b/tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.debian.tar.gz
Binary files differ
diff --git a/tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.dsc b/tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.dsc
new file mode 100644
index 0000000..e0161cd
--- /dev/null
+++ b/tests/pkg-srcs/sunxi-tools_1.2-2.~~dgittest.dsc
@@ -0,0 +1,22 @@
+Format: 3.0 (quilt)
+Source: sunxi-tools
+Binary: sunxi-tools
+Architecture: any
+Version: 1.2-2.~~dgittest
+Maintainer: Ian Campbell <ijc@hellion.org.uk>
+Homepage: http://linux-sunxi.org/Sunxi-tools
+Standards-Version: 3.9.5
+Vcs-Browser: http://git.debian.org/?p=collab-maint/sunxi-tools.git
+Vcs-Git: git://git.debian.org/collab-maint/sunxi-tools.git
+Build-Depends: debhelper (>= 9), pkg-config, libusb-1.0-0-dev, u-boot-tools
+Package-List:
+ sunxi-tools deb utils optional
+Checksums-Sha1:
+ 2457216dbbf5552c413753f7211f7be3db6aff54 35076 sunxi-tools_1.2.orig.tar.gz
+ 6f30698cd897b350a4f92b2b5dded69adca6f82e 5182 sunxi-tools_1.2-2.~~dgittest.debian.tar.gz
+Checksums-Sha256:
+ 03a63203ff79389e728d88ad705e546aa6362a6d08b9901392acb8639998ef95 35076 sunxi-tools_1.2.orig.tar.gz
+ 0a513f3254d245b59aaffbeb5c43159a6461617c1f6f3c6824646c4259cda406 5182 sunxi-tools_1.2-2.~~dgittest.debian.tar.gz
+Files:
+ dbc55f60559f9db497559176c3c753dd 35076 sunxi-tools_1.2.orig.tar.gz
+ a6ec0eb0d897b0121dc978fc00db2ea6 5182 sunxi-tools_1.2-2.~~dgittest.debian.tar.gz
diff --git a/tests/pkg-srcs/sunxi-tools_1.2.orig.tar.gz b/tests/pkg-srcs/sunxi-tools_1.2.orig.tar.gz
new file mode 100644
index 0000000..fe397fa
--- /dev/null
+++ b/tests/pkg-srcs/sunxi-tools_1.2.orig.tar.gz
Binary files differ
diff --git a/tests/run-all b/tests/run-all
index e2e2a6f..3877c76 100755
--- a/tests/run-all
+++ b/tests/run-all
@@ -1,13 +1,21 @@
-#!/bin/sh
+#!/bin/bash
set -e
# convenience script for running the tests outside adt-run
-if [ $# = 0 ]; then
- set `run-parts --list tests/tests`
+# usage: tests/using-intree tests/run-all
+
+set -o pipefail
+
+set +e
+jcpus=`perl -MSys::CPU -we 'printf "-j%d\n", 1.34 * Sys::CPU::cpu_count()'`
+set -e
+
+if [ $# != 0 ]; then
+ set TESTSCRIPTS="$*"
fi
-for f in $@; do
- echo ==================================================
- echo $f
- $f
- echo ==================================================
-done
-echo "ALL PASSED"
+
+mkdir -p tests/tmp
+
+(
+ set -x
+ exec make $jcpus -k -f tests/Makefile "$@"
+) 2>&1 |tee tests/tmp/run-all.log
diff --git a/tests/setup/examplegit b/tests/setup/examplegit
new file mode 100755
index 0000000..112e27a
--- /dev/null
+++ b/tests/setup/examplegit
@@ -0,0 +1,53 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+suitespecs+=' stable testing'
+
+t-tstunt-parsechangelog
+
+t-prep-newpackage example 1.0
+
+cd $p
+
+revision=1
+
+push-to () {
+ t-refs-same-start
+ t-ref-head
+ t-dgit build
+ t-dgit push --new $2
+ t-pushed-good $1 $2
+ t-archive-process-incoming $2
+}
+
+echo ancestor >which
+git add which
+t-commit Ancestor '' stable
+push-to master stable
+
+git checkout -b stable
+
+echo stable >which
+git add which
+t-commit Stable '' stable
+push-to stable stable
+
+git checkout master
+
+majorv=2
+revision=0
+
+echo sid >which
+git add which
+t-commit Sid
+push-to master sid
+
+echo sid-again >>which
+git add which
+t-commit Sid
+push-to master sid
+
+t-setup-done 'p v suitespecs majorv revision' "aq git mirror $p"
+
+t-ok
diff --git a/tests/setup/gnupg b/tests/setup/gnupg
new file mode 100755
index 0000000..43a5c96
--- /dev/null
+++ b/tests/setup/gnupg
@@ -0,0 +1,30 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+mkdir -p $tmp/gnupg
+cp $troot/gnupg/* $tmp/gnupg
+chmod go-rw $tmp/gnupg/*
+
+export GNUPGHOME=$tmp/gnupg
+
+cat >$tmp/gnupg/gpg-agent.conf <<END
+log-file $tmp/gnupg/AGENT.log
+END
+#debug-all
+
+setup='
+ : ${DGIT_TEST_REAL_GPG_AGENT:=$(type -p gpg-agent)}
+ export DGIT_TEST_REAL_GPG_AGENT=$(type -p gpg-agent)
+ export DGIT_STUNT_AGENT=$troot/tstunt/gpg-agent
+ export GNUPGHOME
+ t-tstunt gpg
+'
+
+eval "$setup"
+
+gpg --list-secret
+
+t-setup-done 'GNUPGHOME' 'gnupg' "$setup"
+
+t-ok
diff --git a/tests/tartree-edit b/tests/tartree-edit
index 2e0c017..40bd6e9 100755
--- a/tests/tartree-edit
+++ b/tests/tartree-edit
@@ -2,10 +2,74 @@
set -e
fail () { echo >&2 "$0: $*"; exit 1; }
+play=.git/tartree-edit-work
+
+git_manip_play () {
+ local wd; wd=$(pwd)
+ case "$wd" in
+ *.edit) fail "bad idea to run gitfetchinfo into a .edit tree!" ;;
+ esac
+ rm -rf $play
+ mkdir $play
+}
+
+gitfetchdiff_list () {
+ git for-each-ref --format '%(refname) %(objectname)' \
+ refs/remotes/"$1" \
+ | sed 's/^refs\/remotes\/[^\/]*\///' \
+ | sort >"$play/$2"
+}
+
+gitfetchdiff () {
+ local how="$1"
+ local a="$2"
+ local b="$3"
+ git_manip_play
+
+ rrab=refs/remotes/"$a+$b"
+
+ ulf=\
+"delete refs/remotes/$a/%l
+delete refs/remotes/$b/%l
+"
+ case "$how" in
+ diff)
+ git for-each-ref --format 'delete %(refname)' $rrab \
+ | git update-ref --stdin
+ ;;
+ merge)
+ ulf=\
+"create $rrab/%l
+$ulf"
+ ;;
+ *)
+ fail "internal error bad how ($how)"
+ ;;
+ esac
+
+ gitfetchdiff_list "$a" a
+ gitfetchdiff_list "$b" b
+
+ diff --old-line-format='' --new-line-format='' \
+ --unchanged-line-format="$ulf" \
+ $play/a $play/b >$play/updates \
+ || test $? = 1
+
+ git update-ref --stdin <$play/updates
+ exit 0
+}
+
case "$#.$1" in
2.edit|2.done) mode="$1"; arg="$2" ;;
-2.-*) fail "no options understood" ;;
-*) fail "usage: tartree-edit edit|done DIRECTORY" ;;
+3.gitfetchinfo) mode="$1"; arg="$2"; remote="$3" ;;
+3.gitfetchinfo-diff) gitfetchdiff diff "$2" "$3" ;;
+3.gitfetchinfo-merge) gitfetchdiff merge "$2" "$3" ;;
+?.-*) fail "no options understood" ;;
+*) fail "usage:
+ tartree-edit edit|done DIRECTORY|TARBALL
+ tartree-edit gitfetchinfo DIRECTORY|TARBALL REMOTE
+ tartree-edit gitfetchinfo-merge REMOTE-A REMOTE-B" ;;
+ # we don't document gitfetchinfo-diff because it's rather poor
esac
case "$arg" in
@@ -39,6 +103,83 @@ tryat_edit () {
fi
}
+gitfetchinfo_perhaps_commit () {
+ local m="$1"
+ set +e
+ git diff --cached --quiet --exit-code HEAD
+ local rc=$?
+ set -e
+ case "$rc" in
+ 0) return ;;
+ 1) git commit --allow-empty --author='tartree-edit <>' -m "$m" ;;
+ *) fail "git diff failed ($rc)" ;;
+ esac
+}
+
+tryat_gitfetchinfo () {
+ git_manip_play
+
+ if test -d "$b.edit"; then
+ cp -a "$b.edit"/. "$play"/.
+ else
+ exec 3<"$b.tar"
+ tar -C $play -f - <&3 -x
+ exec 3<&-
+ fi
+
+ local innerwd; innerwd="$(echo $play/*)"
+
+ git for-each-ref --format='%(refname)' refs/remotes >$play/l
+ perl -w -ne '
+ our %remerge;
+ use strict;
+ chomp;
+ next unless m#^refs/remotes/([^/]+)/#;
+ my $old = $_;
+ my $ab = $1;
+ my $rhs = $'\'';
+ my @ab = split /\+/, $ab;
+ next unless @ab == 2;
+ next unless (grep { $_ eq "'"$remote"'" } @ab) == 1;
+ $remerge{"@ab"} = 1;
+ print "update refs/remotes/$_/$rhs $old\n" or die $! foreach @ab;
+ print "delete $old\n" or die $!;
+ END {
+ open REMERGE, ">&3" or die $!;
+ print REMERGE "$_\n" or die $! foreach sort keys %remerge;
+ close REMERGE or die $!;
+ }
+ ' <$play/l >$play/unmerge 3>$play/remerge
+ git update-ref --stdin <$play/unmerge
+
+ git remote remove "$remote" 2>/dev/null ||:
+ git remote add "$remote" $innerwd
+ git fetch --no-tags -p "$remote" \
+ +"HEAD:refs/remotes/$remote/TT-HEAD"
+ cd $innerwd
+ GIT_AUTHOR_DATE=$(git log -n1 --pretty=format:'%ai')
+ GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE
+ export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
+ git checkout -b WORKTREE
+ gitfetchinfo_perhaps_commit 'UNCOMMITTED INDEX'
+ git add -Af .
+ gitfetchinfo_perhaps_commit 'UNCOMMITTED WORKING TREE'
+ cd ../../..
+ git fetch --no-tags "$remote" --refmap \
+ +"refs/*:refs/remotes/$remote/*" \
+ +"refs/*:refs/remotes/$remote/*"
+
+ exec 3<$play/remerge
+ # $play will be destroyed by what follows, but we have
+ # an fd open onto remerge, so this will work
+ while read <&3 a b; do
+ echo "Updating gitfetchinfo-merge $a $b"
+ "$0" gitfetchinfo-merge $a $b
+ done
+
+ exit 0
+}
+
tryat_done () {
local b="$1"
if test -d "$b.edit"; then
diff --git a/tests/tests/absurd-gitapply b/tests/tests/absurd-gitapply
new file mode 100755
index 0000000..62eb190
--- /dev/null
+++ b/tests/tests/absurd-gitapply
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-tstunt-parsechangelog
+
+t-archive example 1.0-1+absurd
+t-git-none
+
+t-expect-fail 'gbp pq import failed' \
+t-dgit --force-import-gitapply-no-absurd clone $p
+
+t-dgit clone $p
+
+cd $p
+grep moo moo
+
+t-ok
diff --git a/tests/tests/badcommit-rewrite b/tests/tests/badcommit-rewrite
new file mode 100755
index 0000000..b7fc701
--- /dev/null
+++ b/tests/tests/badcommit-rewrite
@@ -0,0 +1,47 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+t-tstunt-parsechangelog
+
+cd example
+
+suite=stable
+
+t-commit 'No changes, just send to stable' '' stable
+
+t-make-badcommit
+git reset --hard $badcommit
+
+t-dgit -wgf build
+t-dgit push --overwrite=1.2 stable
+t-archive-process-incoming stable
+
+rstable=refs/remotes/dgit/dgit/stable
+
+t-dgit fetch stable
+t-has-parent-or-is $rstable $badcommit
+
+fixup=${DGIT_BADCOMMIT_FIXUP-dgit-badcommit-fixup}
+
+cd $tmp/git/$p.git
+$fixup --real
+
+cd $tmp/$p
+git symbolic-ref HEAD >../sym.before
+git rev-parse HEAD >../ref.before
+
+$fixup --real
+
+git symbolic-ref HEAD >../sym.after
+git rev-parse HEAD >../ref.after
+diff ../sym.before ../sym.after
+set +e; diff ../ref.before ../ref.after; rc=$?; set -e; test $rc = 1
+
+t-dgit fetch stable
+
+t-expect-fail "child $rstable lacks parent $badcommit" \
+t-has-parent-or-is $rstable $badcommit
+
+t-ok
diff --git a/tests/tests/build-modes b/tests/tests/build-modes
new file mode 100755
index 0000000..c476ec8
--- /dev/null
+++ b/tests/tests/build-modes
@@ -0,0 +1,35 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-build-modes
+
+bm-prep
+
+for act in \
+ 'build' \
+ 'build -S' \
+ 'build -b' \
+ 'build -B' \
+ 'build -A' \
+ 'build -F' \
+ 'build -g' \
+ 'build -G' \
+ build-source \
+; do
+ bm-guess-e-source-e-targets "$act"
+
+ case $act in
+ build-source)
+ cleanmodes="$cleanmodes_all"
+ ;;
+ *)
+ cleanmodes="$cleanmodes_default"
+ ;;
+ esac
+
+ real_act="$act"
+
+ bm-act-iterate
+done
+
+t-ok
diff --git a/tests/tests/build-modes-asplit b/tests/tests/build-modes-asplit
new file mode 100755
index 0000000..fa3bf8a
--- /dev/null
+++ b/tests/tests/build-modes-asplit
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-build-modes
+bm-alwayssplit
diff --git a/tests/tests/build-modes-gbp b/tests/tests/build-modes-gbp
new file mode 100755
index 0000000..50a6288
--- /dev/null
+++ b/tests/tests/build-modes-gbp
@@ -0,0 +1,39 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-build-modes
+
+t-dependencies git-buildpackage
+
+quirk-clean-fixup () {
+ case $cleanmode in
+ dpkg-source*)
+ # git-buildpackage runs the clean target twice somehow
+ perl -i.unfixed -ne '
+ print unless
+ $_ eq $last &&
+ $_ eq "EXAMPLE RULES TARGET clean\n";
+ $last = $_;
+ ' $bmgot
+ ;;
+ esac
+}
+bm_quirk_before_diff=quirk-clean-fixup
+
+bm-prep
+
+for act in \
+ 'gbp-build -S' \
+ 'gbp-build -b' \
+ 'gbp-build -B' \
+ 'gbp-build -A' \
+ 'gbp-build -F' \
+ 'gbp-build -g' \
+ 'gbp-build -G' \
+; do
+ bm-guess-e-source-e-targets "$act"
+ real_act="$act --git-ignore-branch"
+ bm-act-iterate
+done
+
+t-ok
diff --git a/tests/tests/build-modes-gbp-asplit b/tests/tests/build-modes-gbp-asplit
new file mode 100755
index 0000000..fa3bf8a
--- /dev/null
+++ b/tests/tests/build-modes-gbp-asplit
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-build-modes
+bm-alwayssplit
diff --git a/tests/tests/build-modes-sbuild b/tests/tests/build-modes-sbuild
new file mode 100755
index 0000000..19dcc8a
--- /dev/null
+++ b/tests/tests/build-modes-sbuild
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-build-modes
+
+t-dependencies sbuild
+t-restrict x-dgit-schroot-build
+
+bm_quirk_after_act=bm-quirk-sbuild-after-act
+bm-prep
+
+act="sbuild -c build --no-arch-all"
+real_act="$act"
+
+bm-guess-e-source-e-targets "$act"
+bm-act-iterate
+
+t-ok
diff --git a/tests/tests/clone-clogsigpipe b/tests/tests/clone-clogsigpipe
new file mode 100755
index 0000000..4465cf3
--- /dev/null
+++ b/tests/tests/clone-clogsigpipe
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-archive example 1.0-1.100
+t-git-none
+
+t-dgit clone $p
+
+t-ok
diff --git a/tests/tests/clone-gitnosuite b/tests/tests/clone-gitnosuite
new file mode 100755
index 0000000..83c996d
--- /dev/null
+++ b/tests/tests/clone-gitnosuite
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-archive pari-extra 3-1
+t-git-none
+cp -a $tmp/git/_template $dgitrepo
+
+t-dgit clone $p
+
+t-ok
diff --git a/tests/tests/clone-nogit b/tests/tests/clone-nogit
index 477eb55..e99dac3 100755
--- a/tests/tests/clone-nogit
+++ b/tests/tests/clone-nogit
@@ -22,4 +22,4 @@ t-dgit push
t-pushed-good dgit/sid
-echo ok.
+t-ok
diff --git a/tests/tests/clone-reprepro b/tests/tests/clone-reprepro
new file mode 100755
index 0000000..063a138
--- /dev/null
+++ b/tests/tests/clone-reprepro
@@ -0,0 +1,33 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-reprepro
+
+suitespecs+=' stable'
+
+t-dependencies reprepro
+t-reprepro
+t-tstunt-parsechangelog
+
+t-archive example 1.0-1
+t-git-none
+
+t-dgit clone $p
+
+cd $p
+t-cloned-fetched-good
+
+add_pari () {
+ local p
+ local v
+ local suite=stable
+ t-archive pari-extra 3-1
+}
+add_pari
+
+t-dgit fetch unstable,stable
+
+t-refs-same-start
+t-refs-same refs/remotes/dgit/sid,stable refs/remotes/dgit/sid
+
+t-ok
diff --git a/tests/tests/debpolicy-dbretry b/tests/tests/debpolicy-dbretry
new file mode 100755
index 0000000..a9f2334
--- /dev/null
+++ b/tests/tests/debpolicy-dbretry
@@ -0,0 +1,67 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-debpolicy
+t-prep-newpackage example 1.0
+
+cd $p
+revision=1
+git tag start
+
+echo DUMMY >some-file
+git add some-file
+git commit -m some-file
+taint=`git rev-parse HEAD`
+t-policy-admin taint --global $taint dummy
+git reset --hard HEAD~
+
+t-commit 'Make something to autotaint'
+t-dgit build
+t-dgit push --new
+
+autotaint=`t-git-get-ref "refs/tags/$tagpfx/$v"`
+
+git reset --hard start
+t-commit 'Thing which will autotaint'
+t-dgit build
+
+fifo=$tmp/sqlite-cmds
+mkfifo $fifo
+exec 3<>$fifo
+sqlite3 -interactive $tmp/git/policy.sqlite3 0<$fifo 3>&- &
+sqlite3_pid=$!
+
+taintsout=$tmp/sqlite3.taints-out
+echo >&3 'begin;';
+echo >&3 ".output $taintsout"
+echo >&3 'select * from taints;';
+echo >&3 'create table dummy (x text);'
+
+t-dgit build
+
+while ! grep $taint $taintsout; do sleep 0.1; done
+
+DGIT_RPD_TEST_DBLOOP_HOOK='
+ print STDERR "DBLOOP HOOK $sleepy\n";
+ $poldbh->sqlite_busy_timeout(2500);
+ if ($sleepy > 2) {
+ system '\''
+ set -ex
+ echo >'"$fifo"' "rollback;"
+ touch '"$tmp/sqlite3.rolled-back"'
+ '\'' and die "$? $!";
+ }
+' \
+t-dgit push --deliberately-not-fast-forward
+
+exec 3>&-
+wait $sqlite3_pid
+
+ls $tmp/sqlite3.rolled-back
+
+t-policy-admin list-taints | tee $tmp/taints-list | grep $autotaint
+
+t-ok
diff --git a/tests/tests/debpolicy-newreject b/tests/tests/debpolicy-newreject
new file mode 100755
index 0000000..1fa6751
--- /dev/null
+++ b/tests/tests/debpolicy-newreject
@@ -0,0 +1,121 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-debpolicy
+t-prep-newpackage example 1.0
+
+cd $p
+revision=1
+git tag start
+t-dgit setup-mergechangelogs
+
+echo FORBIDDEN >debian/some-file
+git add debian/some-file
+t-commit 'Commit a forbidden thing'
+
+bad=`git rev-parse HEAD:debian/some-file`
+t-policy-admin taint --global "$bad" "forbidden for testing"
+t-policy-admin taint --global "$bad" "forbidden for testing - again"
+
+t_expect_push_fail_hook+='
+t-git-objects-not-present "" $bad
+'
+
+t-dgit build
+t-expect-push-fail 'forbidden for testing' \
+t-dgit push --new
+t-git-dir-check enoent
+
+git reset --hard start
+t-commit 'will vanish from NEW'
+vanished=$v
+t-dgit build
+t-dgit push --new
+t-git-dir-check secret
+
+t-policy-periodic
+t-git-dir-check secret
+
+# pretend it vanished from new:
+rm $tmp/incoming/*
+t-archive-none example
+
+t-git-dir-time-passes
+
+t-policy-periodic
+t-git-dir-check enoent
+
+t-commit 'should require --deliberately...questionable'
+t-dgit build
+
+t-expect-push-fail E:"tag $tagpfx/${vanished//./\\.} referred to this object.*all previously pushed versions were found to have been removed" \
+t-dgit push --new
+t-git-dir-check enoent
+
+vanished=$v
+
+t-dgit push --new --deliberately-include-questionable-history
+t-git-dir-check secret
+
+t-policy-periodic
+t-git-dir-check secret
+
+t-archive-process-incoming new
+t-git-dir-time-passes
+
+t-policy-periodic
+t-git-dir-check secret
+
+oldobj=`git rev-parse HEAD`
+git reset --hard start
+t-commit 'should require --deliberately..not-ff'
+t-dgit build
+
+t-expect-push-fail "HEAD is not a descendant of the archive's version" \
+t-dgit push
+
+t-expect-push-fail \
+ "Package is in NEW and has not been accepted or rejected yet" \
+t-dgit --deliberately-TEST-dgit-only-not-fast-forward push
+
+t-dgit --deliberately-not-fast-forward push
+
+cd $dgitrepo
+t-expect-push-fail "Not a valid object name" \
+git cat-file -p $oldobj
+cd $tmp/$p
+
+t-commit 'Still not accepted, will override taint'
+t-dgit build
+t-expect-push-fail \
+ "Package is in NEW and has not been accepted or rejected yet" \
+t-dgit push
+
+t-dgit push --deliberately-include-questionable-history
+
+t-archive-process-incoming sid
+
+t-commit 'Check taint is no longer there'
+t-dgit build
+t-dgit push
+
+git checkout -b stoats $tagpfx/$vanished
+t-commit 'Simulate accidentally building on rejected version'
+t-dgit build
+t-expect-push-fail "HEAD is not a descendant of the archive's version" \
+t-dgit push
+
+: "check that uploader can't force it now"
+t-expect-push-fail "not fast forward on dgit branch" \
+t-dgit --deliberately-not-fast-forward push
+
+t-dgit pull
+t-dgit build
+t-expect-push-fail \
+ 'Reason: rewound suite sid; --deliberately-not-fast-forward specified' \
+t-dgit push
+
+t-ok
diff --git a/tests/tests/debpolicy-quilt-gbp b/tests/tests/debpolicy-quilt-gbp
new file mode 100755
index 0000000..915f9d3
--- /dev/null
+++ b/tests/tests/debpolicy-quilt-gbp
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-alt-test
diff --git a/tests/tests/defdistro-dsd-clone-drs b/tests/tests/defdistro-dsd-clone-drs
new file mode 100755
index 0000000..1a1c138
--- /dev/null
+++ b/tests/tests/defdistro-dsd-clone-drs
@@ -0,0 +1,14 @@
+#!/bin/bash
+. tests/lib
+
+t-restrict x-dgit-intree-only
+t-restrict x-dgit-git-only
+
+export DGIT_TEST_DSD_CLONE_DRS_HOOK='
+ t-git-config dgit.default.distro test-dummy
+ url=$(git config dgit-distro.test-dummy.git-url)
+ t-git-config dgit-distro.test-dummy/push.git-url "$url"
+ t-git-config dgit-distro.test-dummy.git-url nosuchprotocol://
+'
+
+t-alt-test
diff --git a/tests/tests/defdistro-mirror b/tests/tests/defdistro-mirror
new file mode 100755
index 0000000..8c63451
--- /dev/null
+++ b/tests/tests/defdistro-mirror
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-dependencies rsync
+t-alt-test
diff --git a/tests/tests/defdistro-rpush b/tests/tests/defdistro-rpush
new file mode 100755
index 0000000..915f9d3
--- /dev/null
+++ b/tests/tests/defdistro-rpush
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-alt-test
diff --git a/tests/tests/defdistro-setup b/tests/tests/defdistro-setup
new file mode 100755
index 0000000..24faa33
--- /dev/null
+++ b/tests/tests/defdistro-setup
@@ -0,0 +1,19 @@
+#!/bin/bash
+. tests/lib
+
+t-defdistro
+
+t-select-package example
+t-worktree 1.0
+
+cd example
+
+t-git-config dgit-suite.DGIT-SETUP-TREE.distro test-dummy
+
+t-dgit setup-useremail
+t-dgit setup-mergechangelogs
+t-dgit setup-gitattributes
+
+t-dgit setup-new-tree
+
+t-ok
diff --git a/tests/tests/distropatches-reject b/tests/tests/distropatches-reject
new file mode 100755
index 0000000..75f43db
--- /dev/null
+++ b/tests/tests/distropatches-reject
@@ -0,0 +1,81 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-archive ruby-rails-3.2 3.2.6-1
+t-git-none
+
+cp $troot/pkg-srcs/${p}_3.2.6.orig.tar.gz .
+t-worktree test
+cd $p
+
+t-dgit --quilt=smash -wgf quilt-fixup
+
+build () {
+ t-dgit -wg --dpkg-buildpackage:-d build
+}
+
+expect-fail-distro-series () {
+ local why=$1; shift
+ t-expect-fail \
+ E:"Found active distro-specific series file.*(.*$why.*)" \
+ "$@"
+}
+
+mkdir -p debian/patches
+
+cat >debian/patches/boo <<'END'
+Description: add boo
+Author: Ian Jackson <ijackson@chiark.greenend.org.uk>
+
+---
+
+--- a/boo
++++ b/boo
+@@ -0,0 +1 @@
++content
+END
+
+echo boo >debian/patches/test-dummy.series
+
+git add debian/patches/boo
+git add debian/patches/test-dummy.series
+t-commit 'Add boo (on test-dummy)' 3.2.6-2
+
+expect-fail-distro-series 'distro being accessed' \
+build
+
+defaultvendor=$(perl -we '
+ use Dpkg::Vendor;
+ print lc Dpkg::Vendor::get_current_vendor
+')
+git mv debian/patches/test-dummy.series \
+ debian/patches/$defaultvendor.series
+t-commit 'Move boo (to default vendor)' 3.2.6-3
+
+expect-fail-distro-series 'current vendor' \
+build
+
+git mv debian/patches/$defaultvendor.series \
+ debian/patches/test-dummy-aside.series
+t-commit 'Move boo (to test-dummy-aside)' 3.2.6-4
+
+build
+
+DEB_VENDOR=test-dummy-aside \
+expect-fail-distro-series DEB_VENDOR \
+t-dgit push
+
+t-dgit push
+
+cd ..
+perl -i~ -pe 's/^Dgit:.*\n//' incoming/${p}_${v}.dsc
+t-archive-process-incoming sid
+
+rm -rf $p
+
+DEB_VENDOR=test-dummy-aside \
+expect-fail-distro-series DEB_VENDOR \
+t-dgit clone $p
+
+t-ok
diff --git a/tests/tests/downstream-gitless b/tests/tests/downstream-gitless
new file mode 100755
index 0000000..6b2df1b
--- /dev/null
+++ b/tests/tests/downstream-gitless
@@ -0,0 +1,111 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-reprepro
+
+t-dependencies reprepro
+t-setup-import examplegit
+t-tstunt-parsechangelog
+
+
+# rewrite some things, so we test the rewriting code
+
+mkdir map
+cd map
+git init
+cd ..
+
+record-map () {
+ old=$(t-git-get-ref-exact "refs/original/$r")
+ new=$(t-git-get-ref-exact "$r")
+ if [ "$old" = "$new" ]; then return; fi
+ echo >>$tmp/map/map "$old $new"
+}
+
+filter () {
+ git filter-branch \
+ --msg-filter 'sed s/Sid/Spong/' \
+ --tag-name-filter cat \
+ ^archive/test-dummy/2.0 \
+ "$@"
+ for r in "$@"; do
+ record-map "$r"
+ done
+}
+
+cd $p
+filter \
+ refs/heads/master \
+ refs/remotes/dgit/dgit/sid
+
+t-ref-head
+
+cd ../git/$p.git
+filter \
+ refs/dgit/sid
+
+cd $tmp/map
+git add map
+git commit -m 'by test suite'
+git push $tmp/git/$p.git master:refs/dgit-rewrite/map
+cd ..
+
+
+suitespecs=avon
+t-reprepro-cfg ds- downstream
+t-reprepro-setup ds-
+distro=''
+
+
+dscf=$tmp/mirror/pool/main/example_1.1.dsc
+t-reprepro-includedsc avon $dscf ds-
+t-reprepro-regen ds-
+
+
+mkdir $p.import
+cd $p.import
+git init
+t-dgit import-dsc $dscf x
+cd ..
+
+t-git-config dgit-suite.avon.distro downstream
+t-git-config dgit-distro.downstream.git-check false
+
+t-dgit clone example avon example.avon
+
+
+perl -i -pe 's/ test-dummy / unknown-distro / if m/^Dgit:/' $dscf
+cd $p.import
+
+t-expect-fail 'hinted url with protocol file which is unsafe' \
+t-dgit import-dsc $dscf xunk
+
+t-git-config dgit.dsc-url-proto-ok.file true
+t-dgit import-dsc $dscf xunk
+
+cd ..
+
+
+dscf=$tmp/mirror/pool/main/example_2.1.dsc
+t-reprepro-includedsc avon $dscf ds-
+t-reprepro-regen ds-
+
+
+cd $p.avon
+t-dgit fetch
+t-ref-same refs/remotes/dgit/dgit/avon
+
+cd ../$p.import
+git init
+t-dgit import-dsc $dscf +x
+t-ref-same refs/heads/x
+git show x | grep Spong
+
+t-expect-fail 'Your git tree does not have that object' \
+t-dgit --no-chase-dsc-distro import-dsc $dscf +y
+
+cd ../$p
+t-dgit --no-chase-dsc-distro import-dsc $dscf +y
+git show y | grep Sid
+
+t-ok
diff --git a/tests/tests/drs-clone-nogit b/tests/tests/drs-clone-nogit
index dcfb193..915f9d3 100755
--- a/tests/tests/drs-clone-nogit
+++ b/tests/tests/drs-clone-nogit
@@ -1,4 +1,4 @@
#!/bin/bash
set -e
. tests/lib
-t-drs-test
+t-alt-test
diff --git a/tests/tests/drs-push-masterupdate b/tests/tests/drs-push-masterupdate
new file mode 100755
index 0000000..8457b59
--- /dev/null
+++ b/tests/tests/drs-push-masterupdate
@@ -0,0 +1,50 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-drs
+t-tstunt-parsechangelog
+
+t-prep-newpackage example 1.0
+
+cd $p
+
+git tag common-ancestor
+
+revision=1
+t-dgit build
+t-dgit push --new
+
+push_and_check () {
+ git push $dgitrepo $1
+
+ oldmaster=`cd $dgitrepo && t-git-get-ref refs/heads/master`
+
+ t-refs-same-start
+ git checkout master
+ t-commit 'Empty update'
+ t-dgit build
+ t-dgit push --new
+
+ t-pushed-good master
+}
+
+t-check-master-undisturbed () {
+ local master; master=`t-git-get-ref refs/heads/master`
+ if [ x$master != x$oldmaster ]; then fail "bad update to master"; fi
+}
+
+t_check_pushed_master=t-check-master-undisturbed
+
+git checkout -b divergent common-ancestor
+git commit --allow-empty -m 'Has common ancestor'
+git push $dgitrepo HEAD:master
+
+push_and_check HEAD:master
+
+git checkout --orphan newroot
+git commit --allow-empty -m 'Has no common ancestor'
+
+push_and_check +HEAD:master
+
+t-ok
diff --git a/tests/tests/drs-push-rejects b/tests/tests/drs-push-rejects
index f6f8882..afaed4c 100755
--- a/tests/tests/drs-push-rejects
+++ b/tests/tests/drs-push-rejects
@@ -5,42 +5,24 @@ set -e
t-drs
t-git-none
-p=pari-extra
+t-select-package pari-extra
t-worktree drs
cd $p
-reporefs () {
- (set -e
- if test -d $tmp/git/$p.git; then
- cd $tmp/git/$p.git
- git show-ref
- fi)
-}
+git remote set-url origin \
+ "ext::$troot/drs-git-ext %S /pari-extra.git"
mustfail () {
- local wantmsg="$1"; shift
- reporefs >$tmp/show-refs.pre-push
- set +e
- git push origin "$@" 2>&1 |tee $tmp/mustfail.txt
- ps="${PIPESTATUS[*]}"
- set -e
- case $ps in
- "0 0") fail "push unexpectedly succeeded (instead of: $wantmsg)" ;;
- *" 0") ;;
- *) fail "tee failed" ;;
- esac
- if ! fgrep "$wantmsg" $tmp/mustfail.txt >/dev/null; then
- fail "error message not found"
- fi
- reporefs >$tmp/show-refs.post-push
- diff $tmp/show-refs.{pre,post}-push
+ local mpat="$1"; shift
+ t-expect-push-fail "$mpat" \
+ git push origin "$@"
}
mustsucceed () {
- reporefs >$tmp/show-refs.pre-push
+ t-reporefs pre-push
git push origin "$@"
- reporefs >$tmp/show-refs.post-push
+ t-reporefs post-push
if diff $tmp/show-refs.{pre,post}-push >$tmp/show-refs.diff; then
fail "no refs updated"
fi
@@ -48,16 +30,20 @@ mustsucceed () {
prep () {
local suite=$1
- local csuite=$2
+ csuite=$2
cp $tmp/masters/* $tmp/.
tag_signer='-u Senatus'
tag_message="$p release $version for $suite ($csuite) [dgit]"
- tag_name=debian/$version
+ re-prep
+}
+re-prep () {
+ tag_name=$tagpfx/$version
push_spec1="HEAD:refs/dgit/$csuite"
push_spec2="refs/tags/$tag_name"
push_spec="$push_spec1 $push_spec2"
}
mktag () {
+ t-git-next-date
git tag -f $tag_signer -m "$tag_message" $tag_name "$@"
}
@@ -86,7 +72,7 @@ for h in object type tag; do
cat badtag.asc >>badtag
set +e
- LC_ALL=C git hash-object -w -t tag badtag >badtag.hash 2>badtag.err
+ LC_MESSAGES=C git hash-object -w -t tag badtag >badtag.hash 2>badtag.err
rc=$?
set -e
@@ -101,6 +87,8 @@ for h in object type tag; do
git update-ref refs/tags/$tag_name $badtag
mustfail 'multiple headers '$h' in signed tag object' $push_spec
+
+ t-expect-fsck-fail $badtag
done
done
@@ -119,10 +107,11 @@ mustfail 'sid != sponge' HEAD:refs/dgit/sponge $push_spec2
prep unstable sid
mktag
mustfail 'push is missing tag ref update' $push_spec1
-mustfail 'push is missing head ref update' $push_spec2
+mustfail 'push is missing head ref update' +$push_spec2
mustfail 'pushing unexpected ref' $push_spec HEAD:refs/wombat
mustfail 'pushing multiple heads' $push_spec HEAD:refs/dgit/wombat
-mustfail 'pushing multiple tags' $push_spec HEAD:refs/tags/debian/wombat
+mustfail E:'pushing multiple tags|pushing too many similar tags' \
+ $push_spec HEAD:refs/tags/$tagpfx/wombat
prep unstable sid
mktag
@@ -149,18 +138,36 @@ mktag HEAD~:
mustfail 'tag refers to wrong kind of object' $push_spec
prep unstable sid
-tag_name=debian/wombat
+tag_name=$tagpfx/wombat
mktag
-#git update-ref debian/$version debian/wombat
+#git update-ref $tagpfx/$version $tagpfx/wombat
mustfail 'tag name in tag is wrong' \
- refs/tags/debian/wombat:refs/tags/debian/$version $push_spec1
+ refs/tags/$tagpfx/wombat:refs/tags/$tagpfx/$version $push_spec1
+t-make-badcommit
+git checkout -b broken $badcommit
+prep unstable sid
+mktag
+mustfail "corrupted object $badcommit" $push_spec
+
+git checkout dgit/sid
prep unstable sid
mktag
mustsucceed $push_spec # succeeds
mktag
-mustfail 'not replacing previously-pushed version' $push_spec
+mustfail 'push is missing head ref update' $push_spec1 +$push_spec2
+
+git commit --allow-empty -m 'Dummy update'
+mktag
+mustfail 'not replacing previously-pushed version' +$push_spec1 +$push_spec2
+
+t-newtag
+re-prep
+mktag
+mustfail 'not replacing previously-pushed version' +$push_spec1 +$push_spec2
+
+git reset --hard HEAD~
prep_dm_mangle () {
prep unstable sid
@@ -196,4 +203,4 @@ mustfail "not in permissions list although in keyring" $push_spec
prep_dm_mangle ''
mustsucceed $push_spec # succeeds
-echo ok.
+t-ok
diff --git a/tests/tests/dsd-clone-drs b/tests/tests/dsd-clone-drs
new file mode 100755
index 0000000..6065c5f
--- /dev/null
+++ b/tests/tests/dsd-clone-drs
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-restrict x-dgit-intree-only
+t-restrict x-dgit-git-only
+
+t-dsd
+eval "$DGIT_TEST_DSD_CLONE_DRS_HOOK"
+
+cd $tmp
+t-dgit clone-dgit-repos-server drs-cloned
+
+cd drs-cloned
+ls -al infra/dgit-repos-server
+
+t-ok
diff --git a/tests/tests/dsd-clone-nogit b/tests/tests/dsd-clone-nogit
new file mode 100755
index 0000000..915f9d3
--- /dev/null
+++ b/tests/tests/dsd-clone-nogit
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-alt-test
diff --git a/tests/tests/dsd-divert b/tests/tests/dsd-divert
new file mode 100755
index 0000000..3020a56
--- /dev/null
+++ b/tests/tests/dsd-divert
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-dsd
+rm $drs_dispatch/repos
+echo '* drs' >>$drs_dispatch/diverts
+t-chain-test fetch-somegit-notlast
diff --git a/tests/tests/fetch-localgitonly b/tests/tests/fetch-localgitonly
index 1177ed6..7d603b2 100755
--- a/tests/tests/fetch-localgitonly
+++ b/tests/tests/fetch-localgitonly
@@ -8,9 +8,13 @@ t-worktree 3-1
cd $p
old=`git rev-parse HEAD`
+# pretend that we previously fetched 3-1 (otherwise, dgit
+# is entitled to, and will, make a new history)
+git update-ref refs/remotes/dgit/dgit/sid refs/heads/dgit/sid
+
t-dgit pull
t-cloned-fetched-good
t-has-ancestor $old
-echo ok.
+t-ok
diff --git a/tests/tests/fetch-somegit-notlast b/tests/tests/fetch-somegit-notlast
index 15b9404..63abe8a 100755
--- a/tests/tests/fetch-somegit-notlast
+++ b/tests/tests/fetch-somegit-notlast
@@ -12,4 +12,4 @@ cd $p
t-cloned-fetched-good
t-has-ancestor debian/3-1
-echo ok.
+t-ok
diff --git a/tests/tests/gbp-orig b/tests/tests/gbp-orig
new file mode 100755
index 0000000..9a4937c
--- /dev/null
+++ b/tests/tests/gbp-orig
@@ -0,0 +1,77 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+t-tstunt-debuild
+t-tstunt-lintian
+
+t-archive-none example
+t-git-none
+t-worktree 1.0
+
+cd $p
+
+: '----- construct an unpatched branch with patches -----'
+
+git checkout patch-queue/quilt-tip
+gbp pq export
+: 'now on quilt-tip'
+git add debian/patches
+git commit -m 'Commit patch queue'
+
+: '----- construct an upstream branch -----'
+
+git checkout --orphan upstream
+git reset --hard
+git clean -xdf
+
+tar --strip-components=1 -xf $troot/pkg-srcs/${p}_1.0.orig.tar.gz
+
+mkdir docs
+cd docs
+tar --strip-components=1 -xf $troot/pkg-srcs/${p}_1.0.orig-docs.tar.gz
+cd ..
+
+git add -Af .
+git commit -m 'Import 1.0'
+git tag upstream/1.0
+
+git checkout quilt-tip
+t-git-pseudo-merge -m 'gbp-orig pseudomerge' upstream
+
+v=1.0-1
+
+: '----- let gbp build a .orig for comparison -----'
+
+gbp buildpackage --git-ignore-branch --git-no-sign-tags -us -uc
+
+mkdir ../gbp-output
+mv ../*1.0* ../gbp-output/.
+rm -f ../*.changes
+
+: '----- now do it ourselves -----'
+
+t-dgit -wgf --dgit-view-save=split.b gbp-build --git-ignore-branch
+
+t-dgit -wgf --quilt=gbp clean # gbp leaves dirty trees :-/
+
+t-dgit -wgf --dgit-view-save=split.p --quilt=gbp push --new
+
+t-gbp-pushed-good
+
+: '----- check .origs are the same -----'
+
+# if gbp weren't weird about .gitignore we could just debdiff the .dscs
+
+for d in . gbp-output; do
+ cd $tmp/$d
+ mkdir tar-x
+ cd tar-x
+ tar zxf ../${p}_${v%-*}.orig.tar.gz
+done
+
+cd $tmp
+diff -ruN gbp-output/tar-x tar-x
+
+t-ok
diff --git a/tests/tests/gitattributes b/tests/tests/gitattributes
new file mode 100755
index 0000000..9e1c246
--- /dev/null
+++ b/tests/tests/gitattributes
@@ -0,0 +1,256 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-dependencies bsdgames
+t-dependencies man-db git-man
+t-tstunt-parsechangelog
+
+t-archive-none example
+t-git-none
+bv=1.0
+t-worktree $bv
+
+: ----- prepare badnesses -----
+
+mkdir af
+
+badattr1 () {
+ local filename=$1
+ local attrspec=$2
+ echo >>af/$filename "Test file with $attrspec"
+ printf >>af/$filename 'crlf: \r\n'
+ echo >>af/$filename 'id $Id: $'
+ echo >>af/$filename 'id $Id: SPLARK $'
+ echo >>gitattrs "af/$filename" "$attrspec"
+}
+
+badattr () {
+ attrname=$1; shift
+ badattr1 $attrname-set $attrname
+ badattr1 $attrname-unset -$attrname
+ badattr1 $attrname-unspec \!$attrname
+ local val
+ for val in "$@"; do
+ badattr1 $attrname=$val $attrname=$val
+ done
+}
+
+# xxx want to make each of these files into a quilt patch
+
+t-git-config core.eol crlf
+
+badattr text auto
+badattr eol lf crlf
+badattr ident
+
+t-git-config filter.dgit-test-crazy-f.smudge '/usr/games/rot13 2'
+t-git-config filter.dgit-test-crazy-f.clean '/usr/games/rot13 24'
+t-git-config filter.dgit-test-crazy-f.requrired true
+
+badattr filter dgit-test-crazy-f
+
+badattr diff
+badattr merge text binary union
+badattr whitespace
+badattr export-ignore
+badattr export-subst
+badattr delta
+badattr encoding no-such-encoding
+
+man gitattributes \
+| perl -ne 'print $1,"\n" if m/^ *(\w[-a-z]*)$/' \
+> grepped-attrs
+
+exec <grepped-attrs
+while read attr; do
+ badattr $attr
+done
+
+sha256sum af/* >sums
+
+# ----- common to source formats -----
+
+sfmt_setup () {
+ v=$1
+ sfmt=$2
+
+ pdb=$p.$sfmt
+
+ local addpatch=${sfmt}_addpatch
+ local convert=${sfmt}_convert
+
+ cp -a $p $pdb-edit
+ cd $pdb-edit
+
+ $convert
+
+ dch -v $v -m convert
+
+ rm -rf .git
+
+ cp ../gitattrs .gitattributes
+ $addpatch gitattrs
+
+ cp -a ../af .
+ $addpatch files
+
+ cp ../sums .
+ $addpatch sums
+
+ dpkg-source -b .
+
+ cd ..
+}
+
+sums_check () {
+ # caller should cd into working directory, set
+ # $sums $branch
+ # and check out $branch
+
+ sha256sum af/* >../$sums.checkout
+ diff -U0 ../sums ../$sums.checkout
+
+ for f in af/*; do
+ git cat-file blob "refs/heads/$branch:$f" \
+ | sha256sum \
+ | sed -e 's#-$#'$f'#' \
+ >>../$sums
+ done
+
+ diff -U0 ../sums ../$sums
+}
+
+sums_check_broken () {
+ # caller should cd into working directory, set
+ # $sums
+ # and check out the broken branch
+
+ sha256sum af/* >../$sums.broken
+
+ for s in ../sums ../$sums.broken; do
+ sed 's/[0-9a-f]* //' $s >$s.nosums
+ done
+ diff -U0 ../sums.nosums ../$sums.broken.nosums
+ set +e
+ diff -U0 ../sums ../$sums.broken
+ rc=$?
+ set -e
+ test $rc = 1
+}
+
+t-dgit-warn-check () {
+ local warnok=$1; shift
+ # warnok should be 0 if the warning is expected
+ # 1 if the warning is NOT expected
+
+ local err=stderr.$wd
+
+ LC_MESSAGES=C t-dgit "$@" 2>&1 |tee ../$err
+
+ set +e
+ egrep 'warning: .* contains \.gitattributes' ../$err
+ rc=$?
+ set -e
+
+ test "$rc" = "$warnok"
+}
+
+sfmt_import () {
+ inst=$1
+ dgitargs=$2
+ branch="import.$sfmt-$inst"
+ dscf=${p}_${v}.dsc
+ sums=sums.$sfmt-$inst
+ wd=$pdb-import-$inst
+
+ mkdir $wd
+ cd $wd
+ git init
+
+ t-dgit-warn-check 0 $dgitargs import-dsc ../$dscf +$branch.broken
+
+ git checkout $branch.broken
+
+ sums_check_broken
+
+ t-dgit setup-new-tree
+
+ t-dgit-warn-check 1 $dgitargs import-dsc ../$dscf +$branch
+ git checkout $branch
+ touch af/*
+ git reset --hard
+
+ sums_check
+
+ cd ..
+}
+
+: ----- generate the orig -----
+
+origtar=${p}_${bv}.orig.tar.gz
+
+tar --exclude=debian --exclude=.git -zcf $origtar $p
+
+: ----- test 1.0 native -----
+
+native_addpatch () { :; }
+native_convert () { :; }
+
+sfmt_setup 1.1 native
+sfmt_import norm
+
+: ----- test 1.0 diff -----
+
+diff_addpatch () { :; }
+diff_convert () { :; }
+
+sfmt_setup 1.1 diff
+sfmt_import norm
+
+: ----- test "3.0 (quilt)" -----
+
+quilt_addpatch () {
+ pname=$1
+ cat >../editor.pl <<END
+ next if m/^$/..0;
+ s{^(description:).*}{\$1 dgit test patch $pname}i;
+ \$_='' if m/^ /;
+END
+ EDITOR="perl -pi $tmp/editor.pl" dpkg-source -iX --commit . $pname
+ test -f debian/patches/$pname
+}
+
+quilt_convert () {
+ mkdir -p debian/source
+ echo '3.0 (quilt)' >debian/source/format
+}
+
+sfmt_setup 1.0-1 quilt
+sfmt_import norm
+sfmt_import absurd --force-import-gitapply-absurd
+
+: ----- 'test clone (with "3.0 (quilt)")' -----
+
+mv $origtar ${dscf%.dsc}.* $tmp/mirror/pool/main/
+t-archive-query sid
+
+t-dgit-warn-check 0 -cdgit.default.setup-gitattributes=false \
+ clone $p sid $p.clone.broken
+cd $p.clone.broken
+
+sums=$p.clone.broken
+sums_check_broken
+
+cd ..
+
+t-dgit-warn-check 1 clone $p sid $p.clone
+
+cd $p.clone
+sums=sums.clone
+branch=dgit/sid
+sums_check
+
+cd ..
+
+t-ok
diff --git a/tests/tests/gitconfig b/tests/tests/gitconfig
new file mode 100755
index 0000000..12b342b
--- /dev/null
+++ b/tests/tests/gitconfig
@@ -0,0 +1,38 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-prep-newpackage example 1.0
+
+cd $p
+
+t-dgit clean | tee ../t.output
+grep 'EXAMPLE RULES TARGET clean' ../t.output
+
+t-git-config dgit.default.clean-mode git
+
+t-dgit clean | tee ../t.output
+
+set +e
+grep 'EXAMPLE RULES TARGET clean' ../t.output
+rc=$?
+set -e
+test $rc = 1
+
+git config dgit.default.clean-mode dpkg-source-d
+
+t-dgit clean | tee ../t.output
+grep 'EXAMPLE RULES TARGET clean' ../t.output
+
+t-git-config dgit.default.opts-dpkg-buildpackage --dgit-fail-global
+git config --add dgit.default.opts-dpkg-buildpackage --dgit-fail-foo
+git config --add dgit.default.opts-dpkg-buildpackage --dgit-fail-bar
+
+t-expect-fail '--dgit-fail-global --dgit-fail-foo --dgit-fail-bar' \
+t-dgit clean
+
+t-dgit -cdgit.default.clean-mode=none clean
+
+t-ok
diff --git a/tests/tests/import-dsc b/tests/tests/import-dsc
new file mode 100755
index 0000000..073ba7b
--- /dev/null
+++ b/tests/tests/import-dsc
@@ -0,0 +1,100 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-tstunt-parsechangelog
+
+t-setup-import examplegit
+
+p=example
+
+check-import () {
+ path=$1
+ v=$2
+ opts=$3
+ branch=t.$v
+
+ dsc=${path}/${p}_${v}.dsc
+ t-dgit $opts import-dsc $dsc $branch
+
+ git checkout $branch
+
+ check-imported $dsc
+}
+
+check-imported () {
+ local dsc=$1
+ (
+ rm -rf ../t.unpack
+ mkdir ../t.unpack
+ cd ../t.unpack
+ dpkg-source -x $dsc
+ )
+
+ git checkout HEAD~0
+ git branch -D u.$v ||:
+ git checkout -b u.$v $branch
+ git rm -rf .
+ git clean -xdf
+ cp -al ../t.unpack/*/. .
+ git add -Af .
+
+ git diff --stat --exit-code
+}
+
+cd $p
+
+check-import ../mirror/pool/main 1.2
+
+dgit12=`git rev-parse HEAD`
+
+dsc2=../mirror/pool/main/${p}_2.0.dsc
+
+git checkout $branch
+t-expect-fail 'is checked out - will not update' \
+t-dgit import-dsc $dsc2 $branch
+
+git checkout HEAD~0
+
+t-expect-fail 'Not fast forward' \
+t-dgit import-dsc $dsc2 $branch
+
+t-expect-fail 'Not fast forward' \
+t-dgit import-dsc $dsc2 ..$branch
+
+t-dgit import-dsc $dsc2 +$branch
+check-imported $dsc2
+
+cd ..
+mkdir $p.2
+cd $p.2
+
+git init
+
+check-import $troot/pkg-srcs 1.0-1
+
+t-expect-fail "Your git tree does not have that object" \
+check-import ../mirror/pool/main 1.2 --no-chase-dsc-distro
+
+check-import ../mirror/pool/main 1.2 --force-import-dsc-with-dgit-field
+
+v=1.0-1.100
+dsc2=$troot/pkg-srcs/${p}_${v}.dsc
+
+t-expect-fail E:'Branch.*already exists' \
+t-dgit import-dsc $dsc2 $branch
+
+git branch merge-reset
+t-dgit import-dsc $dsc2 ..$branch
+t-has-ancestor merge-reset $branch
+
+git push . +merge-reset:$branch
+
+t-dgit import-dsc $dsc2 +$branch
+
+mb=$(t-git-merge-base merge-reset $branch)
+test "x$mb" = x
+
+t-expect-fail 'signature check failed' \
+t-dgit import-dsc --require-valid-signature $dsc2 +$branch
+
+t-ok
diff --git a/tests/tests/import-maintmangle b/tests/tests/import-maintmangle
new file mode 100755
index 0000000..31a5f88
--- /dev/null
+++ b/tests/tests/import-maintmangle
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-import-chk
+
+t-tstunt-parsechangelog
+
+t-select-package example
+v=1.0
+t-worktree $v
+
+cd $p
+
+dsc=${p}_${v}.dsc
+
+chk () {
+ local perl="$1"
+ local unperl="$2"
+ git checkout master~0
+ perl -i -pe "next unless m/^ -- /; $perl" debian/changelog
+ git commit --allow-empty -a -m "perl $perl"
+ (cd ..; dpkg-source -i\.git -I.git -b $p)
+ t-dgit import-dsc ../$dsc +x
+ git checkout x~0
+ t-import-chk-authorship
+}
+
+massage () {
+ perl -i~ -pe "$unperl" "$1"
+}
+
+import_chk_changelog_massage=massage
+
+chk
+
+chk 's/Ian Jackson/Ian Jackson, SPQR/' \
+ 's/Ian Jackson, SPQR/Ian Jackson SPQR/'
+
+chk 's/Ian Jackson/"Ian Jackson, SPQR"/'
+
+t-ok
diff --git a/tests/tests/import-native b/tests/tests/import-native
new file mode 100755
index 0000000..1e09343
--- /dev/null
+++ b/tests/tests/import-native
@@ -0,0 +1,69 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+t-tstunt-parsechangelog
+
+mkdir $tmp/aside
+
+versions=""
+for f in $(find $tmp/mirror -name \*.dsc | sort); do
+ perl -i -pe '
+ $_="" if m/^-----BEGIN PGP SIGNED/..!m/\S/;
+ $_="" if m/^-----BEGIN PGP SIGNATURE/..0;
+ $_="" if m/^Dgit: /;
+ ' $f
+ mv $f $tmp/aside/.
+ version="${f%.dsc}"
+ version="${version##*/${p}_}"
+ versions+=" $version"
+done
+
+echo $versions
+
+rm -rf $tmp/git/$p.git
+t-archive-none $p
+
+cd $p
+
+lrref=refs/remotes/dgit/dgit/sid
+
+git update-ref -d $lrref
+
+for v in $versions; do
+ git show-ref
+
+ mv $tmp/aside/${p}_${v}.dsc $tmp/mirror/pool/main/
+ t-archive-query
+
+ t-dgit fetch
+
+ set +e
+ git merge-base HEAD remotes/dgit/dgit/sid
+ rc=$?
+ set -e
+ test $rc = 1
+
+ t-refs-same-start
+ t-ref-same-exact refs/tags/$p/$v:
+ t-ref-same-exact refs/remotes/dgit/dgit/sid:
+
+ first_imp=first-import/$v
+ git tag first-import/$v $lrref
+
+ if [ "$lastv_imp" ]; then
+ git update-ref $lrref $lastv_imp
+
+ t-git-next-date
+ t-dgit fetch
+
+ t-refs-same-start
+ t-ref-same $first_imp
+ t-ref-same $lrref
+ fi
+
+ lastv_imp=$this_imp
+done
+
+t-ok
diff --git a/tests/tests/import-nonnative b/tests/tests/import-nonnative
new file mode 100755
index 0000000..3568563
--- /dev/null
+++ b/tests/tests/import-nonnative
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-import-chk
+
+t-tstunt-parsechangelog
+
+# 1.0 with diff
+t-import-chk pari-extra 3-1
+
+# 3.0 (quilt), multiple patches, multiple origs
+t-import-chk example 1.0-1
+
+# 3.0 (quilt), single-debian-patch, one orig
+t-import-chk sunxi-tools 1.2-2.~~dgittest
+
+t-ok
diff --git a/tests/tests/import-tarbomb b/tests/tests/import-tarbomb
new file mode 100755
index 0000000..9b7f65a
--- /dev/null
+++ b/tests/tests/import-tarbomb
@@ -0,0 +1,49 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-import-chk
+
+t-tstunt-parsechangelog
+
+mangle1 () {
+ rm -f ${1}_*
+ t-import-chk1 "$@"
+ cd $tmp/mirror/pool/main
+ dpkg-source -x ${p}_${v}.dsc td
+ orig=${p}_${v%-*}.orig.tar.gz
+ tar zxf $orig
+ rm $orig ${p}_${v}.*
+ cd $p
+ mkdir urk
+ echo urk >urk/urk
+ export GZIP=-1
+}
+mangle2 () {
+ cd ..
+ dpkg-source -b td
+ rm -rf $p td
+ cd $tmp
+ t-archive-none $p
+ t-archive-query
+ t-import-chk2
+}
+
+# 3.0 (quilt), multiple patches, tarbomb orig
+mangle1 example 1.0-1
+tar zvcf ../$orig *
+mangle2
+
+# 3.0 (quilt), multiple patches, tarbomb orig with dot
+mangle1 example 1.0-1
+tar zvcf ../$orig .
+mangle2
+
+# 3.0 (quilt), multiple patches, tarbomb orig with dot and .git and .pc
+mangle1 example 1.0-1
+git init
+mkdir .pc
+echo SPONG >.pc/SPONG
+tar zvcf ../$orig .
+mangle2
+
+t-ok
diff --git a/tests/tests/inarchivecopy b/tests/tests/inarchivecopy
new file mode 100755
index 0000000..3f84881
--- /dev/null
+++ b/tests/tests/inarchivecopy
@@ -0,0 +1,79 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+t-tstunt-parsechangelog
+
+cd $p
+git checkout -b dgit/stable dgit/dgit/stable
+cd ..
+
+t-inarchive-copy () {
+ local vm=$1
+ local from=${2:-sid}
+ local to=${3:-stable}
+ egrep "^${vm//./\\.}" aq/package.$from.$p >>aq/package.$to.$p
+ t-aq-archive-updated $to $p
+}
+
+copy-check-good () {
+ git diff $vtag
+ t-refs-same refs/remotes/dgit/dgit/$tosuite
+ t-ref-head
+ t-has-parent-or-is HEAD $vtag
+}
+
+copy-check () {
+ local vm=$1
+ local tosuite=${2:-stable}
+ t-inarchive-copy $vm '' $tosuite
+
+ vtag=$(v=$vm t-v-tag)
+
+ cd $p
+ t-refs-same-start
+ t-dgit fetch $tosuite
+ git merge --ff-only dgit/dgit/$tosuite
+
+ copy-check-good
+ local fetched; fetched=$(t-sametree-parent HEAD)
+ cd ..
+
+ rm -rf example.cloned
+ t-dgit clone $p $tosuite example.cloned
+
+ cd example.cloned
+ t-refs-same-start
+ copy-check-good
+ local cloned; cloned=$(t-sametree-parent HEAD)
+ cd ..
+
+ rm -rf example.initd
+ mkdir example.initd
+ cd example.initd
+ git init
+ t-refs-same-start
+ t-dgit -p $p fetch $tosuite
+ git reset --hard refs/remotes/dgit/dgit/$tosuite
+ copy-check-good
+ local initd; initd=$(t-sametree-parent HEAD)
+ cd ..
+
+ t-refs-same-start
+ t-ref-same-val fetched $fetched
+ t-ref-same-val cloned $cloned
+ t-ref-same-val initd $initd
+}
+
+copy-check 2.0
+
+copy-check 2.1
+
+cd $p
+git checkout -b dgit/testing $(v=1.1 t-v-tag)
+cd ..
+
+copy-check 2.1 testing
+
+t-ok
diff --git a/tests/tests/mirror b/tests/tests/mirror
new file mode 100755
index 0000000..4947688
--- /dev/null
+++ b/tests/tests/mirror
@@ -0,0 +1,80 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-mirror
+
+t-dependencies rsync
+
+t-drs
+
+: ---- "basic test" ----
+
+t-tstunt-parsechangelog
+t-prep-newpackage example 1.0
+
+t-mirror-setup
+
+cd $p
+revision=1
+t-dgit build
+t-dgit push --new
+
+t-check-mirrored
+
+: ---- "stunt ssh test" ----
+
+sentinel=$tmp/stunt-ssh-sentinel
+
+cat <<END >$tmp/stunt-ssh
+#!/bin/sh
+set -ex
+: $sentinel
+cat >&2 $sentinel
+shift # eat HOST
+sh -c "\$*"
+END
+chmod +x $tmp/stunt-ssh
+
+t-mirror-set rsyncssh=$tmp/stunt-ssh
+t-mirror-set remoterepos=HOST:$reposmirror
+
+# mirror should fail due to lack of stunt-ssh-sentinel
+
+t-commit-build-push-expect-log "stunt ssh test" \
+ E:'mirror hook failed: .*exited'
+
+ls -al $queuedir/$p.a
+t-check-not-mirrored
+
+touch $sentinel
+
+t-mirror-hook backlog
+t-check-mirrored
+
+: ----- "stall timeout test" -----
+
+rm -f $sentinel
+mkfifo $sentinel
+
+t-mirror-set hooktimeout=5
+
+t-commit-build-push-expect-log "stall timeout test" \
+ E:'mirror hook failed: .*timeout'
+
+t-check-not-mirrored
+
+exec 3<>$sentinel
+exec 3>&-
+
+attempts=100
+while [ -f $queuedir/$p.lock ]; do
+ if [ $attempts = 0 ]; then \
+ fail "timed out waiting for lock to go away"
+ fi
+ attempts=$(( $attempts - 1 ))
+ sleep 0.1
+done
+
+t-check-mirrored
+
+t-ok
diff --git a/tests/tests/mirror-debnewgit b/tests/tests/mirror-debnewgit
new file mode 100755
index 0000000..59b96ef
--- /dev/null
+++ b/tests/tests/mirror-debnewgit
@@ -0,0 +1,26 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-mirror
+
+t-dependencies rsync
+
+t-debpolicy
+
+t-archive pari-extra 3-1
+t-git-none
+
+t-mirror-setup
+
+t-dgit clone $p
+
+cd $p
+t-cloned-fetched-good
+
+t-commit 'test commit' 3-2
+
+t-dgit build
+t-dgit push
+t-check-mirrored
+
+t-ok
diff --git a/tests/tests/mirror-private b/tests/tests/mirror-private
new file mode 100755
index 0000000..1e885ae
--- /dev/null
+++ b/tests/tests/mirror-private
@@ -0,0 +1,30 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-mirror
+
+t-dependencies rsync
+
+t-debpolicy
+
+t-tstunt-parsechangelog
+t-prep-newpackage example 1.0
+
+t-mirror-setup
+
+cd $p
+revision=1
+
+t-reporefs master
+
+t-dgit build
+t-dgit push --new
+
+t-check-not-mirrored
+t-files-notexist $reposmirror/$p.*
+
+t-archive-process-incoming sid
+t-policy-periodic
+t-check-mirrored
+
+t-ok
diff --git a/tests/tests/mismatches-contents b/tests/tests/mismatches-contents
new file mode 100755
index 0000000..ea0d724
--- /dev/null
+++ b/tests/tests/mismatches-contents
@@ -0,0 +1,24 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-prep-newpackage example 1.0
+
+ln -s $troot/pkg-srcs/${p}_${v%-*}.orig.tar.* .
+
+cd $p
+
+v=1.0-1
+dch -v $v -D unstable -m 'Make a revision'
+echo foo >us-file
+git add us-file debian/changelog
+git commit -m "Commit $v"
+
+t-dgit build-source
+
+t-expect-fail 'debian/TRASH' \
+t-dgit push --new
+
+t-ok
diff --git a/tests/tests/mismatches-dscchanges b/tests/tests/mismatches-dscchanges
new file mode 100755
index 0000000..85c7086
--- /dev/null
+++ b/tests/tests/mismatches-dscchanges
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-prep-newpackage example 1.0
+
+cd $p
+revision=1
+
+check () {
+ local fext=$1
+ local emsgpat=$2
+
+ t-dgit -wgf build-source
+
+ perl -i~ -pe 's/^ ([0-9a-f])/ sprintf " %x", (hex $1)^1 /e' \
+ ../*.$fext
+
+ t-expect-fail "$emsgpat" \
+ t-dgit -wgf push --new
+}
+
+check dsc E:'dpkg-source.*error.*checksum'
+check changes E:'dgit.*hash or size.*varies'
+
+# and finally check that our test is basically working
+
+t-dgit -wgf build-source
+
+t-dgit -wgf push --new
+
+t-ok
diff --git a/tests/tests/multisuite b/tests/tests/multisuite
new file mode 100755
index 0000000..d39475b
--- /dev/null
+++ b/tests/tests/multisuite
@@ -0,0 +1,57 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+t-tstunt-parsechangelog
+
+cd $p
+
+rsta=$(t-git-get-ref refs/remotes/dgit/dgit/stable)
+rsid=$(t-git-get-ref refs/remotes/dgit/dgit/sid)
+
+multi-good () {
+ t-refs-same-start
+ t-refs-same refs/remotes/dgit/dgit/stable
+ t-ref-same-val "previous stable" $rsta
+
+ t-refs-same-start
+ t-refs-same refs/remotes/dgit/dgit/sid
+ t-ref-same-val "previous sid" $rsid
+
+ t-refs-same-start
+ t-refs-same refs/remotes/dgit/dgit/stable,sid
+ t-ref-same-val "previous combined" $rcombined
+}
+
+t-dgit fetch stable,unstable
+
+rcombined=$(t-git-get-ref refs/remotes/dgit/dgit/stable,sid)
+
+multi-good
+
+cd ..
+
+t-dgit clone --no-rm-on-error $p stable,unstable ./$p.clone
+
+cd $p.clone
+
+multi-good
+
+t-commit bogus 3.0 stable,unstable
+t-expect-fail "does not support multiple" \
+t-dgit -wgf build
+
+cd ..
+
+t-dgit clone --no-rm-on-error $p stable ./$p.pull
+cd $p.pull
+git checkout -b x
+git commit --allow-empty -m X
+t-dgit pull stable,unstable
+
+multi-good
+
+t-has-parent-or-is HEAD $rcombined
+
+t-ok
diff --git a/tests/tests/newtag-clone-nogit b/tests/tests/newtag-clone-nogit
new file mode 100755
index 0000000..915f9d3
--- /dev/null
+++ b/tests/tests/newtag-clone-nogit
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-alt-test
diff --git a/tests/tests/oldnewtagalt b/tests/tests/oldnewtagalt
new file mode 100755
index 0000000..098fe19
--- /dev/null
+++ b/tests/tests/oldnewtagalt
@@ -0,0 +1,25 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+t-tstunt-parsechangelog
+
+cd $p
+
+test-push () {
+ t-commit "$1"
+ t-dgit build-source
+ t-dgit push
+}
+
+for count in 1 2; do
+ t-oldtag
+ test-push "oldtag $count"
+
+ t-newtag
+ test-push "newtag $count"
+done
+
+t-ok
+
diff --git a/tests/tests/oldtag-clone-nogit b/tests/tests/oldtag-clone-nogit
new file mode 100755
index 0000000..915f9d3
--- /dev/null
+++ b/tests/tests/oldtag-clone-nogit
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+. tests/lib
+t-alt-test
diff --git a/tests/tests/orig-include-exclude b/tests/tests/orig-include-exclude
new file mode 100755
index 0000000..a37f997
--- /dev/null
+++ b/tests/tests/orig-include-exclude
@@ -0,0 +1,21 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+suitespecs+=' stable'
+
+. $troot/lib-orig-include-exclude
+
+ofb=example_1.1.orig.tar
+zcat $ofb.gz >$ofb.SPONG
+gzip -1Nv $ofb.SPONG
+mv $ofb.SPONG.gz $ofb.gz
+
+cd $p
+
+test-push-1 1.1-1.3 '' stable
+
+t-expect-fail E:'archive contains .* with different checksum' \
+test-push-2 --new
+
+t-ok
diff --git a/tests/tests/orig-include-exclude-chkquery b/tests/tests/orig-include-exclude-chkquery
new file mode 100755
index 0000000..f8eac57
--- /dev/null
+++ b/tests/tests/orig-include-exclude-chkquery
@@ -0,0 +1,33 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-git-config dgit-distro.test-dummy.archive-query ftpmasterapi:
+# ^ that will crash if it gets unexpected file_in_archive queries
+
+# orig-include-exclude will set origs and usvsns
+update-files_in_archive () {
+ for o in $origs; do for usvsn in $usvsns; do \
+ of=${p}_${v%-*}.${o}.tar.gz
+ pat="%/${of//_/\\_}"
+ # curl url-decodes these things so we have to have literals
+ find $tmp/mirror -name $of | \
+ xargs -r sha256sum | \
+ perl -pe '
+ BEGIN { print "["; }
+ chomp;
+ s/^/{"sha256sum":"/;
+ s/ /","filename":"/;
+ s/$/"}$delim/;
+ $delim=",";
+ END { print "]\n"; }
+ ' \
+ >$tmp/aq/"file_in_archive/$pat"
+ done; done
+}
+
+test_push_2_hook=update-files_in_archive
+
+. $troot/lib-orig-include-exclude
+
+t-ok
diff --git a/tests/tests/overwrite-chkclog b/tests/tests/overwrite-chkclog
new file mode 100755
index 0000000..fee2181
--- /dev/null
+++ b/tests/tests/overwrite-chkclog
@@ -0,0 +1,50 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+
+cd example
+
+suite=stable
+
+t-commit 'No changes, just send to stable' '' stable
+
+t-dgit -wgf build
+
+t-expect-fail 'Perhaps debian/changelog does not mention' \
+t-dgit push --overwrite stable
+
+t-dgit setup-mergechangelogs
+
+t-expect-fail 'fix conflicts and then commit the result' \
+git merge dgit/dgit/stable
+
+git checkout master which
+EDITOR=: git commit
+
+perl -i~ -pe 's/^(\w+ \(\S+\)) stable/$1 UNRELEASED/ if $.>1' debian/changelog
+git add debian/changelog
+git commit -m 'UNRELEASED changelog'
+
+t-dgit -wgf build
+
+t-expect-fail E:'Distribution.*is UNRELEASED' \
+t-dgit push --overwrite stable
+
+git revert --no-edit 'HEAD^{/UNRELEASED changelog}'
+
+t-dgit -wgf build
+
+perl -i~ -pe 's/^(\w+ \(\S+)(\) stable)/$1+X$2/ if $.>1' debian/changelog
+git add debian/changelog
+git commit -m 'Break changelog'
+
+t-expect-fail 'Perhaps debian/changelog does not mention' \
+t-dgit push --overwrite stable
+
+git revert --no-edit 'HEAD^{/Break changelog}'
+
+t-dgit push --overwrite stable
+
+t-ok
diff --git a/tests/tests/overwrite-junk b/tests/tests/overwrite-junk
new file mode 100755
index 0000000..e11d1f8
--- /dev/null
+++ b/tests/tests/overwrite-junk
@@ -0,0 +1,22 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+
+cd example
+
+suite=stable
+
+t-commit 'No changes, just send to stable' '' stable
+
+t-dgit -wgf build
+
+(
+ : "make a bit of a wrongness, which we still want to be able to overwrite"
+ cd $tmp/git/$p.git; git tag -f $tagpfx/1.2 $tagpfx/1.1
+)
+
+t-dgit push --overwrite=1.2 stable
+
+t-ok
diff --git a/tests/tests/overwrite-splitbrains b/tests/tests/overwrite-splitbrains
new file mode 100755
index 0000000..0ef03f6
--- /dev/null
+++ b/tests/tests/overwrite-splitbrains
@@ -0,0 +1,27 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-gbp-example-prep-no-ff
+t-newtag
+
+t-dgit --quilt=gbp --dgit-view-save=split.b build-source
+
+t-dgit fetch
+
+t-refs-same-start
+t-ref-head
+
+t-expect-fail 'check failed (maybe --overwrite is needed' \
+t-dgit --quilt=gbp --dgit-view-save=split.p push
+
+t-refs-same-start
+t-ref-head
+
+t-dgit --quilt=gbp --dgit-view-save=split.p --overwrite push
+
+t-gbp-pushed-good
+
+t-ok
diff --git a/tests/tests/overwrite-version b/tests/tests/overwrite-version
new file mode 100755
index 0000000..34301ac
--- /dev/null
+++ b/tests/tests/overwrite-version
@@ -0,0 +1,20 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-setup-import examplegit
+
+cd example
+
+suite=stable
+
+t-commit 'No changes, just send to stable' '' stable
+
+t-dgit -wgf build
+
+t-expect-fail 'HEAD is not a descendant' \
+t-dgit push stable
+
+t-dgit push --overwrite=1.2 stable
+
+t-ok
diff --git a/tests/tests/protocol-compat b/tests/tests/protocol-compat
new file mode 100755
index 0000000..fcbeedb
--- /dev/null
+++ b/tests/tests/protocol-compat
@@ -0,0 +1,83 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-reprepro
+
+t-setup-import examplegit
+t-tstunt-parsechangelog
+
+t-git-config dgit.default.distro foreign
+t-git-config dgit-distro.foreign.cmd-git false
+
+prep () {
+ dscf=$tmp/mirror/pool/main/example_$v.dsc
+}
+
+check () {
+ pd=$p.$suite
+ t-refs-same-start
+
+ t-archive-none $p
+ t-archive-query $suite
+
+ t-dgit clone $p $suite $pd
+ cd $pd
+ t-ref-head
+
+ $1
+
+ local distro=''
+ t-dgit import-dsc $dscf +imported
+ t-ref-same refs/heads/imported
+ cd ..
+}
+
+reset () {
+ cd ..
+ rm -rf $pd
+ mkdir $pd
+ cd $pd
+ git init
+}
+
+: ---------- newer ----------
+
+suite=sid
+v=2.1
+prep
+
+perl -i~ -pe 's/^Dgit: .*/$& EXTRA DATA\n TO BE IGNORED/' $dscf
+
+check reset
+
+: ---------- newline ----------
+
+suite=testing
+v=2.0
+prep
+
+perl -i~ -pe 's/^(Dgit: \w+ \S+ \S+) (.*)/$1\n $2 EXTRA/' $dscf
+
+check reset
+
+: ---------- older ----------
+
+suite=stable
+v=1.2
+prep
+
+perl -i -pe 's/^(Dgit: \w+).*/$1/' $dscf
+
+check
+
+: ---------- expect fail ----------
+
+pd=$p.fail
+
+t-git-config dgit.default.old-dsc-distro downstream
+
+t-expect-fail 'no configured url and .dsc provides no hint' \
+t-dgit clone $p $suite $pd
+
+
+t-ok
diff --git a/tests/tests/push-buildproductsdir b/tests/tests/push-buildproductsdir
index 987c081..505d105 100755
--- a/tests/tests/push-buildproductsdir
+++ b/tests/tests/push-buildproductsdir
@@ -28,4 +28,4 @@ t-dgit --build-products-dir=../bpd push
t-pushed-good dgit/sid
-echo ok.
+t-ok
diff --git a/tests/tests/push-newpackage b/tests/tests/push-newpackage
index 9954b3f..79355e3 100755
--- a/tests/tests/push-newpackage
+++ b/tests/tests/push-newpackage
@@ -2,20 +2,14 @@
set -e
. tests/lib
-t-archive-none pari-extra
-t-git-none
-t-worktree 3-1
-v=3-1
-cd $p
-git branch -m dgit/sid master
-git remote rm dgit
+t-prep-newpackage pari-extra 3-1
+cd $p
t-refs-same-start
t-ref-head
-LANG=C t-dgit push 2>&1 \
- | tee /dev/stderr \
- | grep 'package appears to be new in this suite' >/dev/null
+t-expect-push-fail 'package appears to be new in this suite' \
+t-dgit push
t-dgit build
@@ -33,4 +27,4 @@ t-dgit push --new
t-pushed-good master
-echo ok.
+t-ok
diff --git a/tests/tests/push-nextdgit b/tests/tests/push-nextdgit
index 8d4a36f..d0436ab 100755
--- a/tests/tests/push-nextdgit
+++ b/tests/tests/push-nextdgit
@@ -22,4 +22,4 @@ t-dgit push
t-pushed-good dgit/sid
-echo ok.
+t-ok
diff --git a/tests/tests/quilt b/tests/tests/quilt
index 9a4b105..1a921b3 100755
--- a/tests/tests/quilt
+++ b/tests/tests/quilt
@@ -19,9 +19,7 @@ git fetch $tmp/incoming/$p dgit/sid:incoming
dummy=0
-for cherry in incoming~1 incoming~0; do
- git cherry-pick -x $cherry
-
+iteration () {
dummy=$(( $dummy + 1))
v=3.2.6-2~dummy${dummy}
@@ -29,9 +27,70 @@ for cherry in incoming~1 incoming~0; do
t-dgit --dpkg-buildpackage:-d build
t-dgit push
t-pushed-good dgit/sid
+}
+
+git cherry-pick -x incoming~1; iteration
+git cherry-pick -x incoming~0; iteration
+
+git fetch $tmp/incoming/$p incoming-branch:branch
+git checkout branch
+git rebase --onto dgit/sid incoming
+git checkout dgit/sid
+git merge branch
+iteration
+
+diff <<END - debian/patches/series
+ups-topic/ups-yml
+spongiform-upstream-new-file-incl-change
+zorkmid-options-=-42
+END
+
+for f in `cat debian/patches/series`; do
+ egrep -q '^From.*ijackson@chiark' debian/patches/$f
done
t-822-field ../${p}_${v}_*.changes Changes |
grep -Fx 'ruby-rails-3.2 (3.2.6-2~dummy1) unstable; urgency=low'
-echo ok.
+t-git-next-date
+
+# Now we are going to check that our dgit-generated patches round
+# trip to similar git commits when imported by gbp pq:
+
+git clean -xdf
+
+# We need to make a patches-unapplied version
+unpa=$(git log --pretty=format:'%H' --grep '^\[dgit import unpatched')
+git checkout -b for-gbp
+git reset "$unpa" .
+git reset HEAD debian
+git commit -m UNAPPY
+git reset --hard
+git clean -xdf
+
+export GIT_AUTHOR_NAME='Someone Else'
+export GIT_AUTHOR_EMAIL='else@example.com'
+export GIT_COMMITTER_NAME='Someone Else'
+export GIT_COMMITTER_EMAIL='else@example.com'
+
+gbp pq import
+
+for compare in $(git log --pretty='format:%H' \
+ --grep 'Change something in the upstream yml')
+do
+ git cat-file commit $compare >../this.cmp
+ # normalise
+ perl -i~$compare~ -0777 -pe '
+ s/\n+$//; $_ .= "\n";
+ s/^(?:committer|parent|tree) .*\n//gm;
+ s/\n+(\(cherry picked from .*\)\n)\n*/\n\n/m
+ and s/$/$1/;
+ s/\n+$//; $_ .= "\n";
+ ' ../this.cmp
+ if test -f ../last.cmp; then
+ diff -u ../last.cmp ../this.cmp
+ fi
+ mv ../this.cmp ../last.cmp
+done
+
+t-ok
diff --git a/tests/tests/quilt-gbp b/tests/tests/quilt-gbp
new file mode 100755
index 0000000..3ef89e8
--- /dev/null
+++ b/tests/tests/quilt-gbp
@@ -0,0 +1,61 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-gbp-example-prep
+
+t-expect-fail 'quilt fixup cannot be linear' \
+ t-dgit build-source
+
+t-git-config dgit-distro.test-dummy.dgit-tag-format new
+t-expect-fail 'requires split view so server needs to support' \
+t-dgit -wgf --quilt=gbp build-source
+t-newtag
+
+t-dgit --quilt=gbp --dgit-view-save=split.b1 build-source
+git rev-parse split.b1
+
+t-dgit --quilt=gbp --gbp-pq=no-such-command-gbp build-source
+
+echo spong >debian/pointless-for-dgit-test
+git add debian/pointless-for-dgit-test
+git commit -m Pointless
+
+t-expect-fail no-such-command-gbp \
+t-dgit --quilt=gbp --clean=git --gbp-pq=no-such-command-gbp build-source
+
+test-push-1 () {
+ t-refs-same-start
+ t-ref-head
+}
+
+test-push-2 () {
+ t-dgit --quilt=gbp --dgit-view-save=split.p push
+
+ t-gbp-pushed-good
+}
+
+test-push-1
+
+t-dgit --quilt=gbp --clean=git --dgit-view-save=split.b build-source
+
+t-expect-fail "HEAD specifies a different tree to $p" \
+ t-dgit push
+
+test-push-2
+
+echo wombat >>debian/pointless-for-dgit-test
+git add debian/pointless-for-dgit-test
+git commit -m 'Pointless 2'
+
+t-commit 'Check pseudomerge' 1.0-3
+
+test-push-1
+
+t-dgit --quilt=gbp --clean=git --dgit-view-save=split.b build-source
+
+test-push-2
+
+t-ok
diff --git a/tests/tests/quilt-gbp-build-modes b/tests/tests/quilt-gbp-build-modes
new file mode 100755
index 0000000..cd77dab
--- /dev/null
+++ b/tests/tests/quilt-gbp-build-modes
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-build-modes
+
+bm-gbp-example-acts \
+ 'build-source' \
+ 'build -b' \
+ 'build -S' \
+ 'gbp-build -S' \
+ 'gbp-build -b' \
+
+t-ok
diff --git a/tests/tests/quilt-gbp-build-modes-sbuild b/tests/tests/quilt-gbp-build-modes-sbuild
new file mode 100755
index 0000000..4c86bfe
--- /dev/null
+++ b/tests/tests/quilt-gbp-build-modes-sbuild
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-build-modes
+
+t-dependencies sbuild
+t-restrict x-dgit-schroot-build
+
+bm-gbp-example-acts \
+ 'sbuild -c build --arch-all' \
+
+t-ok
diff --git a/tests/tests/quilt-singlepatch b/tests/tests/quilt-singlepatch
new file mode 100755
index 0000000..3b6e228
--- /dev/null
+++ b/tests/tests/quilt-singlepatch
@@ -0,0 +1,39 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-archive sunxi-tools 1.2-2.~~dgittest
+t-git-none
+
+t-dgit clone $p
+cd $p
+t-cloned-fetched-good
+
+echo EXTRA-LINE-1 >>fel.c
+echo EXTRA-LINE-2 >>fel.c
+echo EXTRA-LINE-3 >>.gitignore
+
+git add fel.c .gitignore
+
+t-commit 'commit our stuff' 1.2-3
+
+t-dgit -wgf quilt-fixup
+
+t-refs-same-start
+t-ref-head
+
+t-dgit -wgf build-source
+
+t-dgit push
+t-pushed-good dgit/sid
+
+diff <<END - debian/patches/series
+debian-changes
+END
+
+diff <<END - <(ls debian/patches)
+debian-changes
+series
+END
+
+t-ok
diff --git a/tests/tests/quilt-splitbrains b/tests/tests/quilt-splitbrains
new file mode 100755
index 0000000..9f0ae5f
--- /dev/null
+++ b/tests/tests/quilt-splitbrains
@@ -0,0 +1,140 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+suitespecs+=' stable'
+
+# This test script tests each of the split brain quilt modes, and
+# --quilt=linear, with a tree suitable for each of those, and pushes
+# them in sequence. The idea is to check that each tree is rejected
+# by the wrong quilt modes, and accepted and processed correctly by
+# the right ones.
+
+t-tstunt-parsechangelog
+
+t-newtag
+
+# Easiest way to make a patches-unapplied but not-gbp tree is
+# to take the patches-unapplied tree and by-hand commit the .gitignore
+# changes as a debian patch.
+t-gbp-example-prep
+
+suite=sid
+
+want-success () {
+ local qmode=$1; shift
+ t-refs-same-start
+ t-ref-head
+
+ t-dgit "$@" --quilt=$qmode --dgit-view-save=split.b build-source
+
+ t-dgit "$@" --quilt=$qmode --dgit-view-save=split.p push
+ t-$qmode-pushed-good
+}
+
+
+echo "===== testing tree suitable for --quilt=gbp (only) ====="
+
+t-expect-fail 'grep: new-upstream-file: No such file or directory' \
+t-dgit --quilt=dpm build-source
+
+t-expect-fail 'git tree differs from result of applying' \
+t-dgit -wgf --quilt=dpm build-source
+
+t-expect-fail 'git tree differs from orig in upstream files' \
+t-dgit -wgf --quilt=unapplied build-source
+
+t-expect-fail 'This might be a patches-unapplied branch' \
+t-dgit -wgf build-source
+
+# testing success with --quilt=gbp are done in quilt-gbp test case
+
+
+echo "===== making tree suitable for --quilt=unapplied (only) ====="
+
+pf=debian/patches/test-gitignore
+
+cat >$pf <<END
+From: Senatus <spqr@example.com>
+Subject: Add .gitignore
+
+---
+END
+
+git diff /dev/null .gitignore >>$pf || test $? = 1
+echo ${pf##*/} >>debian/patches/series
+
+git add debian/patches
+git rm -f .gitignore
+git commit -m 'Turn gitignore into a debian patch'
+gitigncommit=`git rev-parse HEAD`
+
+t-commit unapplied 1.0-3
+
+echo "----- testing tree suitable for --quilt=unapplied (only) -----"
+
+t-expect-fail 'git tree differs from result of applying' \
+t-dgit -wgf --quilt=dpm build-source
+
+t-expect-fail 'gitignores: but, such patches exist' \
+t-dgit -wgf --quilt=gbp build-source
+
+t-expect-fail 'This might be a patches-unapplied branch' \
+t-dgit -wgf build-source
+
+want-success unapplied -wgf
+
+
+echo "===== making fully-applied tree suitable for --quilt-check ====="
+
+git checkout master
+git merge --ff-only dgit/dgit/sid
+
+t-commit vanilla 1.0-4
+
+echo "----- testing fully-applied tree suitable for --quilt-check -----"
+
+t-expect-fail 'gitignores: but, such patches exist' \
+t-dgit --quilt=dpm build-source
+
+t-expect-fail 'git tree differs from orig in upstream files' \
+t-dgit --quilt=gbp build-source
+
+t-expect-fail 'git tree differs from orig in upstream files' \
+t-dgit --quilt=unapplied build-source
+
+t-dgit --quilt=nofix build-source
+t-refs-same-start
+t-ref-head
+t-dgit --quilt=nofix push
+t-pushed-good-core
+
+
+echo "===== making tree suitable for --quilt=dpm (only) ====="
+
+git checkout master
+git merge --ff-only dgit/dgit/sid
+
+git revert --no-edit $gitigncommit
+
+t-commit dpmish 1.0-5
+
+echo "----- testing tree suitable for --quilt=dpm (only) -----"
+
+t-expect-fail 'git tree differs from orig in upstream files' \
+t-dgit -wgf --quilt=gbp build-source
+
+t-expect-fail 'git tree differs from orig in upstream files' \
+t-dgit -wgf --quilt=unapplied build-source
+
+t-expect-fail 'This might be a patches-applied branch' \
+t-dgit -wgf build-source
+
+want-success dpm
+
+suite=stable
+t-commit dpmish-stable 1.0-6 $suite
+
+want-success dpm --new
+
+t-ok
diff --git a/tests/tests/quilt-useremail b/tests/tests/quilt-useremail
new file mode 100755
index 0000000..f079395
--- /dev/null
+++ b/tests/tests/quilt-useremail
@@ -0,0 +1,27 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+t-archive example 1.0-1
+t-worktree 1.0
+t-git-none
+
+cd $p
+
+git checkout quilt-tip-2
+
+t-dgit -wgf fetch
+
+oe=other.email@example.com
+on='Hannibal Barca'
+
+git config --local user.email "$oe"
+git config --local user.name "$on"
+
+t-dgit -wgf --quilt=smash quilt-fixup
+
+git show | fgrep "$oe"
+git show | fgrep "$on"
+
+t-ok
diff --git a/tests/tests/rpush b/tests/tests/rpush
index c627788..71bbe2b 100755
--- a/tests/tests/rpush
+++ b/tests/tests/rpush
@@ -28,4 +28,4 @@ t-dgit --ssh=$troot/ssh rpush somehost:$tmp/$p
cd $tmp/$p
t-pushed-good dgit/sid
-echo ok.
+t-ok
diff --git a/tests/tests/spelling b/tests/tests/spelling
new file mode 100755
index 0000000..ed1290c
--- /dev/null
+++ b/tests/tests/spelling
@@ -0,0 +1,16 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-restrict x-dgit-git-only
+
+cd $root
+
+set +e
+git grep -q -i 'ps[u]edo'
+rc=$?
+set -e
+
+test $rc = 1
+
+t-ok
diff --git a/tests/tests/tag-updates b/tests/tests/tag-updates
new file mode 100755
index 0000000..824fd1e
--- /dev/null
+++ b/tests/tests/tag-updates
@@ -0,0 +1,37 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+t-prep-newpackage example 1.0
+
+cd $p
+revision=1
+t-dgit build
+t-dgit push --new
+
+tagref=`t-v-tag`
+tagname=${tn#refs/tags}
+
+(set -e
+ cd $dgitrepo
+ git tag -m UNWANTED unwanted dgit/sid)
+
+fetch-check () {
+ t-dgit fetch
+ t-ref-same-exact $tagref
+ t-refs-notexist refs/tags/unwanted
+}
+
+t-ref-same-exact $tagref
+fetch-check
+
+git tag -d $tagname
+fetch-check
+
+git tag -f -m BOGUS $tagname HEAD
+t-refs-same-start
+t-ref-same-exact $tagref
+fetch-check
+
+t-ok
diff --git a/tests/tests/test-list-uptodate b/tests/tests/test-list-uptodate
new file mode 100755
index 0000000..1e5f199
--- /dev/null
+++ b/tests/tests/test-list-uptodate
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+: "just verifies internal consistency of test suite"
+
+cd $root
+$troot/enumerate-tests gencontrol >$tmp/control-expected
+diff debian/tests/control $tmp/control-expected
+
+t-ok
diff --git a/tests/tests/trustingpolicy-replay b/tests/tests/trustingpolicy-replay
new file mode 100755
index 0000000..ad731f5
--- /dev/null
+++ b/tests/tests/trustingpolicy-replay
@@ -0,0 +1,85 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-git-config dgit.default.dep14tag no
+
+t-dsd
+t-policy dgit-repos-policy-trusting
+t-prep-newpackage example 1.0
+
+cd $p
+revision=1
+git tag start
+
+t-dgit build
+t-dgit push --new
+
+t-commit 'Prep v1.1 which will be rewound'
+t-dgit build
+t-dgit push
+
+t-rm-dput-dropping
+git checkout $tagpfx/1.0
+t-dgit build
+t-dgit push --deliberately-fresh-repo
+
+remote="`git config dgit-distro.test-dummy.git-url`/$p.git"
+
+t-expect-push-fail 'Replay of previously-rewound upload' \
+git push "$remote" \
+ $tagpfx/1.1 \
+ $tagpfx/1.1~0:refs/dgit/sid
+
+git checkout master
+
+
+: "More subtle replay prevention checks"
+
+prepare-replay () {
+ delib=$1
+
+ # We have to stop the pushes succeeding because if they work they
+ # record the tag, which prevents the replays. We are simulating
+ # abortive pushes (since we do want to avoid a situation where
+ # dangerous old signed tags can exist).
+ t-policy-nonexist
+
+ t-commit "request with $delib that we will replay"
+ t-dgit build
+ t-expect-push-fail 'system: No such file or directory' \
+ t-dgit push $delib
+
+ t-policy dgit-repos-policy-trusting
+
+ replayv=$v
+}
+
+attempt-replay () {
+ local mpat=$1
+ git show $tagpfx/$replayv | grep -e $delib
+ t-expect-push-fail "$mpat" \
+ git push "$remote" \
+ $tagpfx/$replayv \
+ +$tagpfx/$replayv~0:refs/dgit/sid
+}
+
+prepare-replay --deliberately-fresh-repo
+
+# simulate some other thing that we shouldn't delete
+git push $dgitrepo +master:refs/heads/for-testing
+
+attempt-replay 'does not declare previously heads/for-testing'
+
+prepare-replay --deliberately-not-fast-forward
+
+t-commit 'later version to stop not fast forward rewinding'
+t-dgit build
+t-dgit push
+
+attempt-replay "does not declare previously tags/$tagpfx/$v"
+
+
+t-ok
diff --git a/tests/tests/unrepresentable b/tests/tests/unrepresentable
new file mode 100755
index 0000000..0d02c6a
--- /dev/null
+++ b/tests/tests/unrepresentable
@@ -0,0 +1,52 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-prep-newpackage example 1.0
+
+ln -s $troot/pkg-srcs/${p}_${v%-*}.orig.tar.* .
+
+cd $p
+
+start () { git checkout quilt-tip~0; }
+attempt () { t-dgit -wgf --quilt=smash quilt-fixup; }
+
+badly-1 () {
+ wrongfn=$1
+ wrongmsg=$2
+ start
+}
+
+badly-2 () {
+ git commit -m "Commit wrongness $wrongfn ($wrongmsg)"
+ t-expect-fail E:"cannot represent change: $wrongmsg .*: $wrongfn" \
+ attempt
+}
+
+badly-1 symlink 'not a plain file'
+ ln -s TARGET symlink
+ git add symlink
+badly-2
+
+start
+ git rm src.c
+ git commit -m deleted
+attempt
+
+badly-1 src.c 'mode changed'
+ chmod +x src.c
+ git add src.c
+badly-2
+
+badly-1 new 'non-default mode'
+ echo hi >new
+ chmod 755 new
+ git add new
+badly-2
+
+start
+attempt
+
+t-ok
diff --git a/tests/tests/version-opt b/tests/tests/version-opt
new file mode 100755
index 0000000..22c35e7
--- /dev/null
+++ b/tests/tests/version-opt
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+# NOT t-tstunt-parsechangelog
+# because that doesn't honour the perl option corresponding to -v
+
+t-debpolicy
+t-prep-newpackage example 1.0
+
+cd $p
+revision=1
+git tag start
+t-dgit setup-mergechangelogs
+
+t-dgit build-source
+t-dgit push --new
+
+t-archive-process-incoming sid
+
+for v in 1.1 1.2; do
+ dch -v $v -D unstable -m "Update to version $v"
+
+ git add debian/changelog
+ git commit -m "Commit changelog for $v"
+
+ t-dgit build-source
+done
+
+fgrep 'Update to version 1.1' ../${p}_${v}_source.changes
+
+t-ok
diff --git a/tests/tstunt/Dpkg/Changelog/Parse.pm b/tests/tstunt/Dpkg/Changelog/Parse.pm
new file mode 100644
index 0000000..d69b7df
--- /dev/null
+++ b/tests/tstunt/Dpkg/Changelog/Parse.pm
@@ -0,0 +1,71 @@
+# -*- perl -*-
+#
+# Copyright (C) 2015-2016 Ian Jackson
+#
+# Some bits stolen from the proper Dpkg::Changelog::Parse
+# (from dpkg-dev 1.16.16):
+#
+# Copyright (C) 2005, 2007 Frank Lichtenheld <frank@lichtenheld.de>
+# Copyright (C) 2009 Raphael Hertzog <hertzog@debian.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package Dpkg::Changelog::Parse;
+
+use strict;
+use warnings;
+
+our $VERSION = "1.00";
+
+use Dpkg::Control::Changelog;
+
+use base qw(Exporter);
+our @EXPORT = qw(changelog_parse);
+
+die +(join " ", %ENV)." ?" if $ENV{'DGIT_NO_TSTUNT_CLPARSE'};
+
+sub changelog_parse {
+ my (%options) = @_; # largely ignored
+
+#use Data::Dumper;
+#print STDERR "CLOG PARSE ", Dumper(\%options);
+#
+# We can't do this because lots of things use `since' which
+# we don't implement, and it's the test cases that arrange that
+# the since value happens to be such that we are to print one output.
+#
+# foreach my $k (keys %options) {
+# my $v = $options{$k};
+# if ($k eq 'file') { }
+# elsif ($k eq 'offset') { die "$v ?" unless $v <= 1; } # wtf, 1==0 ?
+# elsif ($k eq 'count') { die "$v ?" unless $v == 1; }
+# else { die "$k ?"; }
+# }
+
+ $options{'file'} //= 'debian/changelog';
+
+ open P, "dpkg-parsechangelog -l$options{'file'} |" or die $!;
+
+ my $fields = Dpkg::Control::Changelog->new();
+ $fields->parse(\*P, "output of stunt changelog parser");
+
+#use Data::Dumper;
+#print STDERR "PARSE $0 ", Dumper($fields);
+
+ close P or die "$! $?";
+
+ return $fields;
+}
+
+1;
diff --git a/tests/tstunt/debuild b/tests/tstunt/debuild
new file mode 100755
index 0000000..2b2ca71
--- /dev/null
+++ b/tests/tstunt/debuild
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+echo "DGIT TEST STUNT DEBUILD $*" >&2
+"${DGIT_TEST_REAL_DEBUILD}" --preserve-env --preserve-envvar PATH "$@"
diff --git a/tests/tstunt/dpkg-parsechangelog b/tests/tstunt/dpkg-parsechangelog
new file mode 100755
index 0000000..6a9198a
--- /dev/null
+++ b/tests/tstunt/dpkg-parsechangelog
@@ -0,0 +1,78 @@
+#!/usr/bin/perl -w
+#
+# In an example:
+#
+# $ time dpkg-parsechangelog >/dev/null
+#
+# real 0m0.712s
+# user 0m0.656s
+# sys 0m0.048s
+# $ time ~/things/Dgit/dgit/tests/tstunt/dpkg-parsechangelog >/dev/null
+#
+# real 0m0.016s
+# user 0m0.000s
+# sys 0m0.012s
+# $
+
+$SIG{__WARN__} = sub { die $_[0]; }; # no use of system, so we avoid #793471
+
+my $infile = "debian/changelog";
+
+#print STDERR ">@ARGV<\n";
+
+my @orgargv = @ARGV;
+
+if (@ARGV && $ARGV[0] =~ s/^-l//) {
+ $infile = shift @ARGV;
+}
+
+if (@ARGV) {
+ my $strip = $0;
+ $strip =~ s#/[^/]+$## or die "$0 ?";
+ foreach my $k (qw(PATH PERLLIB)) {
+ my @opath = defined $ENV{$k} ? split /\:/, $ENV{$k} : ();
+ my @npath = grep { $_ ne $strip } @opath;
+ @npath != @opath or die "$0 $k ".($ENV{$k}//"(undef)")." ?";
+ $ENV{$k} = join ':', @npath;
+ delete $ENV{$k} if !@npath;
+ }
+ die if $ENV{'DGIT_NO_TSTUNT_CLPARSE'}++;
+ exec 'dpkg-parsechangelog', @orgargv;
+}
+
+use strict;
+open C, $infile or die $!;
+
+$!=0; $_ = <C>;
+m/^(\S+) \(([^()]+)\) (\S+)\; urgency=(\S+)$/ or die "$!, $_ ?";
+print <<END or die $!;
+Source: $1
+Version: $2
+Distribution: $3
+Urgency: $4
+Changes:
+ $&
+END
+
+my $blanks = 0;
+for (;;) {
+ $!=0; $_ = <C>;
+ if (m/^ -- ([^<>]+\<\S+\>) (\w[^<>]+\w)$/) {
+ print <<END or die $!;
+Maintainer: $1
+Date: $2
+END
+ print "Timestamp: " or die $!;
+ exec qw(date +%s -d), $2; die $!;
+ } elsif (m/^ --\s*$/) {
+ last;
+ } elsif (!m/\S/) {
+ $blanks++;
+ } elsif (m/^ .*\n/) {
+ print " .\n" x $blanks or die $!;
+ $blanks=0;
+ print " $_" or die $!;
+ } else {
+ die "$!, $_ ?";
+ }
+}
diff --git a/tests/tstunt/gpg b/tests/tstunt/gpg
new file mode 100755
index 0000000..d71aa63
--- /dev/null
+++ b/tests/tstunt/gpg
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -e
+exec \
+$DGIT_TEST_REAL_GPG \
+ --agent-program=$DGIT_STUNT_AGENT \
+ "$@"
diff --git a/tests/tstunt/gpg-agent b/tests/tstunt/gpg-agent
new file mode 100755
index 0000000..96ae839
--- /dev/null
+++ b/tests/tstunt/gpg-agent
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -e
+exec \
+$DGIT_TEST_REAL_GPG_AGENT \
+ --debug-quick-random \
+ "$@"
diff --git a/tests/tstunt/lintian b/tests/tstunt/lintian
new file mode 100755
index 0000000..f7c2985
--- /dev/null
+++ b/tests/tstunt/lintian
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo >&2 'W: dgit test suite stunt lintian detects no problems'
+exit 0
diff --git a/tests/using-intree b/tests/using-intree
index 70d84e1..0235c20 100755
--- a/tests/using-intree
+++ b/tests/using-intree
@@ -1,6 +1,17 @@
#!/bin/bash
+#
+# usage:
+# cd .../dgit.git
+# tests/using-intree tests/test/some-test
+# or
+# cd .../dgit.git
+# tests/using-intree tests/run-all
+#
+# effects:
+# sets DGIT_TEST_INTREE which causes tests/lib to have test scripts
+# using programs etc. from the working tree
+
set -e
-tree=`pwd`
-export DGIT_TEST="$tree/dgit"
-export DGIT_REPOS_SERVER_TEST="$tree/dgit-repos-server"
+pwd=`pwd`
+export DGIT_TEST_INTREE="$pwd"
exec "$@"
diff --git a/tests/worktrees/example_1.0.tar b/tests/worktrees/example_1.0.tar
new file mode 100644
index 0000000..50baa33
--- /dev/null
+++ b/tests/worktrees/example_1.0.tar
Binary files differ
diff --git a/tests/worktrees/pari-extra_3-1.tar b/tests/worktrees/pari-extra_3-1.tar
index 81a6a54..56b797d 100644
--- a/tests/worktrees/pari-extra_3-1.tar
+++ b/tests/worktrees/pari-extra_3-1.tar
Binary files differ
diff --git a/tests/worktrees/pari-extra_drs.tar b/tests/worktrees/pari-extra_drs.tar
index 1030178..94c8455 100644
--- a/tests/worktrees/pari-extra_drs.tar
+++ b/tests/worktrees/pari-extra_drs.tar
Binary files differ
diff --git a/tests/worktrees/ruby-rails-3.2_test.tar b/tests/worktrees/ruby-rails-3.2_test.tar
index 8c57662..6b0a824 100644
--- a/tests/worktrees/ruby-rails-3.2_test.tar
+++ b/tests/worktrees/ruby-rails-3.2_test.tar
Binary files differ