#!/bin/bash
#
# Build Debian packages inside Linux namespaces.
#
# Copyright (c) 2013, Alessandro Ghedini
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

set -e

export LANG=C
export LC_ALL=C

if [ -z "$PFLASK_ROOTCMD" ]; then
	PFLASK_ROOTCMD="sudo -E"
fi

if [ -z "$DEBUILD_DPKG_BUILDPACKAGE_OPTS" ]; then
	DEBUILD_DPKG_BUILDPACKAGE_OPTS=""
fi

if [ -z "$DEBUILD_LINTIAN" ]; then
	DEBUILD_LINTIAN="yes"
fi

if [ -z "$DEBUILD_LINTIAN_OPTS" ]; then
	DEBUILD_LINTIAN_OPTS="-IE --pedantic"
fi

if [ -f "$HOME/.devscripts" ]; then
	source "$HOME/.devscripts"
fi

if [ -f "/etc/devscripts.conf" ]; then
	source "/etc/devscripts.conf"
fi

if [ -z "${DIST}" ] && [ -r "debian/changelog" ]; then
	DIST=$(dpkg-parsechangelog | awk '/^Distribution: / {print $2}')
fi

: ${DIST:="$(lsb_release --short --codename)"}

: ${ARCH:="$(dpkg --print-architecture)"}

NAME="$DIST-$ARCH"

BASEDIR="/var/cache/pflask/base-$NAME"

BUILDDIR=$(pwd)
PKGDIR=$(basename $BUILDDIR)
RESDIR=$(dirname $BUILDDIR)
TMPDIR="/mnt"

if [ -r "debian/changelog" ]; then
	SRC=$(dpkg-parsechangelog | sed -rne 's,^Source: (.+).*,\1,p')
	VER=$(dpkg-parsechangelog | sed -rne 's,^Version: ([0-9]:)*(.+).*,\2,p')
elif [ "$1" != "--create" ] && [ "$1" != "--update" ]; then
	echo "E: Can't find 'debian/changelog'"
	exit -1
fi

CHANGES_FILE="${SRC}_${VER}_${ARCH}.changes"
DSC_FILE="${SRC}_${VER}.dsc"
DEBIAN_FILE="${SRC}_${VER}.debian.tar"
DIFF_FILE="${SRC}_${VER}.diff.tar.gz"
LOG_FILE="${SRC}_${VER}.build"

PFLASK_TOOL="$PFLASK_ROOTCMD $(which pflask)"
APT_TOOL="apt-get --no-install-recommends -y --force-yes"
TOOLS_TOOL="$APT_TOOL install devscripts equivs fakeroot lintian"
BDEPS_TOOL="mk-build-deps -r -i debian/control -t '$APT_TOOL'"
BUILD_TOOL="dpkg-buildpackage -tc -rfakeroot $DEBUILD_DPKG_BUILDPACKAGE_OPTS"
LINT_TOOL="lintian --allow-root $DEBUILD_LINTIAN_OPTS ../$CHANGES_FILE"
CHOWN_TOOL="chown --from=root:root"
DSIGN_TOOL="debsign"

if [ "$1" != "--create" ] && [ ! -d "$BASEDIR" ]; then
	echo "E: Missing base root directory '$BASEDIR'"
	exit -1
fi

BUILD_CMD="$TOOLS_TOOL && $BDEPS_TOOL && $BUILD_TOOL; FAIL=\$?"
BUILD_CMD="$BUILD_CMD && $CHOWN_TOOL -R $UID:$UID $TMPDIR/$PKGDIR"

FILES="$CHANGES_FILE $DSC_FILE $DEBIAN_FILE.gz $DEBIAN_FILE.xz $DIFF_FILE"

if [ -r "debian/control" ]; then
	for PKG in `dh_listpackages`;
	do
		FILES="$FILES ${PKG}_${VER}_${ARCH}.deb"
		FILES="$FILES ${PKG}_${VER}_${ARCH}.udeb"
		FILES="$FILES ${PKG}_${VER}_all.deb"
		FILES="$FILES ${PKG}_${VER}_all.udeb"
	done
elif [ "$1" != "--create" ] && [ "$1" != "--update" ]; then
	echo "E: Can't find 'debian/control'"
	exit -1
fi

for FILE in $FILES
do
	BUILD_CMD="$BUILD_CMD && [ -f $TMPDIR/$FILE ] && $CHOWN_TOOL $UID:$UID $TMPDIR/$FILE || true"
done

BUILD_CMD="$BUILD_CMD && [ \$FAIL = 0 ]"

if [ "$DEBUILD_LINTIAN" = "yes" ]; then
	BUILD_CMD="$BUILD_CMD && $LINT_TOOL"
fi

if [ "$1" = "--create" ]; then
	shift

	$PFLASK_ROOTCMD debootstrap				\
		--include=devscripts,equivs,fakeroot,lintian	\
		--arch=$ARCH --variant=buildd $DIST $BASEDIR $@
elif [ "$1" = "--update" ]; then
	$PFLASK_TOOL --chroot $BASEDIR				\
		--						\
		sh -c "$APT_TOOL update && $APT_TOOL dist-upgrade && $APT_TOOL autoremove --purge && $APT_TOOL autoclean"
else
	$PFLASK_TOOL --keepenv --chroot $BASEDIR --ephemeral	\
		--mount "bind:$RESDIR:$TMPDIR"			\
		--chdir "/mnt/$PKGDIR"				\
		--						\
		sh -c "$BUILD_CMD" | tee "../$LOG_FILE"

	$DSIGN_TOOL "$RESDIR/$CHANGES_FILE"
fi
