#!/bin/bash -e

if test -f /etc/setup-debootstrap.conf; then
    . /etc/setup-debootstrap.conf
fi
if test -f ~/setup-debootstrap.conf; then
    . ~/setup-debootstrap.conf
fi

tmpdir=${tmpdir:-"/var/tmp/chroots"}
test -d "${tmpdir}" || mkdir -p "${tmpdir}"
if test -z "${ports[@]}"; then
    #ports=( armhf powerpc ppc64el s390x arm64   )
    #qemus=( arm   ppc     ppc64   s390x aarch64 )
    ports=( armhf )
    qemus=( arm   )
fi
numports=${#ports[@]}
if test -z "$archs"; then
    case "$(dpkg --print-architecture)" in
        (amd64) archs="amd64 i386";;
        (*) archs=$(dpkg --print-architecture);;
    esac
    for ((i=0; i<$numports; ++i)); do
        if test -x /usr/bin/qemu-${qemus[$i]}-static; then
            archs+=" ${ports[$i]}"
        fi
    done
fi
excludes="precise-armhf stretch-armhf"

ubuntu="bionic artful xenial trusty"
debian="buster stretch jessie sid"
# not yet successfully installable: ubuntu zesty, debian buster

distros=(${distros:-"${ubuntu[@]}" "${debian[@]}"})

packages_qt5="libpoppler-qt5-dev libpodofo-dev libqt5designer5 libqt5svg5-dev libqt5webkit5-dev qt5-default qt5-qmake qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools"
packages_base="apt-transport-https automake autotools-dev binutils-dev debhelper default-jdk-headless doxygen dpkg-dev g++ git graphviz libboost-thread-dev libcppunit-dev liblog4cxx-dev libpcsclite-dev libpkcs11-helper1-dev libproxy-dev libssl-dev libtool libz-dev lsb-release mscgen nodejs pandoc pkg-config software-properties-common subversion subversion-tools xvfb texinfo"

#package_not_in_bionic="libpoppler-qt5-dev libqt5webkit5-dev texinfo libcppunit-dev liblog4cxx-dev mscgen nodejs pandoc xvfb libpodofo-dev libqt5designer5 qt5-default qttools5-dev-tools qttools5-dev"
#package_not_in_artful="libpoppler-qt5-dev libqt5webkit5-dev texinfo libcppunit-dev liblog4cxx-dev mscgen nodejs pandoc xvfb libpodofo-dev libqt5designer5 qt5-default qttools5-dev-tools qttools5-dev"
package_not_in_stretch="libssl-dev"
#package_not_in_zesty="texinfo libcppunit-dev liblog4cxx-dev mscgen nodejs pandoc xvfb libpodofo-dev libqt5designer5 qt5-default qttools5-dev-tools qttools5-dev"
#package_not_in_yakkety="default-jdk-headless"
package_not_in_wily="default-jdk-headless"
package_not_in_vivid="default-jdk-headless liblog4cxx-dev"
package_not_in_trusty="default-jdk-headless liblog4cxx-dev"
package_not_in_jessie="default-jdk-headless liblog4cxx-dev"
package_not_in_precise="default-jdk-headless liblog4cxx-dev"
package_not_in_wheezy="default-jdk-headless liblog4cxx-dev nodejs"

if test -z "${packages}"; then
    packages="${packages_base} ${packages_qt5}"
fi

fastmode=0;
declare -a limit=()
arch=
docker_user=${docker_user:-${USER:-$(id -un)}}
while [ $# -gt 0 ]; do
    case "$1" in
        (-h|--help) cat <<EOF
SYNPOSIS: $0 [OPTIONS]

OPTIONS:

  -h, --help             show this help
  -f, --fastmode         don't update existing distribution
  -l, --limit <distro>   limit to given ditribution (can be called multiple times)
  -a, --arch <arch>      limit to given architecture (can be called multiple times)
  -u, --user <name>      docker hub user name

VARIABLES:

  docker_user            docker hub user name (${docker_user})
  tmpdir                 temporary directory (${tmpdir})
  archs                  list of architectures to build for (${archs})

DESCRIPTION:

Bootstraps chroots in ${tmpdir} for distro ubuntu and debian
distributions of architecture ${archs// /, }, updates them and creates
docker images on docker hub with tag
${docker_user}/<distro>:<codename>-<architecture>. You should have a
repositories named ubuntu and debian. You can the use these images
e.g. for compiling packages in jenkins. If you have your own
repository, you can also prepend it to docker hub user name,
e.g. my.repo.url:5000/myname the script will then append ubuntu or
debian, e.g. to my.repo.url:5000/myname/ubuntu:trusty-amd64. Please
login to docker hub before you start this script.

EOF
                    exit 0;;
        (-f|--fastmode) fastmode=1;;
        (-l|--limit) shift; limit+=( "$1" );;
        (-a|--arch) shift; arch+=" $1";;
        (-u|--user) shift; docker_user=$1;;
        (*)
            echo "**** ERROR: unknown option $1" 1>&2
            exit 1;;
    esac
    shift
done

error() {
    tmpdir=$2
    disto=$3
    arch=$4
    echo "**** ERROR at ${0}:${1}" 1>&2
    echo ".... on $(eval echo \"${BASH_COMMAND}\")" 1>&2
    echo ".... tmpdir=$tmpdir arch=$arch distro=$distro" 1>&2
    
    exit 1
}

if test ${#limit[@]} -gt 0; then
    distros=( "${limit[@]}" )
fi
for ((i=0; i<${#distros[@]}; ++i)); do
    for distro in ${distros[$i]}; do
        prevent=package_not_in_${distro}
        distropkgs=packages_${distro}
        instpkgs="${packages} ${!distropkgs}"
        for pkg in ${!prevent}; do
            instpkgs=${instpkgs//${pkg}/}
        done
        if ! test -e /usr/share/debootstrap/scripts/${distro}; then
            echo "**** WARNING: skipping unsupported ${distro}" 1>&2
            continue;
        fi
        ubuntus="${ubuntu[@]}"
        if test "${ubuntus//${distro}/}" != "${ubuntus}"; then
            type="ubuntu"
        else
            type="debian"
        fi
        for arch in ${arch:-$archs}; do
            if [[ "${distro}-${arch}" = "$excludes" ]]; then
                continue;
            fi
            trap 'error "${LINENO}" "${tmpdir}" "${disto}" "${arch}"' ERR SIGINT
            echo "******** process $type $distro $arch ********" 1>&2
            if test -d "${tmpdir}/${distro}-${arch}"; then
                echo " ++++    already exists ${tmpdir}/${distro}-${arch}" 1>&2
                if test $fastmode -eq 1; then
                    continue;
                fi
            else
                if test "$(dpkg --print-architecture)" = "$arch" -o \( "$(dpkg --print-architecture)" = amd64 -a "$arch" = i386 \) ; then
                    echo " ----    install ${tmpdir}/${distro}-${arch}" 1>&2
                    sudo debootstrap --arch="$arch" "$distro" "${tmpdir}/${distro}-${arch}"
                else
                    for ((j=0; j<$numports; ++j)); do
                        if test "${ports[$j]}" = "${arch}"; then
                            break;
                        fi
                    done
                    qemu="${qemus[$j]}"
                    if ! test -e /usr/bin/qemu-${qemu}-static; then
                        echo "**** WARNING: no emulator ${qemu} found, skipping ${arch}" 1>&2
                        continue;
                    fi
                    arch=${arch#*-}
                    echo " ----    install on $qemu ${tmpdir}/${distro}-${arch}" 1>&2
                    sudo debootstrap --foreign --arch="$arch" "$distro" "${tmpdir}/${distro}-${arch}"
                    sudo cp /usr/bin/qemu-${qemu}-static "${tmpdir}/${distro}-${arch}/usr/bin/qemu-${qemu}-static"
                    if test -f "${tmpdir}/${distro}-${arch}"/debootstrap/debootstrap; then
                        ls -l "${tmpdir}/${distro}-${arch}"/debootstrap/debootstrap
                    fi
                    sudo DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot "${tmpdir}/${distro}-${arch}" dpkg --configure -a
                fi
            fi
            echo " ----    mount filesystems in ${tmpdir}/${distro}-${arch}" 1>&2
            for x in proc sys dev; do
                if mount | grep -q "${tmpdir}/${distro}-${arch}"/$x; then
                    sudo umount -flr "${tmpdir}/${distro}-${arch}"/$x
                fi
            done
            sudo mount -t proc proc "${tmpdir}/${distro}-${arch}"/proc
            sudo mount -t sysfs sys "${tmpdir}/${distro}-${arch}"/sys
            sudo mount -o bind /dev "${tmpdir}/${distro}-${arch}"/dev
            echo " ----    preconfigure debian packages in ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" debconf-set-selections <<EOF
console-setup   console-setup/fontsize-fb47     select  8x16
console-setup   console-setup/fontface47        select  Fixed
console-setup   console-setup/charmap47 select  UTF-8
console-setup   console-setup/store_defaults_in_debconf_db      boolean true
keyboard-configuration  console-setup/ask_detect        boolean false
keyboard-configuration  console-setup/detected  note
console-setup   console-setup/fontsize  string  8x16
console-setup   console-setup/fontsize-text47   select  8x16
console-setup   console-setup/codesetcode       string  Uni2
keyboard-configuration  console-setup/detect    detect-keyboard
console-setup   console-setup/codeset47 select  . Combined - Latin; Slavic Cyrillic; Greek
EOF
            echo " ----    prevent packages in ${tmpdir}/${distro}-${arch}" 1>&2
            for f in "dbus" "libpam-systemd*" "packagekit*" "policykit*" "colord"; do
                sudo chroot "${tmpdir}/${distro}-${arch}" <<EOF1
if ! grep -q "Package: $f" /etc/apt/preferences; then
cat >> /etc/apt/preferences <<EOF2

Package: $f
Pin-Priority: -100

EOF2
fi
EOF1
            done
            echo " ----    upgrade ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true update
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true -y -f install
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true -y upgrade
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true install -y python-software-properties software-properties-common || \
                sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true install -y software-properties-common
            if [ "$type" != "debian" ]; then
                sudo chroot "${tmpdir}/${distro}-${arch}" add-apt-repository universe || \
                    sudo chroot "${tmpdir}/${distro}-${arch}" add-apt-repository "deb http://archive.ubuntu.com/ubuntu ${distro} universe"
            fi
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true update
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true -y dist-upgrade
            echo " ----    install ${instpkgs} to ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true install -y ${instpkgs}
            echo " ----    cleanup ${instpkgs} to ${tmpdir}/${distro}-${arch}" 1>&2
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true autoremove --purge -y
            sudo chroot "${tmpdir}/${distro}-${arch}" apt-get -o Acquire::ForceIPv4=true clean
	    sudo rm -rf "${tmpdir}/${distro}-${arch}"/var/lib/apt/lists/*
            echo " ----    unmount filesystems in ${tmpdir}/${distro}-${arch}" 1>&2
            for x in proc sys dev; do
                if mount | grep -q "${tmpdir}/${distro}-${arch}"/$x; then
                    sudo umount -flr "${tmpdir}/${distro}-${arch}"/$x
                fi
            done
            echo " ----    import ${tmpdir}/${distro}-${arch} to ${docker_user}/${type}:${distro}-${arch}" 1>&2
            cd "${tmpdir}/${distro}-${arch}"
            sudo tar c . | docker import - "${docker_user}/${type}:${distro}-${arch}"
            echo " ----    push ${tmpdir}/${distro}-${arch} to ${docker_user}/${type}:${distro}-${arch}" 1>&2
            docker push "${docker_user}/${type}:${distro}-${arch}"
        done
    done
done
