#!/bin/sh -e
#
# $Id: hsh,v 1.46 2004/07/19 08:26:15 ldv Exp $
# Copyright (C) 2003, 2004  Dmitry V. Levin <ldv@altlinux.org>
# 
# The hsh utility for the hasher project
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

if [ "$0" = ./hsh ]; then
	. ./functions
	hasher_dir="$(/bin/pwd)"
else
	. /usr/share/hasher/functions
fi

Usage()
{
	[ "$1" = 0 ] || exec >&2
	cat <<EOF
hsh - builds package using hasher utilities.

Usage: $PROG [options] <path-to-workdir> <package>...

<path-to-workdir> must be valid writable directory.

Valid options are:
  --with-stuff                      allow use of built packages;
  --without-stuff                   do not use built packages;
  --no-cache                        do not use initroot cache;
  --no-contents-indices             do not use content indices;
  --repackage-source                repackage source as well as binaries;
  --initroot-only                   do not build, stop after initroot stage;
  --no-sisyphus-check[=LIST]        do not run sisyphus_check tests
                                    [specified in comma-separated LIST];
  --no-sisyphus-check-in[=LIST]     do not run sisyphus_check input tests
                                    [specified in comma-separated LIST];
  --no-sisyphus-check-out[=LIST]    do not run sisyphus_check output tests
                                    [specified in comma-separated LIST];
  --rebuild-prog=PROG               program to run for rebuild instead of
                                    autogenerated script;
  --target=ARCH                     target architecture;
  --number=NUMBER                   subconfig identifier;
  --nprocs=NUMBER                   number of CPUs to use;
  --mountpoints=LIST                comma-separated list of known mount points;
  --install-langs=LANGLIST          colon-separated list of languages to install;
  --build-args=ARGS                 extra arguments for rpmbuild;
  --pkg-init-list=LIST              override default initial package file list;
  --pkg-build-list=LIST             override default build package file list;
  --apt-config=FILE                 path to custom apt.conf file;
  --apt-prefix=DIRECTORY            path to apt directory prefix (e.g. /usr);
  --hasher-priv-dir=DIR             hasher-priv directory;
  -q, --quiet                       try to be more quiet;
  -v, --verbose                     print a message for each action;
  -V, --version                     print program version and exit;
  -h, --help                        show this text and exit.
    
Report bugs to http://bugs.altlinux.ru/

EOF
	[ -n "$1" ] && exit "$1" || exit
}

TEMP=`getopt -n $PROG -o q,v,V,h -l with-stuff,without-stuff,no-stuff,no-cache,no-contents-indices,repackage-source,initroot-only,no-sisyphus-check::,no-sisyphus-check-in::,no-sisyphus-check-out::,rebuild-prog:,target:,number:,nprocs:,mountpoints:,hasher-priv-dir:,install-langs:,build-args:,contents-index-all:,contents-index-bin:,pkg-init-list:,pkg-build-list:,apt-config:,apt-prefix:,quiet,verbose,help,version -- "$@"` || Usage
eval set -- "$TEMP"

no_cache=
no_contents_indices=
nprocs=
rpmargs=
prog_rebuild=
install_langs=
known_mountpoints=
init_list=
build_list=
repackage_source=
apt_config=
initroot_only=
while :; do
	case "$1" in
		--with-stuff) no_stuff=
			;;
		--without-stuff|--no-stuff) no_stuff=1
			;;
		--no-cache) no_cache=1
			;;
		--no-contents-indices) no_contents_indices=1
			;;
		--repackage-source) repackage_source=1
			;;
		--initroot-only) initroot_only=1
			;;
		--no-sisyphus-check) shift
			[ -n "$1" ] && no_sisyphus_check="$1" || no_sisyphus_check=all
			;;
		--no-sisyphus-check-in) shift
			[ -n "$1" ] && no_sisyphus_check_in="$1" || no_sisyphus_check_in=all
			;;
		--no-sisyphus-check-out) shift
			[ -n "$1" ] && no_sisyphus_check_out="$1" || no_sisyphus_check_out=all
			;;
		--rebuild-prog) shift; prog_rebuild="$1"
			;;
		--target) shift; target="$1"
			[ -z "${target##[A-Za-z]*}" ] ||
				Fatal "--target: $target: invalid architecture."
			;;
		--build-args) shift; rpmargs="$1"
			;;
		--number) shift; number="${1##-}"
			[ -z "$(printf %s "$number" |tr -d [0-9])" ] ||
				Fatal "--number: $number: invalid number."
			number="-$number"
			;;
		--nprocs) shift; nprocs="$1"
			[ -z "$(printf %s "$nprocs" |tr -d [0-9])" ] ||
				Fatal "--nprocs: $nprocs: invalid number."
			;;
		--install-langs) shift; install_langs="$1"
			;;
		--mountpoints) shift; known_mountpoints="$1"
			;;
		--hasher-priv-dir) shift; hasher_priv_dir="$1"
			;;
		--pkg-init-list) shift; init_list="$1 "
			;;
		--pkg-build-list) shift; build_list="$1 "
			;;
		--apt-config) shift; apt_config="$1"
			[ -r "$apt_config" ] || Fatal "$apt_config: file not available."
			;;
		--apt-prefix) shift; apt_prefix="$1"
			[ -d "$apt_prefix" ] || Fatal "$apt_prefix: directory not available."
			;;
		-q|--quiet) quiet=-q
			;;
		-v|--verbose) verbose=-v
			;;
		-V|--version) print_version hsh
			;;
		-h|--help) Usage 0
			;;
		--contents-index-all|--contents-index-bin) shift # obsolete
			;;
		--) shift; break
			;;
		*) Fatal "unrecognized option: $1"
			;;
	esac
	shift
