#!/bin/sh -e
#
# Copyright (C) 2000-2006  Dmitry V. Levin <ldv@altlinux.org>
#
# Generates list of package requires for given command.
#
# This program 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.
#

trap '' PIPE

PROG="${0##*/}"

OUTFILE=
ESSENTIAL='/etc/buildreqs/packages/essential'
IGNORE='/etc/buildreqs/packages/ignore.d'
SUBST='/etc/buildreqs/packages/substitute.d'
PACKAGEOF='/usr/bin/packageof'
FILEREQ='/usr/bin/filereq'
QUIET=

Info()
{
	printf %s\\n "${0##*/}: $*" >&2
}

Fatal()
{
	printf %s\\n "${0##*/}: $*" >&2
	exit 1
}

show_usage()
{
	[ -z "$*" ] || Info "$*"
	echo "Try \`$PROG --help' for more information." >&2
	exit 1
}

show_help()
{
	cat <<EOF
packagereq - generates list of file requires while running the program.

packagereq is free software, covered by the GNU General Public License.
packagereq comes with ABSOLUTELY NO WARRANTY, see license for details.

Usage: $PROG options <program> [program-args]

Valid options are:
-o FILENAME, --output=FILENAME      filename where to write output requires;
-e ESSENTIAL, --essential=ESSENTIAL filename where to get list of
                                    essential packages;
-i IGNORE, --ignore=IGNORE          directory where to get list of
                                    packages to ignore;
-s SUBST, --substitute=SUBST        directory where to get package
                                    name substitution rules;
-p PACKAGEOF, --packageof=PACKAGEOF path to PACKAGEOF;
-f FILEREQ, --filereq=FILEREQ       path to FILEREQ;
-q, --quiet                         be quiet;
-h, --help                          show this text.

There are no default filename for output.
Default file with list of essential packages is $ESSENTIAL.
Default directory where to get list of packages to ignore is $IGNORE.
Default directory where to get package name substitution rules is $SUBST.
Default path to PACKAGEOF is $PACKAGEOF.
Default path to FILEREQ is $FILEREQ.

EOF
	exit
}

TEMP=`getopt -n $PROG -o +o:e:f:i:p:s:r:qh -l output:,essential:,filereq:,ignore:,packageof:,substitute:,rpm:,quiet,help -- "$@"` || show_usage
eval set -- "$TEMP"

while :; do
	case "$1" in
		-o|--output) shift; OUTFILE="$1"; shift
			;;
		-e|--essential) shift; ESSENTIAL="$1"; shift
			;;
		-p|--packageof) shift; PACKAGEOF="$1"; shift
			;;
		-f|--filereq) shift; FILEREQ="$1"; shift
			;;
		-i|--ignore) shift; IGNORE="$1"; shift
			;;
		-s|--substitute) shift; SUBST="$1"; shift
			;;
		-q|--quiet) shift; QUIET=1
			;;
		-h|--help) show_help
			;;
		--) shift; break
			;;
		*) Fatal "Unrecognized option: $1"
			;;
	esac
done

# At least one argument, please.
[ "$#" -ge 1 ] || show_usage 'Insufficient arguments.'
# Output file, please.
[ -n "$OUTFILE" ] || show_usage 'Output file not specified.'

WORKDIR=
exit_handler()
{
	local rc=$?
	trap - EXIT
	[ -z "$WORKDIR" ] || rm -rf -- "$WORKDIR"
	exit $rc
}

trap exit_handler HUP INT TERM EXIT
trap : QUIT

export LC_COLLATE=C

WORKDIR="$(mktemp -dt "$PROG.XXXXXXXXXX")"

ls -1 "$IGNORE"/ >"$WORKDIR/ignore"
egrep -v '^[[:space:]]*(#|$)' "$ESSENTIAL" >>"$WORKDIR/ignore" ||:
sort -u -o "$WORKDIR/ignore" "$WORKDIR/ignore"
sed -i 's/^.*/^&$/' "$WORKDIR/ignore"

"$FILEREQ" "$WORKDIR/files" "$@"
[ -s "$WORKDIR/files" ] ||
	Fatal "ERROR: $FILEREQ produced no requires"

"$PACKAGEOF" -f "$WORKDIR/files" >"$WORKDIR/n0"
/usr/share/buildreqs/optimize_package_list <"$WORKDIR/n0" >"$WORKDIR/n1"

SubstIgnore()
{
	while read -r p; do
		[ -f "$SUBST/$p" ] &&
			cat "$SUBST/$p" ||
			printf %s\\n "$p"
	done |
	egrep -v -f "$WORKDIR/ignore" || [ $? = 1 ]
}

SubstIgnore <"$WORKDIR/n1" >"$WORKDIR/deps1"

# Calculate what has been optimized out.
cat >>"$WORKDIR/ignore" <<'EOF'
^lib[^-]+$
^(zlib|bzlib|glib|glib2)$
EOF
SubstIgnore <"$WORKDIR/n0" >"$WORKDIR/deps0"
sort -u -o "$WORKDIR/deps0" "$WORKDIR/deps0"
sort -u -o "$WORKDIR/deps1" "$WORKDIR/deps1"
comm -23 "$WORKDIR/deps0" "$WORKDIR/deps1" >"$WORKDIR/optimized-out"

REQS="$(cat "$WORKDIR/deps1" |tr '\n' ' ' |sed -e 's/ \+$//')"
printf %s\\n "$REQS" >"$OUTFILE"

if [ -z "$QUIET" ]; then
	if [ -s "$WORKDIR/optimized-out" ]; then
		Info "optimized out:" $(cat "$WORKDIR/optimized-out")
	fi
	Info "BuildRequires: ${REQS:-"(none)"}"
fi
