#!/bin/sh
#
# Builds a new campaignd or wesnothd binary from source.
#
# Usage:
#    update_server [-c] <server version> [<revision>]
#
#    -c    Builds campaignd instead of wesnothd
#
# SCons is used to build the source code from SOURCE_ROOT (no write access
# required) onto INT_ROOT. The resulting binary and ancillary files are stored
# in DEST_ROOT in a subdir specific to that build's version and revision (e.g.
# 'wesnothd-trunk-git-<revision id>', where <revision id> corresponds to the
# output of `git describe`).
#
# Additionally, the symbolic link ~/bin/wesnothd-<version> or
# ~/bin/campaignd-<version> (depending on the -c switch) is updated to point
# to the newest binary for that version.
#

die() { echo >&2 "$@"; exit 1; }

[ $# -gt 0 ] && [ $# -lt 4 ] || die "Syntax: $(basename $0) [-c] <server version> [<revision>]"

set -o errexit

case "$1" in
  -c)
	shift
	TYPE=campaignd
	BASE=campaignd
	;;
  *)
	TYPE=wesnothd
	# Should be moved to wesnothd at some point. (Several other scripts depend
	# on the location though!)
	BASE=servers
	;;
esac

VERSION=$(readlink "$HOME/$BASE/$1" || true)
VERSION="${VERSION:=$1}"

echo "Building $TYPE-$VERSION..."

# Parent for the $VERSION source trees, never written to.
SOURCE_ROOT="$HOME/source"
# Parent for the $VERSION intermediate build dir.
INT_ROOT="$HOME/builds-int"
# Parent for the $BUILD_ID output dir.
DEST_ROOT="$HOME/builds"
# Location of the server instance files.
SERVER_BASE="$HOME/$BASE/$VERSION"

SOCKET="$SERVER_BASE/build/var/run/socket"

[ -d "$SERVER_BASE" ] || die "Server base dir '$SERVER_BASE' not found!"
[ -d "$SOURCE_ROOT" ] || die "Source base dir '$SOURCE_ROOT' not found!"

SOURCE_VERSION="$VERSION"

CXXFLAGS="$CXXFLAGS"
LDFLAGS="$LDFLAGS"
BUILD_PRESET="release"

case "$VERSION" in
  1.6|1.8|1.10|1.12)
	CXXFLAGS="$CXXFLAGS -ggdb3 -DNUM_SHARDS=7"
	;;
  1.1[468])
	CXXFLAGS="$CXXFLAGS -ggdb3"
	;;
  1.9)
	[ "$TYPE" = "campaignd" ] || die "1.9 is currently a special case for the 1.10 campaignd only"
	CXXFLAGS="$CXXFLAGS -ggdb3 -DNUM_SHARDS=7"
	SOURCE_VERSION="1.10"
	;;
  1.11)
	# Same flags as 1.12, but we need to build from 1.12 because there is no
	# 1.11 branch. This is really only used for wesnothd.
	CXXFLAGS="$CXXFLAGS -ggdb3 -DNUM_SHARDS=7"
	SOURCE_VERSION="1.12"
	;;
  1.13)
	CXXFLAGS="$CXXFLAGS -ggdb3 -DNUM_SHARDS=7"
	SOURCE_VERSION="1.14"
	;;
  trunk|master)
	CXXFLAGS="$CXXFLAGS -ggdb3 -O0"
	SOURCE_VERSION="master"
	BUILD_PRESET=debug
	;;
  *)
	CXXFLAGS="$CXXFLAGS -ggdb3"
	echo "Unrecognized version, building from 'master'..."
	SOURCE_VERSION="master"
	;;
esac

if [ $TYPE = campaignd ]; then
	case "$VERSION" in
	  1.8|trunk)
		CXXFLAGS="$CXXFLAGS -ggdb3 -pg"
		LDFLAGS="$LDFLAGS -pg"
		;;
	esac
fi

set -o nounset

SOURCE="$SOURCE_ROOT/$SOURCE_VERSION"
[ -d "$SOURCE" ] || die "Source directory '$SOURCE' not found!"

COMMIT=`( cd "$SOURCE" && git describe --long )`
[ -n "$COMMIT" ] || die "No revision information found. Odd, exiting..."

BUILD_ID="$TYPE-$VERSION-git-$COMMIT"

DEST="$DEST_ROOT/$BUILD_ID"
INT="$INT_ROOT/$SOURCE_VERSION"
SCONS_LOG="$DEST/scons.log"
CONF_LOG="$INT/build/config.log"

mkdir -p "$DEST" "$INT"

BUILD_OPTIONS=
if [ $TYPE = wesnothd ]; then
	BUILD_OPTIONS="fifodir=$DEST/var/run raw_sockets=1 forum_user_handler=1"
	case $(hostname) in
	  gonzo.dicp.de)
		BUILD_OPTIONS="fifodir=$DEST/var/run raw_sockets=1 boostdir=$HOME/tools/include boostlibdir=$HOME/tools/lib"
		;;
	  basilic)
		BUILD_OPTIONS="fifodir=$DEST/var/run raw_sockets=1"
		;;
	esac
fi

if [ "$TYPE" = "campaignd" ] && [ "$VERSION" != "1.14" ]; then
	BUILD_OPTIONS="forum_user_handler=1"
fi

mkdir -p "$DEST"/var/run

echo "            Version: $VERSION"
echo "         Source dir: $SOURCE"
echo "   Intermediate dir: $INT"
echo "    Destination dir: $DEST"
echo "   SCons output log: $SCONS_LOG"
echo "   SCons config log: $CONF_LOG"
echo "       Build preset: $BUILD_PRESET"

set -x

#
# Peform the build.
#

cd "$INT"

# HACK: help scons find autorevision from the source dir.
mkdir -p utils/; ln -sf "$SOURCE"/utils/autorevision.sh utils/

CXXFLAGS="$CXXFLAGS" LDFLAGS="$LDFLAGS" \
scons \
	-Y "$SOURCE" \
	--option-cache="$INT/.scons-option-cache" \
		install-$TYPE \
		prefix="$DEST" \
		program_suffix="-$VERSION" \
		profile=0 \
		fribidi=0 \
		python=0 \
		localedir= \
		prefsdir= \
		build="$BUILD_PRESET" \
		$BUILD_OPTIONS \
> "$SCONS_LOG"

# Discard the man pages.
rm -rf "$DEST"/share/

#
# Update the server instance directory.
#

cd "$SERVER_BASE"

test -L build &&
if [ -p "$SOCKET" ] || [ $TYPE = campaignd ]; then
	rm -f oldbuild
	mv build oldbuild
else
	# The server under build/ has never been started, keep the oldbuild link
	# to the (currently) running server.
	rm -f build
fi
ln -s "$DEST" build

#
# Update symlink in ~/bin/.
#

cd "$HOME"/bin || exit 1
ln -sf "$DEST/bin/$TYPE-$VERSION" "$TYPE-$VERSION"

set +x

echo "Build $BUILD_ID finished and installed as $TYPE-$VERSION."
