#!/usr/bin/env bash
set -Eeuo pipefail

thisDir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
source "$thisDir/.constants.sh" \
	--flags 'debian,non-debian' \
	--flags 'debootstrap:' \
	--flags 'debootstrap-script:' \
	--flags 'keyring:,arch:' \
	--flags 'merged-usr,no-merged-usr' \
	-- \
	'<target-dir> <suite> <timestamp>' \
	'rootfs stretch 2017-05-08T00:00:00Z' \
	\
	'--non-debian [--debootstrap-script=xyz] <target-dir> <suite> <mirror>' \
	'--non-debian rootfs xenial http://archive.ubuntu.com/ubuntu'

eval "$dgetopt"
nonDebian=
debootstrap=
script=
keyring=
arch=
noMergedUsr=
while true; do
	flag="$1"; shift
	dgetopt-case "$flag"
	case "$flag" in
		--debian)     nonDebian=  ;;
		--non-debian) nonDebian=1 ;;
		--debootstrap) debootstrap="$1"; shift ;;
		--debootstrap-script) script="$1"; shift ;;
		--keyring) keyring="$1"; shift ;;
		--arch) arch="$1"; shift ;;
		--merged-usr)    noMergedUsr=  ;;
		--no-merged-usr) noMergedUsr=1 ;;
		--) break ;;
		*) eusage "unknown flag '$flag'" ;;
	esac
done

targetDir="${1:-}"; shift || eusage 'missing target-dir'
[ -n "$targetDir" ] || eusage 'target-dir required' # must be non-empty
if [ -e "$targetDir" ] && [ -z "$(find "$targetDir" -maxdepth 0 -empty)" ]; then
	echo >&2 "error: '$targetDir' already exists (and isn't empty)!"
	exit 1
fi

suite="${1:-}"; shift || eusage 'missing suite'

timestamp=
mirror=
secmirror=
if [ -z "$nonDebian" ]; then
	timestamp="${1:-}"; shift || eusage 'missing timestamp'
else
	mirror="${1:-}"; shift || eusage 'missing mirror'

	timestamp="$(wget -qO- "$mirror/dists/$suite/Release" | awk -F ': ' '$1 == "Date" { print $2 }')"
fi

epoch="$(date --date "$timestamp" '+%s')"
export SOURCE_DATE_EPOCH="$epoch"

if [ -z "$nonDebian" ]; then
	mirror="$("$thisDir/.snapshot-url.sh" "@$epoch")"
	secmirror="$("$thisDir/.snapshot-url.sh" "@$epoch" 'debian-security')"
fi

debootstrapArgs=(
	--force-check-gpg
	--variant=minbase
)
[ -n "$noMergedUsr" ] || debootstrapArgs+=( --merged-usr )
[ -z "$keyring" ] || debootstrapArgs+=( --keyring="$keyring" )
[ -z "$arch" ] || debootstrapArgs+=( --arch="$arch" )

debootstrapArgs+=(
	"$suite" "$targetDir" "$mirror"
)
[ -z "$script" ] || debootstrapArgs+=( "$script" )

"${debootstrap:-debootstrap}" "${debootstrapArgs[@]}"
echo "$epoch" > "$targetDir/debuerreotype-epoch"

if [ -z "$nonDebian" ]; then
	"$thisDir/debuerreotype-gen-sources-list" "$targetDir" "$suite" "$mirror" "$secmirror"
fi

# since we're minbase, we know everything included is either essential, or a dependency of essential, so let's get clean "apt-mark showmanual" output
"$thisDir/debuerreotype-chroot" "$targetDir" apt-mark auto '.*' > /dev/null

echo 'debuerreotype' > "$targetDir/etc/hostname"
echo "$epoch" \
	| md5sum \
	| cut -f1 -d' ' \
	> "$targetDir/etc/machine-id" # TODO should we only do this if "/etc/machine-id" already exists?
{
	echo 'nameserver 8.8.8.8'
	echo 'nameserver 8.8.4.4'
} > "$targetDir/etc/resolv.conf"
chmod 0644 \
	"$targetDir/etc/hostname" \
	"$targetDir/etc/machine-id" \
	"$targetDir/etc/resolv.conf"

# https://bugs.debian.org/857803
# adjust field 3 in /etc/shadow and /etc/shadow- to $(( epoch / 60 / 60 / 24 )), if it's larger
sp_lstchg="$(( epoch / 60 / 60 / 24 ))"
for shadowFile in etc/shadow etc/shadow-; do
	newShadowFile="$shadowFile.debuerreotype"
	awk -F ':' \
		-v OFS=':' \
		-v sp_lstchg="$sp_lstchg" \
		'{
			if ($3 > sp_lstchg) {
				$3 = sp_lstchg
			}
			print
		}' "$targetDir/$shadowFile" > "$targetDir/$newShadowFile"
	if [ "$(< "$targetDir/$shadowFile")" != "$(< "$targetDir/$newShadowFile")" ]; then
		# use "cat" instead of "mv" so permissions don't change
		cat "$targetDir/$newShadowFile" > "$targetDir/$shadowFile"
	fi
	rm -f "$targetDir/$newShadowFile"
done
