#!/usr/bin/env bash

BOOTSTRAP="${BASH_SOURCE[0]%/*}/bootstrap-prefix.sh"
BOOTURL="http://rsync.prefix.bitzolder.nl/scripts/bootstrap-prefix.sh"
UPLOAD="rsync1.prefix.bitzolder.nl::gentoo-portage-bootstraps"

do_fetch() {
	local FETCH_COMMAND
	# Try to find a download manager, we only deal with wget,
	# curl, FreeBSD's fetch and ftp.
	if [[ $(type -t wget) == "file" ]] ; then
		FETCH_COMMAND="wget -O -"
		[[ $(wget -h) == *"--no-check-certificate"* ]] && \
			FETCH_COMMAND+=" --no-check-certificate"
	elif [[ $(type -t curl) == "file" ]] ; then
		FETCH_COMMAND="curl -f -L"
	else
		echo "could not download ${1##*/}"
		exit 1
	fi

	${FETCH_COMMAND} "${*}" || exit 1
}

do_prepare() {
	local bitw=$1
	local dte=$2
	local bootstrap
	local chost
	local bootstrapscript

	if [[ -n ${RESUME} && -n ${bitw} && -n ${dte} ]] ; then
		bootstrap=${OVERRIDE_EPREFIX:-bootstrap${bitw}-${dte}}/bootstrap-prefix.sh
	elif [[ -n ${DOLOCAL} ]] ; then
		bootstrap=${BOOTSTRAP}
	fi
	if [[ ! -e ${bootstrap} ]] ; then
		bootstrap=dobootstrap-do_prepare-$$
		do_fetch ${BOOTURL} > ${bootstrap}
	fi

	chost=$("${BASH}" "${bootstrap}" chost.guess x)
	case ${chost} in
		*-darwin[89])
			# ppc64-darwin never really worked for unknown reasons
			# darwin9 (Leopard) doesn't work on Intel either
			bitw=32
			;;
		*-solaris*|*-darwin*)
			# force 64-bits for these targets, 32-bits is no longer
			# supported
			bitw=64
			;;
	esac
	case ${chost} in
		*86-*)
			if [[ ${bitw} == 64 ]] ; then
				chost=x86_64-${chost#*-}
			else
				bitw=32
				chost=i386-${chost#*-}
			fi
			;;
		x86_64-*)
			if [[ ${bitw} == 32 ]] ; then
				chost=i386-${chost#*-}
			else
				bitw=64
				chost=x86_64-${chost#*-}
			fi
			;;
		powerpc-*)
			if [[ ${bitw} == 64 ]] ; then
				chost=powerpc64-${chost#*-}
			else
				bitw=32
				chost=powerpc-${chost#*-}
			fi
			;;
		aarch64-*|arm64-*)
			bitw=64
			;;
		sparc-*)
			if [[ ${bitw} == 64 ]] ; then
				chost=sparcv9-${chost#*-}
			else
				bitw=32
				chost=sparc-${chost#*-}
			fi
			;;
		sparcv9-*|sparc64-*)
			if [[ ${bitw} == 32 ]] ; then
				chost=sparc-${chost#*-}
			else
				bitw=64
				chost=sparcv9-${chost#*-}
			fi
			;;
		*)
			echo "unhandled CHOST: ${chost}"
			rm -f dobootstrap-do_prepare-$$
			exit 1
			;;
	esac

	[[ -z ${dte} ]] && dte=$(date "+%Y%m%d")
	EPREFIX=${PWD}/bootstrap${bitw}-${dte}
	[[ -n ${OVERRIDE_EPREFIX} ]] && EPREFIX=${OVERRIDE_EPREFIX}

	bootstrapscript=$(realpath "${BASH_SOURCE[0]}" 2>/dev/null)
	if [[ -z ${bootstrapscript} ]] ; then
		local b=${BASH_SOURCE[0]}
		cd "${b%/*}" || exit 1
		bootstrapscript="$(pwd -P)/${b##*/}"
	fi
	echo "EPREFIX=${EPREFIX}"
	mkdir -p "${EPREFIX}"
	if [[ ${bootstrap} == dobootstrap-do_prepare-$$ ]] ; then
		mv "${bootstrap}" "${EPREFIX}"/bootstrap-prefix.sh
	elif [[ ${bootstrap} != "${EPREFIX}"/bootstrap-prefix.sh ]] ; then
		cp "${bootstrap}" "${EPREFIX}"/bootstrap-prefix.sh
	fi
	cd "${EPREFIX}" || exit 1

	# reminder: MAKE_CONF_ADDITIONAL_USE can be set to add global
	# USE-flags in make.conf prior to stage2 (first emerge usage)
	starttime=${SECONDS}
	env -i \
		HOME="${EPREFIX}" \
		SHELL="/bin/sh" \
		TERM="${TERM}" \
		USER="${USER}" \
		CHOST="${chost}" \
		EPREFIX="${EPREFIX}" \
		${GENTOO_MIRRORS+GENTOO_MIRRORS="${GENTOO_MIRRORS}"} \
		${DOLOCAL+DOLOCAL=1} \
		${RESUME+RESUME=1} \
		${LATEST_TREE_YES+LATEST_TREE_YES=1} \
		${TREE_FROM_SRC+TREE_FROM_SRC="${TREE_FROM_SRC}"} \
		${USE_CPU_CORES+USE_CPU_CORES="${USE_CPU_CORES}"} \
		${DARWIN_USE_GCC+DARWIN_USE_GCC="${DARWIN_USE_GCC}"} \
		${PREFIX_DISABLE_RAP+PREFIX_DISABLE_RAP="${PREFIX_DISABLE_RAP}"} \
		${BP_KEEPALIVE_ACTIVE+BP_KEEPALIVE_ACTIVE="${BP_KEEPALIVE_ACTIVE}"} \
		"${BASH}" "${bootstrapscript}" bootstrap
	endtime=${SECONDS}

	if [[ -n ${DOPUBLISH} ]] ; then
		echo $((endtime - starttime)) > elapsedtime

		# get identification of host that includes Linux distro, RAP, ...
		chost="$(env CHOST="${chost}" \
			"${BASH}" ./bootstrap-prefix.sh chost.identify x)"

		rsync -q /dev/null "${UPLOAD}/${HOSTNAME}-$$"/
		rsync -q /dev/null "${UPLOAD}/${HOSTNAME}-$$/${chost}"/
		rsync -rltv \
			--exclude=work/ \
			--exclude=homedir/ \
			--exclude=files \
			--exclude=distdir/ \
			--exclude=image/ \
			{stage,.stage}* \
			bootstrap-prefix.sh \
			startprefix \
			elapsedtime \
			var/cache/distfiles \
			var/tmp/portage \
			var/log/emerge.log \
			etc/portage/make.conf \
			"${UPLOAD}/${HOSTNAME}-$$/${chost}/${dte}"/
		rsync -q /dev/null \
			"${UPLOAD}/${HOSTNAME}-$$/${chost}/${dte}"/push-complete/
	fi
}

do_bootstrap() {
	chmod 755 bootstrap-prefix.sh || exit 1
	"${BASH}" ./bootstrap-prefix.sh "${EPREFIX}" noninteractive
}

# re-exec under keepalive wrapper, such that the machine we're running
# on doesn't go to sleep, until we as top-level caller terminate
if [[ -z ${BP_KEEPALIVE_ACTIVE} ]] ; then
	# optional program to keep the machine from sleeping
	# macOS/BSD: caffeinate
	keepalive=$(type -P caffeinate)
	[[ -e ${keepalive} ]] && keepalive+=" -i -m -s" || keepalive=
	if [[ -n ${keepalive} ]] ; then
		export BP_KEEPALIVE_ACTIVE=1
		# starting from Sequoia letting caffeinate spawn the script
		# doesn't seem to work any more, so keep a co-buddy to watch
		# this script
		${keepalive} -w $$ &
	fi
fi

case $1 in
	bootstrap)
		do_bootstrap
		;;
	local)
		export DOLOCAL=1
		do_prepare "$2"
		;;
	resume)
		export RESUME=1
		do_prepare "$2" "${3:-${BOOTSTRAP_DATE}}"
		;;
	check)
		echo "Just checking."
		ps ax | grep caffeinate
		exit
		;;
	*)
		bitw=
		if [[ ${0} == /net/* || ${0} == /System/* ]] ; then
			echo "internal host, activating local and DOPUBLISH"
			export DOLOCAL=1
			export DOPUBLISH=1
			export GENTOO_MIRRORS="http://distfileslocal http://distfiles.gentoo.org"
		fi
		for arg in "${@:1}" ; do
			case "${arg}" in
				latesttree)   export LATEST_TREE_YES=1      ;;
				norap|no-rap) export PREFIX_DISABLE_RAP=yes ;;
				32|64)        bitw="${arg}"                 ;;
			esac
		done
		do_prepare "${bitw}"
		;;
esac

