#!/bin/bash

# build a local dir
#
set -u -o pipefail -ex
umask 022

B=minbase
S=smurf
NC=
BIN=-b
N=$(dpkg-parsechangelog  -l debian/changelog -S source)
F=
C="$(/bin/pwd)"

usage() {
	if [ $# -gt 0 ] ; then
		echo "$0: $*"
		echo "" >&2
		cat >&2
	else
		echo "$0: Simple Build (in a chroot, and tag)."
		echo ""
		cat
	fi <<END
Usage: $0 [options]
-A          use all available archs / distributions
            otherwise default to amd64/testing
-a ARCH     architecture (default: all)
-B          only build arch-dependant binaries
-R          style of root (default: $B)
-d DIST     distribution (default: all)
-f FLAGS    flags for debuild
-n NAME     name of the generated package (default: $N)
-N          don't clean the source
-v VERSION  Package version (default: TAG-1)
-V          use existing version from debian/changelog
END
	if test $# -gt 0 ; then
		echo "$*" >&2
	else
		echo 'Terminating...' >&2
	fi
	exit 1
}

TEMP="$(getopt -o 'Aa:b:Bd:f:hNn:v:V' -n "$(basename "$0")" -- "$@")" || usage "Invalid argument"

eval set -- "$TEMP"
unset TEMP
BIN=-b
MBIN=
BR=
while true ; do
    case "$1" in
		('-A')
	    ALL=y; shift ;;
	('-a')
	    shift; A=$1; shift ;;
	('-b')
	    shift; BR=$1; shift ;;
	('-B')
	    BIN=-B; shift ;;
	('-d')
	    shift; Z=$1; shift ;;
	('-f')
	    shift; F="$1"; shift ;;
	('-h')
		usage ;;
	('-n')
	    shift; N=$1; shift ;;
	('-N')
	    NC="-nc"; shift ;;
	('-R')
	    shift; B=$1; shift ;;
	('-v')
	    shift; V=$1; shift ;;
	('-V')
	    VR=y; shift ;;
	('--')
		shift; break ;;
    *)
        usage "Unknown argument '$1'"
    esac
done

export LC_ALL=C.UTF-8

if [ $(git ls-files --modified --deleted --others --exclude-standard | wc -l) -gt 0 ] ; then
	echo "Unsaved changes. Not building."
	exit 1
fi

CBR=$(git branch --show-current)
if test -n "$BR" ; then
	:
elif [ "$CBR" = "deb" ] || [ "$CBR" = "debian" ] ; then
    BR=$CBR
elif git describe --all deb >/dev/null 2>&1; then
    BR=deb
elif git describe --all debian >/dev/null 2>&1; then
    BR=debian
elif test ! -f debian/changelog ; then
    echo "Neither 'deb' nor 'debian' branches found." >&2
    exit 1
elif test -n "$CBR" ; then
	BR=$CBR
else
    echo "The current checkout is headless!" >&2
    exit 1
fi

if test -v VR ; then
	V=$(dpkg-parsechangelog  -l debian/changelog  -S version | sed -e 's/^\[0-9]\://p')
fi

sv() {
	case $1 in
		(oldoldstable|bullseye) echo 11 ;;
		(oldstable|bookworm) echo 12 ;;
		(stable|trixie) echo 13 ;;
		(testing|forky) echo 14 ;;
		(unstable|sid) echo 987 ;;
		(experimental) echo 999 ;;
		(*)
			usage "Dunno Debian version for '$1'"
	esac
}

next_tag() {
	local v="$1"
	v=$(echo $v|sed -e 's#\.#\\.#g')
	local m="$(git tag|sed -ne "s/^v//" -e "s|^\(.*/\)\?$v.*-\([0-9]\+\)$|\2|p"|sort -rn|head -1)"
	if test -n "$m" ; then m=$(expr $m + 1 ) ; else m=1; fi
	echo $m
}

