#!/bin/sh

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

# Configuration file

CONFIG_FILE=/usr/local/etc/pkgfe.conf


# Paths

PORTS_PATH=${PORTSDIR:-/usr/ports}

PKGDB_PATH=${PKG_DBDIR:-/var/db/pkg}


# Miscellaneous

PAGER_PROGRAM=${PAGER:-less}


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

_prog()
{
	basename $0
}

_plural()
{
	if [ $1 -ne 1 ]
	then
		echo 's'
	fi
}


do_help()
{
local P

P=`_prog`

echo "
--- Package Frondend help ---


$P list		Generate outdated packages list using portversion

$P cvs		Update ports tree using Csup
			Run make fetchindex in $PORTS_PATH
			Run portsdb -u
			Run $P list

$P all		Run $P cvs
			Run $P

$P list+run		Run $P list
			Run $P

$P			Show upgrade dialog

$P fixdb		Run pkgdb -F

$P find		Run make search in $PORTS_PATH

$P ls		Search packages in $PKGDB_PATH

$P chkreq		Check for not required packages

$P padb		Run portaudit -Fd

$P chkbin		Check for existence of required programs

$P help		This help
"

exit 0
}


error()
{
	if [ "$1" ]
	then
		echo "`_prog`: $1"
		exit 1
	fi
}

notice()
{
	if [ "$1" ]
	then
		echo "`_prog`: $1"
	fi
}


do_list()
{
	local NUM PORTVERSION_COMMAND
	
	PORTVERSION_COMMAND="portversion -vl <"
	
	echo
	echo "> $PORTVERSION_COMMAND"
	
	$PORTVERSION_COMMAND | \
	sed 's/<//; s/needs updating (port has //; s/) *$//' > \
	"$STATUSFILE" || exit 1
	
	echo
	
	
	NUM=`wc -l "$STATUSFILE" | awk '{print $1}'`
	
	echo '-----------------------------------'
	echo "Found $NUM outdated package`_plural $NUM`"
	echo '-----------------------------------'
	
	if [ "$NUM" -eq 0 -a "$1" = exit-if-none ]
	then
		exit 0
	fi
	
	echo
}

do_csup()
{
	local OLD_WD CSUP_COMMAND PORTSDB_COMMAND
	
	
	check_file "$CSUP_SUPFILE"
	
	
	CSUP_COMMAND="csup $CSUP_ARGS $CSUP_SUPFILE"
	
	echo
	echo "> $CSUP_COMMAND"
	
	$CSUP_COMMAND || exit 1
	
	echo
	
	
	echo
	echo "> cd $PORTS_PATH && make fetchindex"
	
	OLD_WD=`pwd`
	
	cd $PORTS_PATH && make fetchindex && \
	cd "$OLD_WD" || exit 1
	
	echo
	
	
	PORTSDB_COMMAND="portsdb -u"
	
	echo
	echo "> $PORTSDB_COMMAND"
	
	$PORTSDB_COMMAND || exit 1
	
	echo
	
	
	do_list
}

do_fixdb()
{
	local PKGDB_COMMAND
	
	PKGDB_COMMAND="pkgdb -F"
	
	echo
	echo "> $PKGDB_COMMAND"
	
	$PKGDB_COMMAND || exit 1
	
	echo
	
	exit 0
}

do_find()
{
	local TYPE STR
	
	TYPE=name
	STR="$1"
	
	
	if [ ! "$STR" ]
	then
		error "error: empty search string"
	fi
	
	
	case "$1"
	in
		name|key)
			TYPE="$1"
			STR="$2"
			;;
	esac
	
	
	echo
	echo "> cd $PORTS_PATH && make search $TYPE=$STR"
	
	cd $PORTS_PATH && \
	( make search "$TYPE"="$STR" | $PAGER_PROGRAM )
	
	exit 0
}

do_ls()
{
	[ "$1" ] || error 'one parameter, package name, is required'
	
	( ls -1 $PKGDB_PATH | \
	grep -v pkgdb.db | \
	grep -iE "$1" ) || \
	error "error: no packages matching '$1' found"
	
	exit 0
}

do_chkreq()
{
	local tmpfile NUM DIALOG_PKGLIST PACKAGES
	
	cd $PKGDB_PATH || exit 1
	
	tmpfile=`make_tmp`
	
	
	NUM=0
	
	for name in *
	do
		if [ ! "$name" = pkgdb.db -a ! -f "$name/+REQUIRED_BY" ]
		then
			DIALOG_OPTIONS="$DIALOG_OPTIONS '$name' 'no +REQUIRED_BY' OFF"
			
			NUM=$(($NUM + 1))
		fi
	done
	
	eval "dialog --title '`_prog`: chkreq' \
	--checklist '\n$NUM not required package`_plural $NUM`\n' \
	-1 -1 $DIALOG_LIST_HEIGHT \
	$DIALOG_OPTIONS \
	2> '$tmpfile'"
	
	
	PACKAGES=`cat "$tmpfile"`
	
	rm -f "$tmpfile"
	
	
	if [ "$PACKAGES" ]
	then
		echo '-----------------------------------'
		echo 'Execute that manually:'
		echo
		echo "pkg_deinstall $PACKAGES"
		echo
		echo '-----------------------------------'
	fi
	
	exit 0
}

