#!/bin/bash version="1.23" tanpath="/var/lib/pacman" tandb="pacsync.db" errors=0 upgrade=0 INSTALL_ROOT="/" IGNORE_PKG= message() { echo "==> $1" >&2 } usage() { echo "pacsync version $version" echo "usage: $0 [--root ] [--ignore ] [package]" echo "" echo "operations:" echo " sync Download a fresh package list from the server" echo " install Download and install " echo " upgrade Download and upgrade " echo " report Generate a report of all packages that could be upgraded" echo " sysupgrade Same as \"report\", but actually do the upgrades" echo " clean Removes all files from package cache to clear up diskspace" echo "" echo "options:" echo " --root Set installation root to " echo " --ignore Ignore packages that have in their names when doing" echo " sysupgrades. (--ignore can be used multiple times)" echo "" } checkdb() { if [ ! -f $INSTALL_ROOT/$tanpath/$tandb ]; then message "missing package list. (use \"sync\" first)" exit 1 fi } download() { targ=$1 shift cl= for file in $*; do # snarf returns a nonzero error code when the file already exists, which # confuses pacsync, so for now, no resume action... rm -f $file cl="$cl $SYNC_SERVER/$file" done message "Downloading $targ" $ftpagent $cl 2>&1 if [ $? -gt 0 ]; then message "error: could not download $targ" return 1 fi return 0 } dosync() { download "package list" pacsync/$tandb if [ $? -gt 0 ]; then exit 1 fi rm -f $INSTALL_ROOT/$tanpath/$tandb mv $tandb $INSTALL_ROOT/$tanpath/$tandb message "Done." } doinstall() { pkg2dl= pkg2inst= for pkgname in $*; do line=`egrep "^[a-z]+/$pkgname-[a-zA-Z0-9\.]+-[0-9]+\.pkg\.tar\.gz$" $INSTALL_ROOT/$tanpath/$tandb` if [ $? -gt 0 ]; then message "package $pkgname not found" exit 1 fi pacman=`pacman -Q -r $INSTALL_ROOT $pkgname 2>/dev/null` if [ $? -eq 0 ]; then message "$pkgname is already installed (try using \"upgrade\")" exit 1 fi filename=`echo $line | sed 's|^[a-z]*/||g'` pkg2inst="$pkg2inst $filename" if [ ! -f $INSTALL_ROOT/var/cache/pacman/pkg/$filename ]; then pkg2dl="$pkg2dl $filename" fi done # download packages that aren't already cached if [ "$pkg2dl" != "" ]; then download "packages" $pkg2dl if [ $? -gt 0 ]; then exit 1 fi if [ `pwd` != "$INSTALL_ROOT/var/cache/pacman/pkg" ]; then # move downloaded files into cache mkdir -p $INSTALL_ROOT/var/cache/pacman/pkg mv $pkg2dl $INSTALL_ROOT/var/cache/pacman/pkg/ fi fi # install packages message "Installing packages" cd $INSTALL_ROOT/var/cache/pacman/pkg pacman -A -r $INSTALL_ROOT $pkg2inst if [ $? -gt 0 ]; then message "error: some packages failed to install" exit 1 fi message "Done" exit 0 } doupgrade() { pkg2dl= pkg2up= for pkgname in $*; do line=`egrep "^[a-z]+/$pkgname-[a-zA-Z0-9\.]+-[0-9]+\.pkg\.tar\.gz$" $INSTALL_ROOT/$tanpath/$tandb` if [ $? -gt 0 ]; then message "package $pkgname not found" exit 1 fi pacman=`pacman -Q -r $INSTALL_ROOT $pkgname 2>/dev/null` if [ $? -gt 0 ]; then message "$pkgname is not installed (use \"install\" first)" exit 1 fi pkgver=`echo $pacman | awk '{print $2}'` package="$pkgname-$pkgver" filename=`echo $line | sed 's|^[a-z]*/||g'` # compare filename and package. if they are at all different, we # assume that the newer version is on the server and do the upgrade if [ "$filename" = "$package.pkg.tar.gz" ]; then message "$pkgname is already up to date (skipping)" else pkg2up="$pkg2up $filename" if [ ! -f $INSTALL_ROOT/var/cache/pacman/pkg/$filename ]; then pkg2dl="$pkg2dl $filename" fi fi done # download packages that aren't already cached if [ "$pkg2dl" != "" ]; then download "packages" $pkg2dl if [ $? -gt 0 ]; then exit 1 fi if [ `pwd` != "$INSTALL_ROOT/var/cache/pacman/pkg" ]; then # move downloaded files into cache mkdir -p $INSTALL_ROOT/var/cache/pacman/pkg mv $pkg2dl $INSTALL_ROOT/var/cache/pacman/pkg/ fi fi # install packages if [ "$pkg2up" != "" ]; then message "Upgrading packages" cd $INSTALL_ROOT/var/cache/pacman/pkg pacman -U -r $INSTALL_ROOT $pkg2up if [ $? -gt 0 ]; then message "error: some packages failed to upgrade" exit 1 fi message "Done" fi exit 0 } doreport() { headers=0 newkernel=0 pkg2up= for pkgfile in `cat $INSTALL_ROOT/$tanpath/$tandb | sed "s|^[a-z]*/||g"`; do pkgname=`echo $pkgfile | sed 's|-[a-zA-Z0-9\.]*-[0-9]*\.pkg\.tar\.gz||g'` pacman=`pacman -Q -r $INSTALL_ROOT $pkgname 2>/dev/null` if [ $? -gt 0 ]; then # skip this one, it's not installed continue fi pkgver=`echo $pacman | awk '{print $2}'` locfile="$pkgname-$pkgver" remfile=`echo $pkgfile | sed 's|^[a-zA-Z]*/||g' | sed 's|\.pkg\.tar\.gz||g'` # compare locfile and remfile if [ "$locfile" = "$remfile" ]; then # this package is up to date continue else if [ `echo "$locfile" | egrep '^kernel-[a-zA-Z0-9\.]+-[0-9]+$'` ]; then # this is the kernel pacakge -- we handle this one specially newkernel=1 continue fi if [ "$IGNORE_PKG" != "" ]; then if [ `echo "$locfile" | egrep "$IGNORE_PKG"` ]; then # ignore this package as per user's request continue fi fi if [ "$headers" = "0" ]; then echo "+--------------------------------------+--------------------------------------+" echo "| LOCAL | REMOTE |" echo "+--------------------------------------+--------------------------------------+" headers=1 fi echo -n "| $locfile" awk "BEGIN { for (j=length(\"$locfile\"); j<36; j++) printf \" \" }" echo -n " | " awk "BEGIN { for (j=length(\"$remfile\"); j<36; j++) printf \" \" }" echo "$remfile |" pkg2up="$pkg2up $pkgname" fi done if [ "$headers" = "1" ]; then echo "+--------------------------------------+--------------------------------------+" fi if [ "$newkernel" = "1" ]; then echo echo "NOTICE: A new kernel is available for upgrade, but this process will not" echo " upgrade it for you. If you wish to upgrade, you must explicitly" echo " request it by running 'pacsync upgrade kernel'. If you choose to" echo " upgrade, make sure you re-run 'lilo' as well!" echo fi # do we upgrade? if [ "$upgrade" = "1" -a "$pkg2up" != "" ]; then echo "" echo -n "Do you want to upgrade these packages? [Y/n] " read answer echo "" if [ "$answer" = "y" -o "$answer" = "Y" -o "$answer" = "" ]; then doupgrade $pkg2up fi fi exit 0 } cd /tmp if [ $# -lt 1 ]; then usage exit 0 fi if [ "$1" = "--root" ]; then shift INSTALL_ROOT=$1 shift fi while [ "$1" = "--ignore" ]; do shift if [ "$IGNORE_PKG" = "" ]; then IGNORE_PKG="$1" else IGNORE_PKG="$IGNORE_PKG|$1" fi shift done if [ -f /etc/pacsync.conf ]; then . /etc/pacsync.conf else message "error: Missing /etc/pacsync.conf configuration file!" exit 1 fi proto=`echo $SYNC_SERVER | sed 's|://.*||'` # check for a download utility if [ -x /usr/bin/snarf ]; then ftpagent="/usr/bin/snarf" elif [ -x /usr/bin/lftpget -a "$proto" = "ftp" ]; then ftpagent="/usr/bin/lftpget" elif [ -x /usr/bin/wget ]; then ftpagent="/usr/bin/wget --passive-ftp --tries=3 --waitretry=3" else message "error: you need an ftp client installed (snarf/lftp/wget) in /usr/bin" exit 1 fi op=$1 shift if [ "$1" = "-v" ]; then verbose=1 shift fi case $op in sync) dosync ;; install) checkdb if [ "$1" = "" ]; then message "error: no package specified" exit 1 fi doinstall $* ;; upgrade) checkdb if [ "$1" = "" ]; then message "error: no package specified" exit 1 fi doupgrade $* ;; report) checkdb doreport ;; sysupgrade) checkdb upgrade=1 doreport ;; clean) message "Removing packages from cache" rm -f $INSTALL_ROOT/var/cache/pacman/pkg/* ;; *) message "error: invalid operation" exit 1 ;; esac