#!/bin/sh -ef
#
# Copyright (C) 2003-2008  Dmitry V. Levin <ldv@altlinux.org>
# Copyright (C) 2006  Alexey Gladkov <legion@altlinux.org>
# 
# The hsh-rebuild 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#

. hsh-sh-functions

show_help()
{
	cat <<EOF
hsh-rebuild - rebuild source package in chroot prepared by hsh-initroot.

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

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

Options:
  --args=ARGS                       extra arguments for rpmbuild;
  --excludedocs                     do not install documentation files;
  --hasher-priv-dir=DIR             hasher-priv directory;
  --install-only                    do not build, stop after installing build dependencies;
  --mountpoints=LIST                comma-separated list of known mount points;
  --nodeps                          ignore package dependencies (dangerous);
  --no-sisyphus-check-in[=LIST]     do not run sisyphus_check input tests [specified in LIST];
  --no-sisyphus-check[=LIST]        do not run sisyphus_check tests [specified in LIST];
  --no-sisyphus-check-out[=LIST]    do not run sisyphus_check output tests [specified in LIST];
  --number=NUMBER                   subconfig identifier;
  --query-repackage                 repackage the source before query for requirements;
  --query-req-prog=FILE             program to run to query for requirements instead of autogenerated script;
  --rebuild-prog=FILE               program to run for rebuild instead of autogenerated script;
  --repo=DIR                        repository directory;
  --repo-bin=DIR                    binary packages destination directory,
                                    overriding --repo option for binary packages;
  --repo-src=DIR                    source packages destination directory,
                                    overriding --repo option for source packages;
  --source-only                     do not build, stop after installing source package;
  --target=ARCH                     target architecture;
  --wait-lock                       wait for workdir and hasher-priv locks;
  --no-wait-lock                    do not wait for workdir and hasher-priv locks;
  --without-stuff                   do not generate apt index files;
  --with-stuff                      generate apt index files;
  -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
	exit
}

TEMP=`getopt -n $PROG -o $getopt_common_opts -l args:,excludedocs,hasher-priv-dir:,install-only,mountpoints:,nodeps,no-lock,no-sisyphus-check::,no-sisyphus-check-in::,no-sisyphus-check-out::,no-stuff,number:,query-repackage,query-req-prog:,rebuild-prog:,repo:,repo-bin:,repo-src:,save-fakeroot,source-only,target:,wait-lock,no-wait-lock,without-stuff,with-stuff,$getopt_common_longopts -- "$@"` ||
	show_usage
eval set -- "$TEMP"

nodeps=
install_only=
source_only=
while :; do
	case "$1" in
		--args) shift; rpmargs="$1"
			;;
		--excludedocs) exclude_docs=--excludedocs
			;;
		--hasher-priv-dir)
			hasher_priv_dir="$(opt_check_dir "$1" "$2")"
			shift
			;;
		--install-only) install_only=1
			;;
		--mountpoints) shift; known_mountpoints="$1"
			;;
		--nodeps) nodeps=--nodeps
			;;
		--no-lock) no_lock=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
			;;
		--number)
			number="$(opt_check_number_ge_0 "$1" "$2")"
			shift
			;;
		--query-repackage) query_repackage=1
			;;
		--query-req-prog)
			prog_query_req="$(opt_check_read "$1" "$2")"
			shift
			;;
		--rebuild-prog)
			prog_rebuild="$(opt_check_read "$1" "$2")"
			shift
			;;
		--repo) shift; repo="$1"
			;;
		--repo-bin) shift; repo_bin="$1"
			;;
		--repo-src) shift; repo_src="$1"
			;;
		--source-only) source_only=1
			;;
		--save-fakeroot) message "Warning: obsolete option $1 ignored."
			;;
		--target) shift; target="$1"
			[ -z "${target##[A-Za-z]*}" ] ||
				fatal "--target: $target: invalid architecture."
			;;
		--wait-lock) lock_nowait=
			;;
		--no-wait-lock) lock_nowait=1
			;;
		--without-stuff|--no-stuff) no_stuff=1
			;;
		--with-stuff) no_stuff=
			;;
		--) shift; break
			;;
		*) parse_common_option "$1"
			;;
	esac
	shift
done

