#!/bin/sh

# Copyright (c) 2008-2011 Aleksey Cheusov <vle@gmx.net>
# All rights reserved.
#
# See LICENSE file

######################################################################

set -e

. /usr/pkg/bin/pipestatus

: ${DISTBB_CONF:=/usr/pkg/etc/distbb.conf}
. "$DISTBB_CONF"

. /usr/pkg/libexec/psu/sig_handler.sh
on_exit () { rm -rf $tmp_dir; }

unset PKG_PATH || true
unset PKG_SUFX || true

export BINPKG_SITES="$PACKAGES"
export DISTBB_CONF

if test -n "$LD_PRELOAD"; then
    export LD_PRELOAD
fi
if test -n "$LIBKVER_OSRELEASE"; then
    export LIBKVER_OSRELEASE
fi

eval "$SLAVE_CMD" 1>&2

######################################################################
# temp directory
tmp_dir=`mktemp -d /tmp/distbb_slave.XXXXXX`
test -n "$tmp_dir"

tmpfn="$tmp_dir/tmpfn.tmp"
logfn="$tmp_dir/log.tmp"
######################################################################

usage (){
    cat 1>&2 <<EOF
slave - program run on slave hosts

usage: slave [OPTIONS]
OPTIONS:
  -h|--help              display this help message
EOF
}

while test $# -ne 0; do
    case "$1" in
	-h|--help)
	    usage
	    exit 0;;
	--)
	    shift
	    break;;
	-*)
	    echo "Bad option $1" 1>&2
	    exit 1;;
	*)
	    break
    esac
    shift
done

if test $# -ne 0; then
    usage
    exit 1
fi

######################################################################
# exporting for special target Init

get_var (){
    ${BMAKE} "$@" -f - my-show-var BSD_PKG_MK=yes <<'EOF'
.PHONY: my-show-var
my-show-var:
	@echo ${${VARNAME}:Q}
EOF
}

if test -n "$TARGET_MAKECONF"; then
    export TARGET_PACKAGES=`get_var -f $TARGET_MAKECONF VARNAME=PACKAGES`
    export TARGET_PKG_DBDIR=`get_var -f $TARGET_MAKECONF VARNAME=PKG_DBDIR`
    export TARGET_PREFIX=`get_var -f $TARGET_MAKECONF VARNAME=LOCALBASE`
    export TARGET_SYSROOT=`get_var -f $TARGET_MAKECONF VARNAME=SYSROOT`
    export TARGET_ARCH=`get_var -f $TARGET_MAKECONF VARNAME=TARGET_ARCH`
fi

export BH_PACKAGES="$PACKAGES"
export BH_PKG_DBDIR="$PKG_DBDIR"

export EXTRACT_BOOTSTRAP_CMD
export RMDIRS_CMD

######################################################################

# < /dev/null - for building packages that require
# an interaction with user
if test "$STDIN_FROM_DEV_NULL"; then
    stdin_from_dev_null=' < /dev/null'
else
    stdin_from_dev_null=''
fi

header (){
    printf ' --**--**-- %8s --**--**--\n' "$1"
}

