X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=tests%2Flib;h=993ec36b647a44953d1a67d59cb536b7ca5a8969;hp=cebe10d9452e79d649662f42404f3b80847c0152;hb=127632098e58021e467fb56fa36466785f2cbe55;hpb=9243bf289e6ece2b20765a6cd850aab4c66f98e8 diff --git a/tests/lib b/tests/lib index cebe10d9..993ec36b 100644 --- a/tests/lib +++ b/tests/lib @@ -21,6 +21,8 @@ END trap 'test $? = 0 || t-report-failure' EXIT +t-filter-out-git-hyphen-dir + t-set-intree : ${DGIT_TEST_DEBUG=-D} @@ -36,9 +38,12 @@ 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 @@ -46,11 +51,9 @@ tmp=`pwd` t-set-using-tmp -ln -f $troot/ssh ssh +env -0 >$tmp/.save-env -mkdir -p $tmp/gnupg -cp $troot/gnupg/* $tmp/gnupg -chmod go-rw $tmp/gnupg/* +ln -f $troot/ssh ssh export DEBCHANGE_VENDOR=dpkg @@ -62,7 +65,8 @@ incoming = $tmp/incoming run_dinstall = 0 END -: ${tagpfx:=test-dummy} +: ${t_archive_method:=aq} +: ${tagpfx:=archive/test-dummy} : ${suitespecs:=sid:unstable} t-git-next-date () { @@ -110,7 +114,7 @@ t-grep-mpat () { t-expect-push-fail () { local mpat="$1"; shift - local triedpush=`git rev-parse HEAD` + local triedpush; triedpush=`git rev-parse HEAD` t-reporefs pre-push t-expect-fail "$mpat" "$@" @@ -185,14 +189,29 @@ t-git-merge-base () { } t-has-ancestor () { - local now=`git rev-parse HEAD` - local ancestor=`git rev-parse $1^{}` - local mbase=`t-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 @@ -209,6 +228,9 @@ t-prep-newpackage () { t-archive-none () { 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 @@ -220,12 +242,12 @@ t-archive-none () { local sname=${suitespec#*:} >$tmp/aq/package.$suite.$p - t-archive-updated $suite $p + t-aq-archive-updated $suite $p >$tmp/aq/package.new.$p - t-archive-updated new $p + t-aq-archive-updated new $p - ln -s $suite $tmp/aq/dsc_in_suite/$sname + ln -sf $suite $tmp/aq/dsc_in_suite/$sname cat <>$tmp/aq/suites $jsondelim @@ -250,7 +272,7 @@ END END } -t-archive-updated () { +t-aq-archive-updated () { local suite=$1 local p=$2 local suitedir=$tmp/aq/dsc_in_suite/$suite @@ -275,16 +297,23 @@ t-archive-updated () { t-archive-process-incoming () { local suite=$1 - mv $tmp/incoming/${p}_${v}[._]* $tmp/mirror/pool/main/ + mv $tmp/incoming/${p}_* $tmp/mirror/pool/main/ t-archive-query "$suite" } t-archive-query () { local suite=${1-sid} local dscf=main/${p}_${v}.dsc - local sha=`sha256sum <$tmp/mirror/pool/$dscf` + 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-archive-updated $suite $p + t-aq-archive-updated $suite $p } t-archive () { @@ -293,7 +322,7 @@ t-archive () { local dscf=${p}_$2.dsc rm -f $tmp/mirror/pool/main/${p}_* ln $troot/pkg-srcs/${p}_${2%-*}* $tmp/mirror/pool/main/ - t-archive-query + t-archive-query $suite rm -rf $tmp/extract mkdir $tmp/extract (set -e; cd $tmp/extract; dpkg-source -x ../mirror/pool/main/$dscf) @@ -321,6 +350,52 @@ t-git-dir-check () { 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 } @@ -332,7 +407,7 @@ t-dgit () { {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{' $dgit --dgit=$dgit --dget:-u --dput:--config=$tmp/dput.cf \ -dtest-dummy $DGIT_TEST_OPTS $DGIT_TEST_DEBUG \ - -k39B13D8A "$@" + -k39B13D8A $t_dgit_xopts "$@" : '}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} ' } @@ -361,7 +436,7 @@ t-cloned-fetched-good () { } 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 @@ -371,6 +446,65 @@ 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 @@ -395,35 +529,37 @@ t-git-get-ref () { t-ref-same-exact () { local name="$1" - local val=`t-git-get-ref-exact $name` + 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:-nothing} != ${t_ref_val:-nothing}" ;; + *) 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 () { @@ -447,21 +583,48 @@ t-v-tag () { 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=`t-git-get-ref refs/heads/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=`t-git-merge-base $master $t_ref_val` + 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/$suite t-refs-notexist \ @@ -478,6 +641,117 @@ t-pushed-good () { 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 @@ -505,20 +779,51 @@ t-stunt-envvar () { local var=$1 local tstunt=$2 eval ' - case "'$var'" in + 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=$(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 @@ -530,11 +835,24 @@ t-tstunt-parsechangelog () { t-tstunt dpkg-parsechangelog Dpkg/Changelog/Parse.pm } -t-ref-dsc-dgit () { +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` + perl -e '$_=shift @ARGV; die "Dgit $_ ?" unless m/^\w+\b/;' "$val" + t-ref-same-val $incoming_dsc "$val" } t-apply-diff () { @@ -566,7 +884,20 @@ t-gbp-unapplied-pq2qc () { git commit -m 'Commit patch queue' } -t-gbp-example-prep () { +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 @@ -575,7 +906,7 @@ t-gbp-example-prep () { t-dgit fetch - git-checkout -b patch-queue/quilt-tip-2 patch-queue/quilt-tip + git checkout -b patch-queue/quilt-tip-2 patch-queue/quilt-tip gbp pq rebase echo '/* some comment */' >>src.c @@ -585,16 +916,29 @@ t-gbp-example-prep () { t-gbp-unapplied-pq2qc t-commit 'some updates' 1.0-2 +} - git merge -s ours \ +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:-1.$revision} - dch -v$v --distribution ${3:-unstable} "$1" + v=${2:-${majorv:-1}.$revision} + dch --force-distribution -v$v --distribution ${3:-unstable} "$1" git add debian/changelog debcommit revision=$(( ${revision-0} + 1 )) @@ -609,7 +953,7 @@ t-drs () { 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 - t-git-config dgit-distro.test-dummy.dgit-tag-format old,new + 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 @@ -633,9 +977,10 @@ t-drs () { t-newtag () { export tagpfx=archive/test-dummy - t-git-config dgit-distro.test-dummy.dgit-tag-format new + 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 } @@ -707,6 +1052,7 @@ t-chain-test () { local d=${0%/*} cd $root export DGIT_TEST_TESTNAME="$testname" + export DGIT_TEST_TMPBASE="$tmpbase" export ADTTMP=$tmp exec "$d/$ct" } @@ -716,3 +1062,8 @@ t-alt-test () { t-${t%%-*} t-chain-test "${t#*-}" } + +case "$0" in +*/gnupg) ;; +*) t-setup-import gnupg ;; +esac