#!/bin/bash

LOG=/tmp/perl-update.log

echo "The script will attempt to re-emerge your perl modules, any packages"
echo "that compiled against libperl.so previously, as well as any packages"
echo "that placed files in /usr/lib/perl*. A log of its attempts, work, and"
echo "even failures is kept in ${LOG} - please refer to this log should you"
echo "experience any difficulties."


echo "--------------------------------------------------------------" >> $LOG
echo "--------------------------------------------------------------" >> $LOG
echo "--------------------------------------------------------------" >> $LOG


echo 'Finding what perl modules you have installed...'
echo 'Finding what perl modules you have installed...' >> $LOG


cd /var/db/pkg/dev-perl
PRE_MODULE_LIST=`
	for i in $(ls -1| sort | uniq)
	do
	   echo "dev-perl/${i}"
	done | sed 's/-[0-9].*//g' | sort -u `



echo "Preliminary Module List: $PRE_MODULE_LIST"
echo "Preliminary Module List: $PRE_MODULE_LIST" >> $LOG

#First, we clean up the perl module list - this is to avoid ambiguities later
echo "Cleaning Module List..."
echo "Cleaning Module List..." >> $LOG


for MODULE in $PRE_MODULE_LIST;
do
	env-update
	echo "Cleaning $MODULE"
	echo "Cleaning $MODULE" >> $LOG
	emerge -cp ${MODULE} 2>&1 | tee -a $LOG
	emerge -c ${MODULE}
done

echo 'Rechecking what perl modules you have installed...'
echo 'Rechecking what perl modules you have installed...' >> $LOG


SECOND_MODULE_LIST=`
	for i in $(ls -1| sort -u)
	do
	   echo "dev-perl/${i}"
	done | sed 's/-[0-9].*//g' | sort -u`



x=0
while [ $x -lt 3 ] ; do
let "x++"
for MODULE in $SECOND_MODULE_LIST;
  do
	env-update
	echo "Rebuilding: $MODULE, pass ${x}"
	echo "Rebuilding: $MODULE, pass ${x}" >> $LOG
	if ! emerge "$MODULE"; then
		echo "emerge $MODULE FAILED while in rebuild, pass ${x}."
		echo "emerge $MODULE FAILED while in rebuild, pass ${x}." >> $LOG
	
	else
		echo "Done with $MODULE, pass ${x}"
		echo "Done with $MODULE, pass ${x}" >> $LOG
		

	fi
  done

done

echo 'Preliminary Module Rebuild Complete. Now for rebuilding the rest...'
echo 'Preliminary Module Rebuild Complete. Now for rebuilding the rest...' >> $LOG

#This time around, we want the explicit package name, since in the group remerge, we use
# a --oneshot =package syntax
MODULE_LIST=`
	for i in $(ls -1| sort -u)
	do
	   echo "dev-perl/${i}"
	done | sort -u`


echo 'Finding broken packages...'
echo 'Finding broken packages...' >> $LOG
unset USE
REBUILD_FAKED=""

env-update

# Note: `` == $()
# REBUILD EXACTLY AS ON DISK. emerge =cat/package-version-rev
LDD_LIST=`
for i in $(find $(egrep -v ^# /etc/ld.so.conf) -type f -name '*.so*') \
		$(find $(echo $PATH | sed 's/:/ /g') -type f -perm +0111);
do
  ldd ${i} 2>&1 | grep "libperl" - >/dev/null && qpkg -f -nc  -v $i;
done | sort -u`
ORIGINAL_LIST="$LDD_LIST"

if [ ! -z "$LDD_LIST" ]; then
	REBUILD_PRELIST=`
			echo $LDD_LIST | sed 's:\([^ ]\+\):=\1:g' | xargs emerge -p |
			grep ebuild | sed 's:.*\] \([^ ]*\) .*:\1:'`
fi

# The following is to grab any packages that have placed files in
# /usr/lib/perl* - this may include packages that are not explicityly
# perl modules in dev-perl, or that did not compile against our old 
# libperl - this is a sanity check among other things

cd /var/db/pkg
LIBS_LIST=`grep -ls "usr\/lib\/perl" */*/CONTENTS | sed 's|/CONTENTS||g'  | grep -v "dev-lang/perl" | grep -v "dev-perl"`

