#!/bin/sh
#
#  NAME
#     pkg_upgrade
#
#  SYNOPSIS
#     pkg_upgrade.sh [-n] [-f] [-p "port list"]
#
#     If the switch -n is specified, the commands necessary to perform the
#     upgrade are not executed.
#
#     -f will cause pkg_upgrade to unconditionally overwrite the save file
#      containing the current list of packages. 
#
#     -p "port list" allows the definition of a list of ports that
#     must be compiled, rather than downloaded as packages.  If more
#     than one port is specified, the list must be whitespace separated
#     and enclosed in quotes.  It will override any script set list
#     of ports.
#
#  DESCRIPTION
#    This script is intended to be run following a FreeBSD OS
#    upgrade.  It will delete all the installed packages, then
#    re-install all leaf packages (i.e. those with no dependencies)
#
#    Where packages cannot be used, due to the need to specify compile-
#    time options, a list of ports may be specified.  An attempt is made
#    to identify these and not download the corresponding package.  
#    Such ports are built using the normal make && make install.
#
#  NOTES
#    This script is best run following a single-user reboot into the
#    new version of the OS.  Then, issue the following commands:
#
#      fsck -p
#      mount -u /
#      mount -t ufs -a
#      swapon -a
#      /etc/rc.d/hostname start
#      /etc/rc.d/netif start
#      /etc/rc.d/routing start
#      csup -g -L 2 /usr/local/etc/cvsup/ports-supfile # update ports tree
#
#   The pkg_update.sh script can then be run.
#
#  MODIFICATION HISTORY
#  Mnemonic    Date     Rel   Who
#  pkg_upgrade 20090129 1.0   mpw
#    Created.
#  pkg_upgrade 20100405 1.1   mpw
#    Issue 'make clean' before building ports
#    If port name and package name are different, try to add both
#

tmp=${TMP:-/tmp}
exec=${tmp}/pu_$$
today=`date +'%y%m%d'`
host=`uname -n`
ports_dir=${PORTS_DIR:-/usr/ports}
backup_file=${tmp}/pkg_upgrade_list_${today}
safe=true
execute=true
script=${0##*/}
ports=""

if [ "$[host}" = "" ]; then
    echo "${script}: no host name set; not proceeding."
    exit 1
fi

# define packages that must be built from ports, for each host supported.
# this section needs to be deleted/modifed for different hosts.
if [ "${host}" = "crimson" ]; then
    ports="emacs ispell samba34 cyrus-sasl2-saslauthd py-libxml2"
elif [ "${host}" = "chrome" ]; then
    ports="emacs ispell samba3 cyrus-sasl2-saslauthd py-libxml2"
elif [ "${host}" = "topaz" ]; then
    ports="samba34 ispell"
fi

# get arguments
while [ $# -gt 0 ]; do
    case $1 in
        "-p" ) ports=$2;shift
            ;;
        "-n" ) execute=false
            ;;
        "-f" ) safe=false
            ;;
        * ) echo "$1: unrecognised switch, quitting..."
            exit 1
            ;;
    esac
    shift
done

# get list of all installed packages
pkgs=`pkg_info -E -x '.*'`

# remember them in case of disaster
if [ -r ${backup_file} ] && ${safe}; then
    echo "${script}: package list backup file already exists; use -f to force overwrite"
    exit 1
else
    echo ${pkgs} >${backup_file}
fi

# ensure exec shell script file is empty
echo "#!/bin/sh" >${exec}

# delete all packages
echo pkg_delete -af >>${exec}

# for each package, identify those that are leaves and pkg_add them
# if a package exists in the list of ports, it will not be pkg_add'ed,
# but built from ports later
for pkg in ${pkgs}
do
    deps=`pkg_info -q -R ${pkg}`
    if [ "${deps}" = "" ]; then
        origin=`pkg_info -q -o ${pkg}`
        basepkg=${origin#*/}
        build=${basepkg}
        for port in ${ports}
        do
          if [ ${port} = ${basepkg} ]; then
              portlist=${origin}" "${portlist}
              build=""
              break;
          fi
        done
        if [ "${build}" = "${basepkg}" ]; then
            if [ "${basepkg}" = "${pkg%-*}" ]; then
                echo "pkg_add -r ${basepkg}" >>${exec} 
           else
                echo "pkg_add -r ${basepkg} || pkg_add -r ${pkg%-*}" >>${exec}
            fi
        fi
    fi
done

# now build from ports
for port in ${portlist}
do
  echo cd ${ports_dir}/${port} >>${exec}
  echo "make clean && make && make install" >>${exec}
done

# the commands necessary for the package upgrade are now in the 
# script ${exec}
if [ -r ${exec} ]; then
    if  ${execute} ; then
        logfile=/tmp/pkg_upgrade_${today}
        echo "${script}: upgrade running... logfile in ${logfile}"
        sh -x ${exec} | tee ${logfile}
    else
        echo "${script}: pkg_upgrade commands are in ${exec}"
    fi
else
    echo "${script}: package upgrade script (${exec}) is unreadable!"
    exit 1
fi