if [ -n "$prog_query_req" -a -n "$query_repackage" ]; then
	show_usage '--query-req-prog and --query-repackage are mutually exclusive options.'
fi

if [ -z "$workdir" ]; then
	# Exactly two arguments.
	[ "$#" -ge 2 ] || show_usage 'Insufficient arguments.'
	[ "$#" -le 2 ] || show_usage 'Too many arguments.'
else
	# At least one and at most two arguments.
	[ "$#" -ge 1 ] || show_usage 'Insufficient arguments.'
	[ "$#" -le 2 ] || show_usage 'Too many arguments.'
fi

if [ "$#" -eq 2 ]; then
	set_workdir "$1"
	shift
else
	set_workdir
fi

source="$1"
[ -z "${source##/*}" ] || source="$saved_cwd/$source"

sname="${source##*/}"
shift

lock_workdir
[ -d "$chroot" ] || fatal "$chroot: cannot find chroot."
deduce_lock_hasher_priv

# Create rebuild script.
if [ -n "$prog_rebuild" ]; then
	install -p -m755 $verbose "$prog_rebuild" chroot/.host/rebuild >&2
else
	cat >"chroot/.host/rebuild" <<__EOF__
#!/bin/sh -le
${verbose:+set -x}
export -n target ||:
exec >&2 time rpmbuild --rebuild --target="\$target" $nodeps $rpmargs "\$@"
__EOF__
	chmod 755 "chroot/.host/rebuild"
	verbose 'Created rebuild script.'
fi

. hsh-sh-rebuild-functions

install_source_package

# Execute sisyphus_check for input.
run_sisyphus_check '$HOME/in/srpm' "$no_sisyphus_check_in"

[ -z "$source_only" ] || exit 0

# Calculate, check and install build dependencies.
if [ -z "$nodeps" ]; then
	# Create query script.
	if [ -n "$prog_query_req" ]; then
		install -p -m755 $verbose "$prog_query_req" chroot/.host/query_req >&2
	elif [ -n "$query_repackage" ]; then
		cat >chroot/.host/query_req <<__EOF__
#!/bin/sh -e
${rpmi:-$def_rpmi} -i -- "\$@"
cd \`rpm --eval %_specdir\`
rpmbuild -bs --nodeps \\
	--target="$(quote_shell "${target:-$def_target}")" \\
	--define '_allow_undefined_macros 1' \\
	$rpmargs \\
	--define "_source_payload w1.gzdio" \\
	-- *.spec >/dev/null
cd \`rpm --eval %_srcrpmdir\`
rpmquery -pR -- "\$@"
__EOF__
	else
		cat >chroot/.host/query_req <<__EOF__
#!/bin/sh -e
rpmquery -pR -- "\$@"
__EOF__
	fi
	chmod 755 chroot/.host/query_req

	create_entry_header
	cat >>"$entry" <<__EOF__
cd "\$HOME/in/srpm"
/.host/query_req *
__EOF__

	calc_check_install_build_deps
	calculate_required_mountpoints "$build_deps"
	calculate_required_mountpoints_from_installed
fi

[ -z "$install_only" ] || exit 0

# Build the package.
purge_chroot_out
run_rebuild

# Execute sisyphus_check for output.
run_sisyphus_check '/.out' "$no_sisyphus_check_out" gpg

# Copy binaries from chroot.
case `find chroot/.out/ -mindepth 1 -maxdepth 1 -type f -name \*.src.rpm |LC_ALL=C grep -c '\.src\.rpm$'` in
	0) subdir=.in ;;
	1) subdir=.out ;;
	*) fatal 'Too many src.rpm files written.' ;;
esac

make_repo
repo_bin="${repo_bin:-${repo:-$def_repo}/"${target:-$def_target}"/RPMS.hasher/}"
repo_src="${repo_src:-${repo:-$def_repo}/SRPMS.hasher/}"

find chroot/$subdir/ -mindepth 1 -maxdepth 1 -type f -name \*.src.rpm -print0 |
	xargs -r0 mv -f $verbose --target-directory="$repo_src" -- >&2

find chroot/.out/ -mindepth 1 -maxdepth 1 -type f -name \*.rpm -print0 |
	xargs -r0 mv -f $verbose --target-directory="$repo_bin" -- >&2

purge_chroot_out