REBUILD_LIST=`echo ${LIBS_LIST} ${REBUILD_PRELIST} | sort -u`

if echo $REBUILD_LIST | egrep -q "no.*ebuilds to satisfy"; then
  echo "Packages are installed that no longer exist in Gentoo."
  echo "Determine what you need to do to fix this and try again."
	echo "The package may have been moved to a different category."
	echo
	echo "Easiest course of action: unmerge these by explicit versions"
	echo "and re-emerge them if they still exist."
	echo 'emerge -C \=package-version'
	echo "Notice: $REBUILD_LIST"
  exit 1
fi

if echo $REBUILD_LIST | grep -q "have been masked"; then
  echo "Masked packages are installed and need to be rebuilt..."
  echo "Either unmask them, or emerge -C them all."
	echo
	echo "Easiest course of action: unmerge these by explicit versions"
	echo 'emerge -C \=package-version'
	echo "Notice: $REBUILD_LIST"
  exit 1
fi

echo "Preliminary List: $REBUILD_LIST"
echo "Preliminary List: $REBUILD_LIST" >> $LOG

sleep 10s

if ! emerge -p $(echo "$REBUILD_LIST" | sed 's:\([^ ]\+\):=\1:g') &>/dev/null;   #'
then
	# System isn't up to date, or nothing here to do...
	if [ ! -z "$LDD_LIST" ]; then
		REBUILD_LIST=`
			echo $LDD_LIST | sed 's:\([^ ]\+\):>=\1:g' | xargs emerge -p |
			grep ebuild | sed 's:.*\] \([^ ]\+\) .*:\1:'`
	fi
fi




echo -e "Rebuild list:\n$REBUILD_LIST"
echo -e "Rebuild list:\n$REBUILD_LIST" >> $LOG

sleep 20s

if echo $REBUILD_LIST | egrep -q "no.*ebuilds to satisfy"; then
  echo "Packages are installed that no longer exist in Gentoo."
  echo "Determine what you need to do to fix this and try again."
	echo "The package may have been moved to a different category."
	echo
	echo "Easiest course of action: unmerge these by explicit versions"
	echo "and re-emerge them if they still exist."
	echo 'emerge -C \=package-version'
	echo "Notice: $REBUILD_LIST"
  exit 1
fi

if echo $REBUILD_LIST | grep -q "have been masked"; then
  echo "Masked packages are installed and need to be rebuilt..."
  echo "Either unmask them, or emerge -C them all."
	echo
	echo "Easiest course of action: check your ACCEPT_KEYWORDS in make.conf"
	echo 'emerge -C \=package-version'
	echo "Notice: $REBUILD_LIST"
  exit 1
fi

# I'm commenting out the next block. I don't think that this is necessary for the
# perl upgrade the same way it was for the gcc upgrade - MPC
#echo "Backing up the world file."
#cp /var/cache/edb/world /var/cache/edb/world.update_system_backup
#
#
#echo "Unmerging broken packages..."
#emerge -Cp $ORIGINAL_LIST | tee -a $LOG
#if ! emerge -C $ORIGINAL_LIST; then
#	echo
#	echo "There was a problem unmerging the broken packages."
#	echo "Please pass on your log file to a Gentoo Dev via bugzilla."
#	echo "Log file: $LOG"
#	echo
#	exit 1
#fi
#
#env-update
#
#echo "Restoring world file..."
#mv /var/cache/edb/world.update_system_backup /var/cache/edb/world

REBUILD_LIST=`
	echo $LDD_LIST | sed 's:\([^ ]\+\):\\>\\=\1:g' | xargs emerge -np $(cat /var/cache/edb/world) |
	grep ebuild | sed 's:.*\] \([^ ]\+\) .*:\1:'`

if echo $REBUILD_LIST | egrep -q "no.*ebuilds to satisfy"; then
  echo "Packages are installed that no longer exist in Gentoo."
  echo "Determine what you need to do to fix this and try again."
	echo "The package may have been moved to a different category."
	echo
	echo "Easiest course of action: unmerge these by explicit versions"
	echo "and re-emerge them if they still exist."
	echo 'emerge -C \=package-version'
	echo "Notice: $REBUILD_LIST"
  exit 1