# remove comments from "$SPECIAL_PACKAGES"
remove_comments (){
    awk '
    NF == 0 {
	print
	next
    }
    {
	sub(/#.*$/, "")
	if (NF > 0) {
	    $1 = $1
	    print
	}
    }' "$@"
}

save_TARGETS_and_EXTRA_OPTS (){
    orig_TARGETS="$TARGETS"
    orig_EXTRA_OPTS="$EXTRA_OPTS"
}

restore_TARGETS_and_EXTRA_OPTS (){
    TARGETS="$orig_TARGETS"
    EXTRA_OPTS="$orig_EXTRA_OPTS"
}

do_build_package (){
    # $1 - long pkgpath, e.g. www/php-apc:PHP_VERSION_REQD=5
    # $2 - real pkgpath, e.g. www/php-apc

    header preinit

    # new targets? new extra_opts?
    echo "$SPECIAL_PACKAGES" |
    remove_comments |
    pkg_grep_summary 'PKGPATH' "\$2 == \"$1\"" > $tmpfn

    new_TARGETS="`sed -n 's,^TARGETS=,,p' $tmpfn`"

    if test "$new_TARGETS"; then
	TARGETS="$new_TARGETS"
    fi

    new_EXTRA_OPTS="`sed -n 's,^EXTRA_OPTS=,,p' $tmpfn`"
    if test "$new_EXTRA_OPTS"; then
	EXTRA_OPTS="$new_EXTRA_OPTS"
    fi

    #
    if ! cd "$PKGSRCDIR/$2"; then
	return 1
    fi

    # $TARGETS
    bmake_opts="$EXTRA_OPTS $multivar_opts"
    export bmake_opts

    for t in $TARGETS; do
	header $t

	case "$t" in
	    Init)
		# remove /usr/pkg and unpack bootstrap
		if test -n "$TH_pkg"; then
		    if test -z "$TARGET_SYSROOT" -o -z "${TARGET_PREFIX}" -o -z "${TARGET_PKG_DBDIR}"; then
			echo 'TARGET_* variables must be non-empty!' 1>&2
			return 1
		    fi

		    rm -rf "${TARGET_SYSROOT}${TARGET_PREFIX}"
		    rm -rf "${TARGET_SYSROOT}${TARGET_PKG_DBDIR}"
		else
		    eval $RMDIRS_CMD
		    eval $EXTRACT_BOOTSTRAP_CMD
		fi
		;;
	    *)
		case "${t}_${TH_pkg}" in
		    *_|Depends_1)
			bmake_env=;;
		    *)
			bmake_env="MAKECONF=$TARGET_MAKECONF";;
		esac

		bmake_env="$bmake_env PKGPATHe=$BH_pkg$1 BH_pkg=$BH_pkg"

		set +e
		(
		    eval "$ULIMIT_CMD"
		    eval "\$SU_UNPRIV_CMD_$t" \
			env $bmake_env $BMAKE -f Makefile \
			-f "$DISTBB_LOCAL_MK" \
			-f /usr/pkg/share/distbb/distbb.mk \
			$bmake_opts $t $stdin_from_dev_null
		) || return $?
		set -e
		;;
	esac
    done
}

pkgpath2multivar_opts (){
    sed -e 's|^[^:]*:||' -e 's|,| |g' -e "s|[^ ][^ ]*|'&'|g" -e 's|~| |g'
}

build_package (){
    # $1 - long pkgpath, e.g. www/php-apc:PHP_VERSION_REQD=5
    multivar_opts=''
    unset MAKECONF || true # ksh, dash, pdksh

    BH_pkg=
    TH_pkg=
    if ! is_true "$CROSS_COMPILE"; then
	long_pkgpath="$1"
    elif echo "$1" | grep ^BH-- > /dev/null; then
	BH_pkg='BH--'
	long_pkgpath=`echo $1 | cut -b 5-`
    else
	TH_pkg=1
	long_pkgpath="$1"
    fi

    real_pkgpath="`echo $long_pkgpath | cut -d: -f1`"
    if test "$real_pkgpath" != "$long_pkgpath"; then
	multivar_opts="$(echo $long_pkgpath | pkgpath2multivar_opts)"
    fi

    do_build_package "$long_pkgpath" "$real_pkgpath" 2>&1
    ex=$?

    if test -n "${TH_pkg}"; then
	bmake_env="MAKECONF=$TARGET_MAKECONF"
    else
	bmake_env=
    fi

    # clean even if it fails
    if test "_$CLEAN_TARGET" != "_None"; then
	eval $bmake_env $BMAKE "$CLEAN_TARGET" $multivar_opts \
	    $stdin_from_dev_null > /dev/null 2>&1
    fi

    unset MAKECONF || true # ksh, dash, pdksh

    #
    return $ex
}

check_max_log_size (){
    awk -v limit="$LOG_SIZE_LIMIT" '
    {
	print " " $0 # space is for paexec! empty line is not allowed!
#	print $0

	curr += length($0)+1
	if (limit && curr >= limit){
	    print " Maximum log size is reached! Exiting..."
	    exit 1
	}
    }' "$@"
}

save_TARGETS_and_EXTRA_OPTS

while read pkgpath; do
    restore_TARGETS_and_EXTRA_OPTS

    runpipe_base build_package $pkgpath '|' check_max_log_size > "$logfn"
    case "$pipestatus_1" in
	0)
	    echo success;;
	*)
	    cat "$logfn"
	    echo failure;;
    esac

    #
    echo '' # end of task marker
done