do_padb()
{
	local PORTAUDIT_COMMAND
	
	PORTAUDIT_COMMAND="portaudit -Fd"
	
	echo
	echo "> $PORTAUDIT_COMMAND"
	
	$PORTAUDIT_COMMAND || exit 1
	
	echo
}

do_checkbinaries()
{
	for binary in portupgrade portversion dialog \
	csup portsdb pkgdb portaudit $PAGER_PROGRAM
	do
		which "$binary" > /dev/null
		
		if [ $? -gt 0 ]
		then
			error "$binary: program not found"
		else
			echo "$binary = OK"
		fi
	done
	
	exit 0
}


check_file()
{
	if [ ! -f "$1" ]
	then
		error "$1: file not found"
		
	elif [ ! -r "$1" ]
	then
		error "$1: file not readable"
	fi
}

check_statusfile()
{
	if [ ! -r "$1" ]
	then
		touch "$1"
		
		if [ $? -gt 0 ]
		then
			error "Cannot create status file '$1'"
		fi
	fi
}

check_portupgrade_logdir()
{
	if [ ! "$1" ]
	then
		return 0
	fi
	
	if [ ! -d "$1" ]
	then
		notice "$1: directory not found"
		
	elif [ ! -w "$1" ]
	then
		notice "$1: directory not writable"
		
	else
		return 0
	fi
	
	echo
	echo "If you don't want logging,"
	echo "comment out following varibles in ${CONFIG_FILE}:"
	echo ' PORTUPGRADE_LOGDIR'
	echo ' PORTUPGRADE_ARGS'
	exit 1
}


make_tmp()
{
	mktemp -t "`_prog`"
}


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

if [ `id -u` -gt 0 ]
then
	error 'Requires root'
fi


if [ `uname -s` != FreeBSD ]
then
	error 'Requires FreeBSD'
fi


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

check_file "$CONFIG_FILE"

. "$CONFIG_FILE"


check_portupgrade_logdir "$PORTUPGRADE_LOGDIR"

check_statusfile "$STATUSFILE"


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

case "$1"
in
	listup|list)
		do_list
		exit 0
		;;
	cvsup|cvs|csup)
		do_csup
		exit 0
		;;
	fixdb|fix)
		do_fixdb
		;;
	find|portfind)
		do_find "$2" "$3"
		;;
	ls|lspkg)
		do_ls "$2"
		;;
	chkreq)
		do_chkreq
		;;
	padb)
		do_padb
		exit 0
		;;
	all)
		do_csup
		;;
	listup+run|list+run)
		do_list
		;;
	chkbin)
		do_checkbinaries
		;;
	help)
		do_help
		;;
esac


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

if [ ! -s "$STATUSFILE" ]
then
	do_list exit-if-none
fi


TMPOPTIONSFILE=`make_tmp`


NUM=0

while read name comments
do
	DIALOG_OPTIONS="$DIALOG_OPTIONS '$name' '< $comments' OFF"
	
	NUM=$(($NUM + 1))
done < \
"$STATUSFILE"


if [ ! "$DIALOG_OPTIONS" ]
then
	error 'Error: $DIALOG_OPTIONS is empty'
fi


eval "dialog --title '`_prog`: list' \
--checklist '\nFound $NUM outdated package`_plural $NUM`\n' \
-1 -1 $DIALOG_LIST_HEIGHT \
$DIALOG_OPTIONS \
2> '$TMPOPTIONSFILE'"


PACKAGES=`sed 's/"//g' < "$TMPOPTIONSFILE"`

rm -f "$TMPOPTIONSFILE"


if [ "$PACKAGES" ]
then
	NUM=0
	
	for package in $PACKAGES
	do
		UPGRADE_DIALOG="$UPGRADE_DIALOG '$package' ' '"
		
		NUM=$(($NUM + 1))
	done
	
	
	eval "dialog --title '`_prog`: upgrade' \
	--menu '\nUpgrade $NUM package`_plural $NUM`?\n' \
	-1 -1 $DIALOG_LIST_HEIGHT \
	$UPGRADE_DIALOG \
	2> /dev/null"
	
	
	case $?
	in
		0)
			echo
			do_padb
			
			
			PORTUPGRADE_COMMAND="portupgrade -v $PORTUPGRADE_ARGS $PACKAGES"
			
			echo
			echo "> $PORTUPGRADE_COMMAND"
			
			$PORTUPGRADE_COMMAND
			
			
			if [ $? = 0 ]
			then
				case "$LISTUP_AFTER_UPGRADE"
				in
					[Yy][Ee][Ss])
						echo
						do_list
						;;
				esac
			fi
			
			exit 0
			;;
		*)
			echo
			echo 'Upgrade cancelled'
			echo
			
			exit 0
			;;
	esac
	
else
	echo
	echo 'No packages selected'
	echo
	
	exit 0
fi


# EOF

