#!/bin/bash

###########################
# gotostable version 1.00
# Isaac Chanin, 2005
#
# This script finds unneeded entries in package.keywords and package.unmask
# and (optionally) removes them.
#
# This code is not copyrighted and is in the public domain.
# It comes with no warranty of any kind, explicit or otherwise.
###########################


if [ "$UID" -ne 0 ]
then
	echo "You must be root to run this script."
	exit 1
fi	

# If they entered a command-line parameter
if [ -n "$1" ]
then
	echo "gotostable - stablize your package.keywords and package.unmask"
	echo 
	echo "  usage:"
	echo "  $0"
	echo 
	echo "  (There are no options.)"
	exit 1
fi

# Finds not needed entries and (optionally) removes them
function removefunc
{
	unset packages remove
	fn=$1

	cd /etc/portage/
	echo
	echo "Checking $fn..."

	# Array of packages listed in $fn
	packages=( `cat $fn | awk '{ print $1 }' | egrep "^([a-z]|(<|>|=))" | sed "s/^[=|<|>]*\(.*\)$/\1/g" | sed "s/^\(.*\)-[0-9]\{1,\}.*$/\1/g" | xargs` )

	declare -a remove
	mv -f $fn $fn.bak.keep
	index=1
	# For each package (in the file)
	for i in "${packages[@]}"
	do
		# If we would get the same version without the keyword/unmasking
		if [ -n "`emerge -p $i | grep \ \ \ R\ \ \ \]`" ]
		then
			# Add it to removable array
			remove[index]=$i
			let "index=index+1"
			echo "The following package can be removed from $fn: $i"
		fi
	done

	# If there was anything to remove ask about removing it
	if [ "${#remove[@]}" -gt 0 ]
	then
		readyesno "Remove the not needed entries?"
		yesno=$?
		if [ "$yesno" -eq 1 ]
		then
			# Get some backups in case sed chokes
			mv -f $fn.bak.keep $fn.1
			cp -f $fn.1 $fn.bak
			strt=1
			index=2
			# For each removable package
			for i in "${remove[@]}"
			do
				# Hack to get around sed not liking /'s
				i=`echo "$i" | awk -F / '{ print $1 "\\\\/" $2 }'`
				# Remove it and increment index
				sed "/$i/d" $fn.$strt > $fn.$index
				rm -f $fn.$strt
				let "strt=strt+1"
				let "index=index+1"
			done
			# Move the final file to package.keywords
			mv -f $fn.$strt $fn
			# If file is not 0 bytes remove backup, otherwise use backup
			if [ `ls -l $fn | awk '{ print $5 }'` -ne 0 ]
			then
				rm -f $fn.bak
			else
				mv -f $fn.bak $fn
			fi
		else
			# If they don't want to auto-remove
			mv -f $fn.bak.keep $fn
		fi
	fi
	
	# If there was nothing to remove
	if [ -f "$fn.bak.keep" ]
	then
		mv -f $fn.bak.keep $fn
		echo "There is nothing to remove."
	fi
}

# Prompt a yes or no question
function readyesno
{
	unset yesno
	message=$1
	while [[ "$yesno" != "yes" && "$yesno" != "no" ]]
	do
		echo "$1 (yes/no)"
		read yesno
	done
	if [[ "$yesno" == "yes" ]]
	then
		return 1
	else
		return 0
	fi
}

# Only bother with asking if the file exists
if [ -f "/etc/portage/package.keywords" ]
then
	readyesno "Check package.keywords for needless keywords?"
	keywords=$?
fi

if [ -f "/etc/portage/package.unmask" ]
then
	readyesno "Check package.unmask for needlessly unmasked packages?"
	unmask=$?
fi

if [[ "$keywords" == 1 ]]
then
	removefunc package.keywords
fi
	
if [[ "$unmask" == 1 ]]
then
	removefunc package.unmask
fi

# If they said 'no' to both questions, or they don't have either files
if [[ "$keywords" == 0 && "$unmask" == 0 ]]
then
	echo 
	echo "You must have either"
	echo "  /etc/portage/packages.keywords"
	echo "  /etc/portage/packages.unmask"
	echo
	echo "in order to use this script."
fi

echo 
echo "Done."