fi

if echo $REBUILD_LIST | grep -q "have been masked"; then
  echo "Masked packages are installed and need to be rebuilt..."
  echo "Either unmask them, or emerge -C them all."
	echo
	echo "Easiest course of action: check your ACCEPT_KEYWORDS in make.conf"
	echo 'emerge -C \=package-version'
	echo "Notice: $REBUILD_LIST"
  exit 1
fi

#Join the perl module list and the binary list, sorting out dups
FULL_LIST=`echo ${REBUILD_LIST} ${MODULE_LIST} | sort -u`

echo -e "Complete rebuild list:\n$FULL_LIST"
echo -e "Complete rebuild list:\n$FULL_LIST" >> $LOG


CLEAN_FAILED=""
MERGE_FAILED=""
MERGE_DONE=""

for PACKAGE in $FULL_LIST;
do
	env-update
	echo "Rebuilding: $PACKAGE"
	echo "Rebuilding: $PACKAGE" >> $LOG
	if ! emerge --oneshot "=$PACKAGE"; then
		echo "emerge $PACKAGE FAILED while in rebuild."
		echo "emerge $PACKAGE FAILED while in rebuild." >> $LOG
		MERGE_FAILED="$MERGE_FAILED \n$PACKAGE"
	else
		echo "Cleaning after $PACKAGE"
		echo "Cleaning after $PACKAGE" >> $LOG
		emerge -cp 2>&1 | tee -a $LOG
		if ! emerge -c; then
			echo "FAILED cleaning after $PACKAGE while in rebuild"
			echo "FAILED cleaning after $PACKAGE while in rebuild" >> $LOG
			CLEAN_FAILED="$CLEAN_FAILED \n$PACKAGE"
		else
			echo "Done with $PACKAGE"
			echo "Done with $PACKAGE" >> $LOG
			MERGE_DONE="$MERGE_DONE \n$PACKAGE"
		fi
	fi
done

# One last pass of the modules - this is to catch those modules that dep'd a binary from above

for MODULE in $MODULE_LIST; 
  do 
        env-update 
        echo "Rebuilding: $MODULE" 
        echo "Rebuilding: $MODULE" >> $LOG 
        if ! emerge --oneshot "=$MODULE"; then 
                echo "emerge $MODULE FAILED while in final rebuild." 
                echo "emerge $MODULE FAILED while in final rebuild." >> $LOG 
         
        else 
                echo "Done with $MODULE" 
                echo "Done with $MODULE" >> $LOG 
                 
 
        fi 
  done 
 



echo
echo "Ok... We're done (really)..."
echo -e "The following packages merged successfully:$MERGE_DONE" 
echo -e "The following packages merged successfully:$MERGE_DONE" >> $LOG
echo "-------------------------------------------"
echo

if [ ! -z "$MERGE_FAILED" ]; then
	echo -e "Merging failed on the following packages: $MERGE_FAILED"
	echo -e "Merging failed on the following packages: $MERGE_FAILED" >> $LOG
	echo "-----------------------------------------"
else
	echo "All packages merged successfully."
	echo "All packages merged successfully." >> $LOG
fi

if [ ! -z "$CLEAN_FAILED" ]; then
	echo -e "Weird: the following packages failed to clean:$CLEAN_FAILED"
	echo -e "Weird: the following packages failed to clean:$CLEAN_FAILED" >> $LOG
	echo "----------------------------------------------------------"
else
	echo "All packages cleaned successfully."
	echo "All packages cleaned successfully." >> $LOG
fi

if [ -z "$MERGE_FAILED" ] && [ -z "$CLEAN_FAILED" ]; then
	echo -e "\n\nEverything Completed Successfully."
	echo -e "Have a nice day and thank you for flying with Gentoo."
	echo -e "\n\nEverything Completed Successfully." >> $LOG
	echo -e "Have a nice day and thank you for flying with Gentoo. :)" >> $LOG
else
	echo -e "\n\nThere were some issues... Check the log for details. :("
	echo "Some or all of the failed packages may have been cause by a"
	echo "dependancy failing earlier. Don't assume EVERYTHING is broken."
	echo "Start with the first one to fail."
	echo "Log is: $LOG"
fi

