X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/9b78cda6873104b80ffdbc8b5d3965575ce0a31d..92d5a40da433833380626b9678c4887568505b6d:/test/integration/framework?ds=inline diff --git a/test/integration/framework b/test/integration/framework index 5d849bda2..45c1f156a 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1,16 +1,19 @@ #!/bin/sh -- # no runable script, just for vi # we all like colorful messages -CERROR="" # red -CWARNING="" # yellow -CMSG="" # green -CINFO="" # light blue -CDEBUG="" # blue -CNORMAL="" # default system console color -CDONE="" # green -CPASS="" # green -CFAIL="" # red -CCMD="" # pink +if expr match "$(readlink -f /proc/$$/fd/1)" '/dev/pts/[0-9]\+' > /dev/null && \ + expr match "$(readlink -f /proc/$$/fd/2)" '/dev/pts/[0-9]\+' > /dev/null; then + CERROR="" # red + CWARNING="" # yellow + CMSG="" # green + CINFO="" # light blue + CDEBUG="" # blue + CNORMAL="" # default system console color + CDONE="" # green + CPASS="" # green + CFAIL="" # red + CCMD="" # pink +fi msgdie() { echo "${CERROR}E: $1${CNORMAL}" >&2; exit 1; } msgwarn() { echo "${CWARNING}W: $1${CNORMAL}" >&2; } @@ -39,6 +42,14 @@ fi if [ $MSGLEVEL -le 2 ]; then msgmsg() { true; } msgnmsg() { true; } + msgtest() { true; } + msgpass() { echo -n " ${CPASS}P${CNORMAL}" >&2; } + msgskip() { echo -n " ${CWARNING}S${CNORMAL}" >&2; } + if [ -n "$CFAIL" ]; then + msgfail() { echo -n " ${CFAIL}FAIL${CNORMAL}" >&2; } + else + msgfail() { echo -n " ###FAILED###" >&2; } + fi fi if [ $MSGLEVEL -le 3 ]; then msginfo() { true; } @@ -75,9 +86,24 @@ aptcache() { runapt apt-cache $*; } aptget() { runapt apt-get $*; } aptftparchive() { runapt apt-ftparchive $*; } aptkey() { runapt apt-key $*; } +aptmark() { runapt apt-mark $*; } dpkg() { $(which dpkg) --root=${TMPWORKINGDIRECTORY}/rootdir --force-not-root --force-bad-path --log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log $* } +aptitude() { + if [ -f ./aptconfig.conf ]; then + APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY} $(which aptitude) $* + elif [ -f ../aptconfig.conf ]; then + APT_CONFIG=../aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY} $(which aptitude) $* + else + LD_LIBRARY_PATH=${BUILDDIRECTORY} $(which aptitude) $* + fi +} + +addtrap() { + CURRENTTRAP="$CURRENTTRAP $1" + trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM +} setupenvironment() { TMPWORKINGDIRECTORY=$(mktemp -d) @@ -86,8 +112,7 @@ setupenvironment() { BUILDDIRECTORY="${TESTDIR}/../../build/bin" test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first" local OLDWORKINGDIRECTORY=$(pwd) - CURRENTTRAP="cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY" - trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM + addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;" cd $TMPWORKINGDIRECTORY mkdir rootdir aptarchive keys cd rootdir @@ -107,8 +132,10 @@ setupenvironment() { local PACKAGESFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Packages-/' -e 's/^skip-/Packages-/') if [ -f "${TESTDIR}/${PACKAGESFILE}" ]; then cp "${TESTDIR}/${PACKAGESFILE}" aptarchive/Packages - else - touch aptarchive/Packages + fi + local SOURCESSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Sources-/' -e 's/^skip-/Sources-/') + if [ -f "${TESTDIR}/${SOURCESSFILE}" ]; then + cp "${TESTDIR}/${SOURCESSFILE}" aptarchive/Sources fi cp $(find $TESTDIR -name '*.pub' -o -name '*.sec') keys/ ln -s ${TMPWORKINGDIRECTORY}/keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg @@ -116,18 +143,22 @@ setupenvironment() { echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf echo "Debug::NoLocking \"true\";" >> aptconfig.conf echo "APT::Get::Show-User-Simulation-Note \"false\";" >> aptconfig.conf + echo "Dir::Bin::Methods \"${BUILDDIRECTORY}/methods\";" >> aptconfig.conf echo "Dir::Bin::dpkg \"fakeroot\";" >> aptconfig.conf echo "DPKG::options:: \"dpkg\";" >> aptconfig.conf echo "DPKG::options:: \"--root=${TMPWORKINGDIRECTORY}/rootdir\";" >> aptconfig.conf echo "DPKG::options:: \"--force-not-root\";" >> aptconfig.conf echo "DPKG::options:: \"--force-bad-path\";" >> aptconfig.conf echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf + echo 'quiet::NoUpdate "true";' >> aptconfig.conf export LC_ALL=C + export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin" msgdone "info" } configarchitecture() { local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf + rm -f $CONFFILE echo "APT::Architecture \"$1\";" > $CONFFILE shift while [ -n "$1" ]; do @@ -167,8 +198,12 @@ Maintainer: Joe Sixpack Build-Depends: debhelper (>= 7) Standards-Version: 3.9.1 -Package: $NAME -Architecture: $ARCH" > debian/control +Package: $NAME" > debian/control + if [ "$ARCH" = 'all' ]; then + echo "Architecture: all" >> debian/control + else + echo "Architecture: any" >> debian/control + fi test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> debian/control if [ -z "$DESCRIPTION" ]; then echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} @@ -192,15 +227,71 @@ buildsimplenativepackage() { local DEPENDENCIES="$5" local DESCRIPTION="$6" local SECTION="${7:-others}" + local PRIORITY="${8:-optional}" local DISTSECTION if [ "$SECTION" = "$(echo "$SECTION" | cut -d'/' -f 2)" ]; then DISTSECTION="main" else DISTSECTION="$(echo "$SECTION" | cut -d'/' -f 1)" fi - setupsimplenativepackage "$NAME" "$ARCH" "$VERSION" "$RELEASE" "$DEPENDENCIES" "$DESCRIPTION" "$SECTION" - buildpackage "incoming/${NAME}-${VERSION}" "$RELEASE" "$DISTSECTION" - rm -rf "incoming/${NAME}-${VERSION}" + local BUILDDIR=${TMPWORKINGDIRECTORY}/incoming/${NAME}-${VERSION} + + msgninfo "Build package ${NAME} in ${VERSION} for ${RELEASE} in ${DISTSECTION}… " + mkdir -p $BUILDDIR/debian/source + echo "* most suckless software product ever" > ${BUILDDIR}/FEATURES + echo "#!/bin/sh +echo '$NAME says \"Hello!\"'" > ${BUILDDIR}/${NAME} + + echo "Copyleft by Joe Sixpack $(date +%Y)" > ${BUILDDIR}/debian/copyright + echo "$NAME ($VERSION) $RELEASE; urgency=low + + * Initial release + + -- Joe Sixpack $(date -R)" > ${BUILDDIR}/debian/changelog + echo "Source: $NAME +Section: $SECTION +Priority: $PRIORITY +Maintainer: Joe Sixpack +Standards-Version: 3.9.1 + +Package: $NAME" > ${BUILDDIR}/debian/control + if [ "$ARCH" = 'all' ]; then + echo "Architecture: all" >> ${BUILDDIR}/debian/control + else + echo "Architecture: any" >> ${BUILDDIR}/debian/control + fi + test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> ${BUILDDIR}/debian/control + if [ -z "$DESCRIPTION" ]; then + echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} + If you find such a package installed on your system, + YOU did something horribly wrong! They are autogenerated + und used only by testcases for APT and surf no other propose…" >> ${BUILDDIR}/debian/control + else + echo "Description: $DESCRIPTION" >> ${BUILDIR}/debian/control + fi + echo '3.0 (native)' > ${BUILDDIR}/debian/source/format + local SRCS="$( (cd ${BUILDDIR}/..; dpkg-source -b ${NAME}-${VERSION} 2>&1) | grep '^dpkg-source: info: building' | grep -o '[a-z0-9._+~-]*$')" + for SRC in $SRCS; do + echo "pool/${SRC}" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.srclist + done + + for arch in $(echo "$ARCH" | sed -e 's#,#\n#g'); do + rm -rf ${BUILDDIR}/debian/tmp + mkdir -p ${BUILDDIR}/debian/tmp/DEBIAN ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME} ${BUILDDIR}/debian/tmp/usr/bin + cp ${BUILDDIR}/debian/copyright ${BUILDDIR}/debian/changelog ${BUILDDIR}/FEATURES ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME} + cp ${BUILDDIR}/${NAME} ${BUILDDIR}/debian/tmp/usr/bin/${NAME}-${arch} + (cd ${BUILDDIR}; dpkg-gencontrol -DArchitecture=$arch) + (cd ${BUILDDIR}/debian/tmp; md5sum $(find usr/ -type f) > DEBIAN/md5sums) + + dpkg-deb --build ${BUILDDIR}/debian/tmp ${BUILDDIR}/.. 2> /dev/null > /dev/null + echo "pool/${NAME}_${VERSION}_${arch}.deb" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.pkglist + done + + mkdir -p ${BUILDDIR}/../${NAME}_${VERSION} + cp ${BUILDDIR}/debian/changelog ${BUILDDIR}/../${NAME}_${VERSION}/ + cp ${BUILDDIR}/debian/changelog ${BUILDDIR}/../${NAME}_${VERSION}.changelog + rm -rf "${BUILDDIR}" + msgdone "info" } buildpackage() { @@ -251,9 +342,11 @@ createaptftparchiveconfig() { echo -n '"; }; Default { - Packages::Compress ". gzip bzip2 lzma"; - Sources::Compress ". gzip bzip2 lzma"; - Contents::Compress ". gzip bzip2 lzma"; + Packages::Compress ". gzip bzip2 lzma xz"; + Sources::Compress ". gzip bzip2 lzma xz"; + Contents::Compress ". gzip bzip2 lzma xz"; + Translation::Compress ". gzip bzip2 lzma xz"; + LongDescription "false"; }; TreeDefault { Directory "pool/"; @@ -313,24 +406,76 @@ insertpackage() { local ARCH="$3" local VERSION="$4" local DEPENDENCIES="$5" - local ARCHS="$ARCH" - if [ "$ARCHS" = "all" ]; then - ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')" - fi - for BUILDARCH in $ARCHS; do - local PPATH="aptarchive/dists/${RELEASE}/main/binary-${BUILDARCH}" - mkdir -p $PPATH aptarchive/dists/${RELEASE}/main/source - touch aptarchive/dists/${RELEASE}/main/source/Sources - local FILE="${PPATH}/Packages" + local PRIORITY="${6:-optional}" + local ARCHS="" + for arch in $(echo "$ARCH" | sed -e 's#,#\n#g'); do + if [ "$arch" = "all" ]; then + ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')" + else + ARCHS="$arch" + fi + for BUILDARCH in $ARCHS; do + local PPATH="aptarchive/dists/${RELEASE}/main/binary-${BUILDARCH}" + mkdir -p $PPATH aptarchive/dists/${RELEASE}/main/source + touch aptarchive/dists/${RELEASE}/main/source/Sources + local FILE="${PPATH}/Packages" + echo "Package: $NAME +Priority: $PRIORITY +Section: other +Installed-Size: 42 +Maintainer: Joe Sixpack +Architecture: $arch +Version: $VERSION +Filename: pool/main/${NAME}/${NAME}_${VERSION}_${arch}.deb" >> $FILE + test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE + echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} + If you find such a package installed on your system, + YOU did something horribly wrong! They are autogenerated + und used only by testcases for APT and surf no other propose… +" >> $FILE + done + done +} + +insertsource() { + local RELEASE="$1" + local NAME="$2" + local ARCH="$3" + local VERSION="$4" + local DEPENDENCIES="$5" + local ARCHS="" + local SPATH="aptarchive/dists/${RELEASE}/main/source" + mkdir -p $SPATH + local FILE="${SPATH}/Sources" + echo "Package: $NAME +Binary: $NAME +Version: $VERSION +Maintainer: Joe Sixpack +Architecture: $ARCH" >> $FILE + test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE + echo "Files: + d41d8cd98f00b204e9800998ecf8427e 0 ${NAME}_${VERSION}.dsc + d41d8cd98f00b204e9800998ecf8427e 0 ${NAME}_${VERSION}.tar.gz" >> $FILE +} + +insertinstalledpackage() { + local NAME="$1" + local ARCH="$2" + local VERSION="$3" + local DEPENDENCIES="$4" + local PRIORITY="${5:-optional}" + local FILE="rootdir/var/lib/dpkg/status" + for arch in $(echo "$ARCH" | sed -e 's#,#\n#g'); do echo "Package: $NAME -Priority: optional +Status: install ok installed +Priority: $PRIORITY Section: other -Installed-Size: 23356 +Installed-Size: 42 Maintainer: Joe Sixpack -Architecture: $ARCH +Architecture: $arch Version: $VERSION" >> $FILE test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE - echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} + echo "Description: an autogenerated dummy ${NAME}=${VERSION}/installed If you find such a package installed on your system, YOU did something horribly wrong! They are autogenerated und used only by testcases for APT and surf no other propose… @@ -338,6 +483,7 @@ Version: $VERSION" >> $FILE done } + buildaptarchivefromincoming() { msginfo "Build APT archive for ${CCMD}$(basename $0)${CINFO} based on incoming packages…" cd aptarchive @@ -358,20 +504,52 @@ buildaptarchivefromfiles() { cat ${line} | gzip > ${line}.gz cat ${line} | bzip2 > ${line}.bz2 cat ${line} | lzma > ${line}.lzma + cat ${line} | xz > ${line}.xz msgdone "info" done generatereleasefiles } +# can be overridden by testcases for their pleasure +getcodenamefromsuite() { echo -n "$1"; } +getreleaseversionfromsuite() { true; } + generatereleasefiles() { msgninfo "\tGenerate Release files… " + local DATE="${1:-now}" if [ -e aptarchive/dists ]; then + for dir in $(find ./aptarchive/dists -mindepth 3 -maxdepth 3 -type d -name 'i18n'); do + aptftparchive -qq release $dir -o APT::FTPArchive::Release::Patterns::='Translation-*' > $dir/Index + done for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do - aptftparchive -qq release $dir -o APT::FTPArchive::Release::Codename="$(echo "$dir" | cut -d'/' -f 4)" | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference + local SUITE="$(echo "$dir" | cut -d'/' -f 4)" + local CODENAME="$(getcodenamefromsuite $SUITE)" + local VERSION="$(getreleaseversionfromsuite $SUITE)" + if [ -z "$VERSION" ]; then + aptftparchive -qq release $dir \ + -o APT::FTPArchive::Release::Suite="${SUITE}" \ + -o APT::FTPArchive::Release::Codename="${CODENAME}" \ + | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference + else + aptftparchive -qq release $dir \ + -o APT::FTPArchive::Release::Suite="${SUITE}" \ + -o APT::FTPArchive::Release::Codename="${CODENAME}" \ + -o APT::FTPArchive::Release::Version="${VERSION}" \ + | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference + fi + if [ "$SUITE" = "experimental" -o "$SUITE" = "experimental2" ]; then + sed -i '/^Date: / a\ +NotAutomatic: yes' $dir/Release + fi done else aptftparchive -qq release ./aptarchive | sed -e '/0 Release$/ d' > aptarchive/Release # remove the self reference fi + if [ "$DATE" != "now" ]; then + for release in $(find ./aptarchive -name 'Release'); do + touch -d "$1" $release + done + fi msgdone "info" } @@ -432,6 +610,7 @@ signreleasefiles() { done for RELEASE in $(find aptarchive/ -name Release); do gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" -abs -o ${RELEASE}.gpg ${RELEASE} + gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o "$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" $RELEASE done msgdone "info" } @@ -439,15 +618,28 @@ signreleasefiles() { changetowebserver() { if which weborf > /dev/null; then weborf -xb aptarchive/ 2>&1 > /dev/null & - CURRENTTRAP="kill $(ps | grep weborf | sed -e 's#^[ ]*##' | cut -d' ' -f 1); $CURRENTTRAP" - trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM - local APTARCHIVE="file://$(readlink -f ./aptarchive)" - for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do - sed -i $LIST -e "s#$APTARCHIVE#http://localhost:8080/#" - done - return 0 + addtrap "kill $!;" + elif which gatling > /dev/null; then + cd aptarchive + gatling -p 8080 -F -S 2>&1 > /dev/null & + addtrap "kill $!;" + cd - > /dev/null + elif which lighttpd > /dev/null; then + echo "server.document-root = \"$(readlink -f ./aptarchive)\" +server.port = 8080 +server.stat-cache-engine = \"disable\"" > lighttpd.conf + lighttpd -t -f lighttpd.conf >/dev/null || msgdie 'Can not change to webserver: our lighttpd config is invalid' + lighttpd -D -f lighttpd.conf 2>/dev/null >/dev/null & + addtrap "kill $!;" + else + msgdie 'You have to install weborf or lighttpd first' + return 1 fi - return 1 + local APTARCHIVE="file://$(readlink -f ./aptarchive)" + for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do + sed -i $LIST -e "s#$APTARCHIVE#http://localhost:8080/#" + done + return 0 } checkdiff() { @@ -474,17 +666,18 @@ testfileequal() { testequal() { local COMPAREFILE=$(mktemp) + addtrap "rm $COMPAREFILE;" echo "$1" > $COMPAREFILE shift msgtest "Test for equality of" "$*" $* 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail - rm $COMPAREFILE } testequalor2() { local COMPAREFILE1=$(mktemp) local COMPAREFILE2=$(mktemp) local COMPAREAGAINST=$(mktemp) + addtrap "rm $COMPAREFILE1 $COMPAREFILE2 $COMPAREAGAINST;" echo "$1" > $COMPAREFILE1 echo "$2" > $COMPAREFILE2 shift 2 @@ -495,16 +688,15 @@ testequalor2() { ( echo "\n${CINFO}Diff against OR 1${CNORMAL}" "$(checkdiff $COMPAREFILE1 $COMPAREAGAINST)" \ "\n${CINFO}Diff against OR 2${CNORMAL}" "$(checkdiff $COMPAREFILE2 $COMPAREAGAINST)" && msgfail ) - rm $COMPAREFILE1 $COMPAREFILE2 $COMPAREAGAINST } testshowvirtual() { - local VIRTUAL="N: Can't select versions from package '$1' as it purely virtual" + local VIRTUAL="N: Can't select versions from package '$1' as it is purely virtual" local PACKAGE="$1" shift while [ -n "$1" ]; do VIRTUAL="${VIRTUAL} -N: Can't select versions from package '$1' as it purely virtual" +N: Can't select versions from package '$1' as it is purely virtual" PACKAGE="${PACKAGE} $1" shift done @@ -512,11 +704,11 @@ N: Can't select versions from package '$1' as it purely virtual" VIRTUAL="${VIRTUAL} N: No packages found" local COMPAREFILE=$(mktemp) + addtrap "rm $COMPAREFILE;" local ARCH=$(dpkg-architecture -qDEB_HOST_ARCH_CPU) eval `apt-config shell ARCH APT::Architecture` echo "$VIRTUAL" | sed -e "s/:$ARCH//" -e 's/:all//' > $COMPAREFILE aptcache show -q=0 $PACKAGE 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail - rm $COMPAREFILE } testnopackage() { @@ -533,8 +725,8 @@ testnopackage() { testdpkginstalled() { msgtest "Test for correctly installed package(s) with" "dpkg -l $*" - local PKGS="$(dpkg -l $* | grep '^[a-z]' | grep '^[^i]' | wc -l)" - if [ "$PKGS" != 0 ]; then + local PKGS="$(dpkg -l $* | grep '^i' | wc -l)" + if [ "$PKGS" != $# ]; then echo $PKGS dpkg -l $* | grep '^[a-z]' msgfail @@ -543,9 +735,9 @@ testdpkginstalled() { msgpass } -testdpkgnoninstalled() { - msgtest "Test for correctly non-installed package(s) with" "dpkg -l $*" - local PKGS="$(dpkg -l $* | grep '^[a-z]' | grep '^[^u]' | wc -l)" +testdpkgnotinstalled() { + msgtest "Test for correctly not-installed package(s) with" "dpkg -l $*" + local PKGS="$(dpkg -l $* 2> /dev/null | grep '^i' | wc -l)" if [ "$PKGS" != 0 ]; then echo dpkg -l $* | grep '^[a-z]' @@ -554,3 +746,22 @@ testdpkgnoninstalled() { fi msgpass } + +testmarkedauto() { + local COMPAREFILE=$(mktemp) + addtrap "rm $COMPAREFILE;" + if [ -n "$1" ]; then + msgtest 'Test for correctly marked as auto-installed' "$*" + while [ -n "$1" ]; do echo "$1"; shift; done | sort > $COMPAREFILE + else + msgtest 'Test for correctly marked as auto-installed' 'no package' + echo -n > $COMPAREFILE + fi + aptmark showauto 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail +} + +pause() { + echo "STOPPED execution. Press enter to continue" + local IGNORE + read IGNORE +}