done

if [ -z "$initroot_only" ]; then
	# At least two arguments, please.
	[ "$#" -ge 2 ] || Usage
else
	# Exactly one argument, please.
	[ "$#" -eq 1 ] || Usage
fi

set_workdir "$1"
shift

set_apt_vars

for f in "$@"; do
	[ -z "${f##/*}" ] || f="$saved_cwd/$f"
	[ -r "$f" ] ||
		Fatal "${f##*/}: cannot access source"
	[ -s "$f" ] ||
		Fatal "${f##*/}: broken source"
done

exit_handler()
{
	local rc=$?
	trap - EXIT
	rm -rf -- lockdir
	exit $rc
}

pidfile="lockdir/pid"
if ! mkdir -m700 $verbose -- lockdir; then
	[ ! -s "$pidfile" ] ||
		Info "working directory \`$workdir' is locked, pid=`cat "$pidfile"`"
	Fatal "unable to create lock directory"
fi

trap exit_handler SIGHUP SIGPIPE SIGINT SIGQUIT SIGTERM EXIT

echo $$ >"$pidfile"

handle_package()
{
	local f="$1" && shift ||:
	[ -z "${f##/*}" ] || f="$saved_cwd/$f"

	rm -rf aptbox
	$hasher_dir/mkaptbox "$workdir" \
		${target:+--target="$target"} \
		${apt_config:+--apt-config="$apt_config"} \
		${quiet:+$quiet} \
		${verbose:+$verbose} \
		${no_stuff:+--no-stuff} \
		#
	[ ! -d chroot ] || $hasher_dir/rmchroot "$workdir" \
		${hasher_priv_dir:+--hasher-priv-dir="$hasher_priv_dir"} \
		${quiet:+$quiet} \
		${verbose:+$verbose} \
		${number:+--number=$number} \
		#
	$hasher_dir/mkchroot "$workdir" \
		${hasher_priv_dir:+--hasher-priv-dir="$hasher_priv_dir"} \
		${quiet:+$quiet} \
		${verbose:+$verbose} \
		${number:+--number=$number} \
		#
	$hasher_dir/initroot "$workdir" \
		${hasher_priv_dir:+--hasher-priv-dir="$hasher_priv_dir"} \
		${quiet:+$quiet} \
		${verbose:+$verbose} \
		${no_cache:+--no-cache} \
		${no_contents_indices:+--no-contents-indices} \
		${repackage_source:+--repackage-source} \
		${number:+--number=$number} \
		${nprocs:+--nprocs=$nprocs} \
		${install_langs:+--install-langs="$install_langs"} \
		${init_list:+--pkg-init-list="$init_list"} \
		${build_list:+--pkg-build-list="$build_list"} \
		#
	[ -n "$f" ] || return 0
	$hasher_dir/rebuild "$workdir" \
		${target:+--target="$target"} \
		${hasher_priv_dir:+--hasher-priv-dir="$hasher_priv_dir"} \
		${known_mountpoints:+--mountpoints="$known_mountpoints"} \
		${quiet:+$quiet} \
		${verbose:+$verbose} \
		${no_stuff:+--no-stuff} \
		${no_sisyphus_check:+--no-sisyphus-check="$no_sisyphus_check"} \
		${no_sisyphus_check_in:+--no-sisyphus-check-in="$no_sisyphus_check_in"} \
		${no_sisyphus_check_out:+--no-sisyphus-check-out="$no_sisyphus_check_out"} \
		${prog_rebuild:+--rebuild-prog="$prog_rebuild"} \
		${number:+--number=$number} \
		${rpmargs:+--args="$rpmargs"} \
		-- "$f"
}

if [ -z "$initroot_only" ]; then
	for f in "$@"; do
		handle_package "$f"
	done
else
	handle_package
fi