mk() {
	local X=$1
	local Y=$2
	local xd=$3
	local vv
	local a
	local b


	cd "$C"

	if test -v V ; then
		vv=$V
	else
		vv="$(git describe --tags)"
		vv="$(basename $vv)"
		vv="${vv#v}"
		IFS="-" read vv b < <(echo $vv)
		vv="$vv-$(next_tag $vv)"
	fi

	# extract epoch
	vx=$(dpkg-parsechangelog  -l debian/changelog  -S version | sed -ne 's/^\([0-9]\):.*/\1:/p')
	local ov="$(dpkg-parsechangelog  -l debian/changelog  -S version | sed -e 's/^[0-9]://')"
#	if dpkg --compare-versions $vv "<<" $ov ; then
#		echo "WARNING using Debian version '$ov' instead of '$vv'"
#		vv="$ov"
#	fi
	if echo "$vv" | grep -qs ":" ; then vx=""; fi
	export EMAIL=${DEBEMAIL?:$EMAIL}
	export FULLNAME=${DEBFULLNAME?:$FULLNAME}

	local R="sudo --preserve-env=EMAIL,FULLNAME systemd-nspawn -E EMAIL -E FULLNAME --private-users=pick -D $X --bind-ro=$C:/$Y/orig:rootidmap --bind=/srv/build/cache:/var/cache/apt/archives:rootidmap"
	if test -n "$NC" ; then
		$R --chdir=/$Y/src git pull
	else
		$R --chdir=/$Y git clone --depth 1 -b $BR --shallow-submodules orig src
	fi
	$R --chdir=/$Y/src git submodule update --init --recursive

	test "$ov" = "$vx$vv" || $R --chdir=/$Y/src debchange -b -D $xd -v "$vx$vv" "Autobuild."

	test -n "$NC" || $R eatmydata apt update
	$R --chdir=/$Y eatmydata mk-build-deps -i -t 'apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' src/debian/control

	# $R dpkg --unpack /$Y/$(cd $X/$Y; ls | grep '.*-build-deps_.*\.deb$')
	# $R eatmydata apt-get --no-install-recommends --yes -f install
	# test -v SH && $R /bin/bash
	if test -f bootstrap.sh ; then
		$R --chdir=/$Y/src bash bootstrap.sh
	fi
	$R --chdir=/$Y rm -f \*.changes
	$R --chdir=/$Y/src eatmydata debuild -eDEB_BUILD_OPTIONS="$F" $MBIN -us -uc $NC -j$(( $(nproc) * 3 / 2))

	cd $X/$Y
	dput -u ext $(ls *.changes | grep -v .-build-deps_) || true  # maybe can't write here

	cd "$C"
	if test $xd = "unstable" ; then
		git tag smurf/$vv || true
	else
		git tag smurf/$xd/$vv || true
	fi
	git push-all
}

mk2() {
	local xd=$1
	local xa=$2
	local DR=$D/$xd/$xa
	local X=$DM/$xd/$xa
	local Y=build/$N

	if test -n "$NC" ; then
		test -d $X || usage "Noclean set but doesn't exist"
	else
		test -d $X && sudo btrfs subvolume delete $X
		sudo mkdir -p $(dirname $X)
		sudo btrfs subvolume snapshot $DR $X
	fi

	sudo mkdir -p $X/$Y/orig

	mk $X $Y $xd
}

mk1() {
	local xd=$1
	local DD=$D/$xd

	MBIN="$BIN"
	if test -v A ; then
		mk2 $xd $A
	elif test -v ALL ; then
		for dd in $(ls $DD) ; do
			mk2 $xd $dd
			MBIN="-B"
		done
	else
		mk2 $xd amd64
	fi
}

D=/srv/build/$B
DM=/srv/build/make
if test -v Z ; then
	mk1 $Z
elif test -v ALL ; then
	for d in $(ls $D) ; do mk1 $d; done
else
	mk1 testing
fi

