#!/bin/sh

lockfile=/var/run/mqtt-exec.aports-build/aports-build.pid
pid=$(cat $lockfile 2>/dev/null)

if [ -n "$pid" ]; then
	if [ -d /proc/"$pid" ]; then
		# already running
		exit 0
	fi
fi
echo $$ > $lockfile || exit 1

logurl=
conf=/etc/conf.d/mqtt-exec.aports-build
. $conf || exit 1

if [ -z "$git_branch" ]; then
	echo "Please set 'git_branch' in $conf" >&2
	exit 1
fi

rel=$upload_release

if [ -z "$rel" ]; then
	case "$git_branch" in
		master)		rel="edge";;
		[0-9]*-stable)	rel=v${git_branch%-stable} ;;
	esac
fi

arch=$(abuild -A)

aports=${APORTS:-$HOME/aports}
isodir=$HOME/alpine-iso
packages=${REPOSDIR:-$HOME/packages}
repos=${REPOS:-"main community testing"}

: ${buildrepo:="buildrepo -p"}
: ${upload_host:="rsync.alpinelinux.org"}
: ${upload_prefix:="$upload_host:alpine"}
upload_pkg="$upload_prefix/$rel/"
upload_iso="$upload_prefix/$rel/releases/$arch/"

: ${ircchannel:="#alpine-devel"}
: ${hostname:=$(hostname)}
: ${mqtt_broker:="msg.alpinelinux.org"}
: ${status_msg:="mosquitto_pub -h $mqtt_broker -t build/$hostname -r -m"}
: ${upload_msg:="mosquitto_pub -h $mqtt_broker -t rsync/$upload_host/$rel/$arch -m"}
: ${irc_msg:="mosquitto_pub -h $mqtt_broker -t irc/${ircchannel//#/%} -m"}
: ${logdir:="/var/cache/distfiles/buildlogs"}
: ${logurlprefix:="http://build.alpinelinux.org/buildlogs"}

log() {
	echo "$hostname: $@"
	$status_msg "$1"
}

send_irc() {
	#echo "$1" | sircbot-send "$ircchannel"
	$irc_msg "$hostname: $1"
}

# create new_release
new_release() {
	local new=$1
	local target="all-release"
	local yaml=latest-releases.yaml
	local txt=.latest.txt
	local release_pkgs="lua"
	if [ "$rel" = "edge" ]; then
		target="edge"
	fi
	case "$arch" in
	x86*) release_pkgs="$release_pkgs syslinux";;
	esac
	cd "$isodir"
	echo "$new" > current
	rm -rf isotmp.*
	sudo apk add --virtual .alpine-release $release_pkgs
	if ! make $target; then
		rm current
		return 1
	fi
	sh mklatest.sh || return 1
	ssh $upload_host mkdir -p "${upload_iso#${upload_host}:}"
	[ -e "$yaml" ] || yaml=""
	[ -e "$txt" ] || txt=""
	rsync -ruv $yaml $txt *"$new"* "$upload_iso" || return 1
	sudo apk del .alpine-release
	mv current previous
	return 0
}

build() {
	( $buildrepo "$@" || echo "FAIL" ) | while read line; do
		case "$line" in
		FAIL) return 1;;
		[0-9]*/[0-9]*) $status_msg "$line";;
		*) echo "$line";;
		esac
	done
}

cd $aports || return 1
[ -z "$repos" ] && return 1

# parse opts
while getopts "fu:" opt; do
	case $opt in
	'f') force=true;;
	'u') logurl=" $OPTARG";;
	esac
done
shift $(( $OPTIND - 1 ))

while true; do
	local do_release=false
	cd $aports || return 1
	# check if we need to rebuild
	log "pulling git"
	_old=$(git describe)
	_old_tag=$(git describe --abbrev=0)
	git checkout $git_branch
	git pull || return 1
	_current=$(git describe)
	_current_tag=$(git describe --abbrev=0)
	if [ "$_old_tag" != "$_current_tag" ]; then
		log "$_old_tag -> $_current_tag"
		if [ -n "$release_formats" ]; then
			do_release=true
		fi
	fi
	if [ "$_old" = "$_current" ] && [ -f /tmp/uploaded ] && [ -z "$force" ] && [ "$_current_tag" = "$_old_tag" ]; then
		break
	fi

	force=

	# check if we need make new release
	if $do_release; then
		_new_release=1
		# we want build the realease from this tag
		git checkout "$_current_tag"
		_current=$(git describe)
	fi

	rm -f /tmp/uploaded

	# do the compile, send output to log
	log "building $_current"
	rc=0
	for repo in $repos; do
		if ! build $repo >"$logdir"/$hostname.log 2>&1 ; then
			local errlog=$hostname.$_current.log
			cp "$logdir"/$hostname.log "$logdir"/$errlog
			# todo: revert last commit?
			send_irc "failed to build $_current: $logurlprefix/$errlog"
			exit 1
		fi

		# upgrade our running system
		log "upgrading system"
		sudo apk upgrade -U -a --quiet || log 'failed to apk upgrade'

		# copy for distribution
		cd "$packages" || return 1
		if [ -z "$upload_pkg" ]; then
			continue
		fi

		log "uploading packages to $repo"
		for i in $upload_pkg; do
			rsync -rui --delete-delay --delay-updates \
				$repo/$arch $i/$repo/ > /tmp/upload-$repo
			if [ $? -ne 0 ]; then
				rc=1
			elif [ -s /tmp/upload-$repo ]; then
				$upload_msg "$rel/$repo/$arch"
				# report to irc that we are done with repo
				send_irc "files from $_current uploaded to $repo"
			fi
		done
	done
	[ $rc -eq 0 ] && touch /tmp/uploaded && sudo apk update

	if [ -n "$upload_pkg" ] && $do_release; then
		if new_release ${_current_tag#v}; then
			$upload_msg "$rel/releases/$arch"
			send_irc "release $_current_tag uploaded"
		fi
	fi

done

# cleanup
log "idle"
rm -f $lockfile

