#!/bin/sh -ef
export LC_ALL=C

arch= aptconf= sourceslist= cachelimit=
while getopts a:c:l:s:h opt; do
	case "$opt" in
		a) arch="${OPTARG:?}" ;;
		c) aptconf="$(readlink -ev "${OPTARG:?}")" ;;
		l) cachelimit="${OPTARG:?}" ;;
		s) sourceslist="$(readlink -ev "${OPTARG:?}")" ;;
		h) pod2usage --exit=0 "$0"; exit 0 ;;
		*) pod2usage --exit=2 "$0"; exit 2 ;;
	esac
done
shift "$((OPTIND-1))"

if [ $# -gt 0 ]; then
	echo "${0##*/}: too many arguments" >&2
	pod2usage --exit=2 "$0"; exit 2
fi

make_aptbox()
{
	rm -f apt.conf sources.list
	if [ -n "$aptconf" ]; then
		cat "$aptconf" >apt.conf
	else
		cat >apt.conf <<__EOF__
Dir::Etc::main "/dev/null";
Dir::Etc::parts "/var/empty";
__EOF__
	fi
	if [ -n "$sourceslist" ]; then
		cat "$sourceslist" >sources.list
		cat >>apt.conf <<__EOF__
Dir::Etc::sourcelist "$PWD/sources.list";
Dir::Etc::sourceparts "/var/empty";
__EOF__
	fi
	if [ -n "$cachelimit" ]; then
		cat >>apt.conf <<__EOF__
APT::Cache-Limit "$cachelimit";
__EOF__
	fi
	rm -rf aptbox
	mkaptbox -q ${arch:+--target=$arch} --without-stuff --apt-config=apt.conf "."
}

# entry ::= package dependency
# package ::= name#version
show_unmets()
{
	./aptbox/apt-cache unmet >apt.out
	awk -f - apt.out >awk.out <<'__EOF__'
	NF>3 && $1=="Package" && $3=="version" {
		if (index($2, "#" $4) == 0)
			package = $2 "#" $4
		else
			package = $2
		next
	}
	NF>1 && $1~/Depends:$/ {
		if (NF>3) {
			sub("[)]$", "", $NF)
			sub("^[(]", "", $(NF-1))
		}
		$1 = package
		sub(" ", "\t")
		print
		next
	}
	NF>0 {
		print "unmets: bad apt output:" >"/dev/stderr"
		print >"/dev/stderr"
		exit 1
	}
__EOF__
	sort -u awk.out
}

if [ -z "$workdir" ]; then
	. tmpdir.sh
	workdir="$TMPDIR"
fi

cd "${workdir:?}"
make_aptbox
show_unmets
cd - >/dev/null

# The rest is for qa-robot.
noun="unmet dependency"

fmt_plus()
{
	subj="$subj +$1"
	echo "	$1 NEW $2 detected:"
	awk -F'\t' '{printf "%-24s\t%s\n", $1, $2}'
	echo
}

fmt_minus()
{
	subj="$subj -$1"
	echo "	$1 $2 have been RESOLVED:"
	awk -F'\t' '{printf "%-24s\t%s\n", $1, $2}'
	echo
}

fmt_total()
{
	n=`sort -u -k1,1 |wc -l`
	subj="$subj ($1/$n)"
	echo "Total $n $(count "$n" package) have $1 $2."
}

: <<'__EOF__'

=head1	NAME

unmets - show unmet dependencies

=head1	SYNOPSIS

B<unmets>
[B<-h>]
[B<-a> I<arch>]
[B<-c> I<aptconf>]
[B<-l> I<apt-cache-limit>]
[B<-s> I<sourceslist>]

=head1	DESCRIPTION

B<unmets> shows unmet dependencies in the B<apt> repositories currently
being used.  It uses B<mkaptbox> to create initial B<apt> environment
which is largely free of the host system influence.  Furthermore, by
using minimal I<apt.conf>, most of the B<apt> configuration is reset to
its initial state (however, I<sources.list> configuration is inherited
by default).

B<unmets> produces two-column output (one line per each unmet dependency).
Column one contains package name and its version, separated by "#" character.
Column two contains the dependency (which is possibly versioned).
Sample output:

	ccs#0.0.cvs20050330-alt1	/etc/sysconfig/cluster
	cman#0.0.cvs20050330-alt1	/etc/sysconfig/cluster
	drwright#0.18-alt2	libdbus-1.so.0
	drwright#0.18-alt2	libdbus-glib-1.so.0
	encfs#1.2.0-alt3	fuse = 2.2-alt5

B<unmets> is part of B<qa-robot>.  When I<workdir> environment variable is set,
it is treated as a working directory to store temporary files under.  Otherwise,
temporary directory is created for this purpose, and then removed upon exit.

=head1	OPTIONS

=over

=item	B<-a> I<architecture>

Architecture to pass to mkaptbox.

=item	B<-c> I<aptconf>

Path to custom I<apt.conf> file.

=item	B<-l> I<apt-cache-limit>

Value of APT::Cache-Limit to add to apt.conf.

=item	B<-s> I<sourceslist>

Path to custom I<sources.list> file.

=item	B<-h>

Display this help and exit.

=back

=head1	AUTHOR

Written by Alexey Tourbin <at@altlinux.org>.

=head1	COPYING

Copyright (c) 2005, 2006 Alexey Tourbin, ALT Linux Team.

This 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.

=head1	SEE ALSO

apt(8),
apt-cache(8), 
mkaptbox(1),
apt.conf(5),
sources.list(5),
qa-robot(1)

=cut

__EOF__
