#!/bin/bash
#---help---
# Usage: install-ubuntu-chroot -d destination-directory
#
# This script downloads and installs a recent version of Ubuntu to a chroot.
#---help---

set -euo pipefail

die() {
    printf '\033[1;31mERROR:\033[0m %s\n' "$@" >&2  # bold red
    exit 1
}

einfo() {
    printf '\n\033[1;36m> %s\033[0m\n' "$@" >&2  # bold cyan
}

ewarn() {
    printf '\033[1;33m> %s\033[0m\n' "$@" >&2  # bold yellow
}

usage() {
    sed -En '/^#---help---/,/^#---help---/p' "$0" | sed -E 's/^# ?//; 1d;$d;'
}

download_file() (
    local url="$1"
    local sha256="$2"
    local dest="${3:-.}"
    local file="${url##*/}"

    mkdir -p "$dest" && cd "$dest"

    if [ -f "$file" ]; then
        einfo "$file exists; checking sha256sum..."
        echo "$sha256  $file" | sha256sum -c && exit 0
    fi

    einfo "Downloading $file..."

    # On Wheezy, we may have outdated certificates and be unable to update.
    # Skipping the check is safe because we immediately verify the sha256.
    rm -f "$file" \
        && wget --no-check-certificate -T 10 "$url" \
        && echo "$sha256  $file" | sha256sum -c
)

gen_chroot_script() {
    cat <<-EOF
        #!/bin/sh
        set -e
        ENV_FILTER_REGEX='(TERM)'
EOF
    cat <<-'EOF'
        user='root'
        if [ $# -ge 2 ] && [ "$1" = '-u' ]; then
            user="$2"; shift 2
        fi
        oldpwd="$(pwd)"
        [ "$(id -u)" -eq 0 ] || _sudo='sudo'
        tmpfile="$(mktemp)"
        chmod 644 "$tmpfile"
        export | sed -En "s/^([^=]+ ${ENV_FILTER_REGEX}=)('.*'|\".*\")$/\1\3/p" > "$tmpfile" || true
        cd "$(dirname "$0")"
        $_sudo mv "$tmpfile" env.sh
        $_sudo chroot . /usr/bin/env -i su -l "$user" \
            sh -c ". /etc/profile; . /env.sh; cd '$oldpwd' 2>/dev/null; \"\$@\"" \
            -- "${@:-bash}"
EOF
}

################################################################################

while getopts 'd:h' OPTION; do
    case "$OPTION" in
        d) CHROOT_DIR="$OPTARG";;
        h) usage; exit 0;;
        *) exit 1;;
    esac
done

if [ "$(id -u)" -ne 0 ]; then
    die "This script must be run as root!"
fi

[ -z "${CHROOT_DIR:-""}" ] && die "You must specify a chroot directory with -d";
[ -e "${CHROOT_DIR:-""}" ] && die "Something already exists at $CHROOT_DIR";

################################################################################

IMAGE_URL="https://cloud-images.ubuntu.com/minimal/releases/eoan/release-20200129/ubuntu-19.10-minimal-cloudimg-amd64-root.tar.xz"
IMAGE_SHA="69d8e83fd17c6c8c5e014937aaeb19a35e3b30363f9daffa7decbe707bb8cfdf"
TEMP_DIR="/tmp/install-ubuntu-chroot"

download_file "$IMAGE_URL" "$IMAGE_SHA" "$TEMP_DIR"

mkdir -p "$CHROOT_DIR"

cd "$CHROOT_DIR"

tar -xvf "$TEMP_DIR/${IMAGE_URL##*/}"

einfo "Replacing chroot's /etc/resolv.conf"

rm -v -f etc/resolv.conf
cp -v /etc/resolv.conf etc/resolv.conf

einfo "Generating enter-chroot"

gen_chroot_script > enter-chroot
chmod +x enter-chroot

einfo "Mounting /proc and /dev/pts"

mount -v --bind /dev/pts dev/pts
mount -v --bind /proc proc

einfo 'Updating chroot system'

./enter-chroot <<-EOF
    apt -y update && apt -y upgrade
EOF

einfo "Unmounting /proc and /dev/pts"

umount -v proc
umount -v dev/pts

einfo 'Done!'
