#!/bin/bash # ############################################################################### # # portage-upgrade: Generate list of merged packages for which more recent # versions exist, even if they do not exist in the world # profile. # # This script is a development of the upgrade-all and upgrade-stable scripts # by the same author. Hopefully, these will take less time to run that the # subsequent merging of the new packages, unlike the previous effort :) # # Stuart Shelton, 20040207. ############################################################################### # # set -o xtrace NAME="$( basename ${0} )" EMERGE="/usr/bin/emerge" EMERGEOPTS="--columns --nospinner -p" PORTAGEQ="/usr/bin/portageq" SLOW="-O" # Use equery - broken in the current version of Portage... # EQUERY="$( type -p equery )" # EOPTS="-q -C list -i \*" # # Use qpkg - leaves temporary files lying around filesystem... # EQUERY="$( type -p qpkg )" # EOPTS="-I -v -nc" # # Use epm - emulates rpm, but has the advantage of actually working... EQUERY="$( type -p epm )" EOPTS="-qGa" function die() { [ -e $TMPFILE ] && rm -f $TMPFILE exit ${1:-1} } function warn() { echo "$@" >&2 } function error() { warn "$@" die 1 } function verbose() { if [ -n "$VERBOSE" ]; then echo -e "$@" >&2 fi } function showHelp() { echo "${NAME:-portage-upgrade}: Output list of non-current merged packages" echo "Options: --help -h Display this help text" echo " --verbose -v Display package information" echo " --keyword[=] -k[=] Use this value for \$ACCEPT_KEYWORDS" echo " --slow Check full dependancy tree for each package" } function checkKeyword() { [ -r /etc/make.conf ] && eval "$( grep "PORTDIR=" /etc/make.conf )" if [ -r ${PORTDIR:-/usr/portage}/profiles/arch.list ]; then BASEARCH="$( echo $1 | sed 's/~//' )" [ -z "$BASEARCH" ] && error "Internal Error: No keyword supplied" if [ -n "$( grep $BASEARCH ${PORTDIR:-/usr/portage}/profiles/arch.list )" ]; then ACCEPT_KEYWORDS=$1 else error "\"$1\" is not a supported architecture" fi else warn "Cannot read arch.list - Accepting supplied value" ACCEPT_KEYWORDS=$1 fi } trap die 1 2 3 PORTAGEDB="/var/db/pkg" unset VERBOSE [ -z "$( groups | grep "portage" )" -a "$UID" != "0" ] && error "Fatal Error: You must be in the Portage group" [ -z "$( type -p $EQUERY )" ] && error "$( basename $EQUERY ) missing - Please merge relevant package" [ -z "$( type -p $PORTAGEQ )" ] && error "portageq missing - Please merge sys-apps/portage" [ -d /dev/shm -a -w /dev/shm ] && TMP="/dev/shm" TMPFILE="${TMP:-/tmp}/$NAME.tmp" touch $TMPFILE [ -w $TMPFILE ] || error "Cannot write to temporary file $TMPFILE" # Parse command-line arguments CLINE=$( getopt -o hvk: --long help,verbose,keyword:,slow -n $NAME -- "$@" ) eval set -- "$CLINE" while true; do case "$1" in -h|--help) showHelp die 0 ;; -v|--verbose) VERBOSE=1 shift ;; -k|--keyword) checkKeyword "$2" shift 2 ;; --slow) echo "Full dependancy checking enabled - this will take a LONG time..." SLOW="-D" shift ;; --) shift ;; *) if [ -n "$1" ]; then checkKeyword "$1" shift else break fi ;; esac done # We'll honor the ACCEPT_KEYWORDS variable, make.conf, and the command-line if [ -z "$ACCEPT_KEYWORDS" ]; then if [ -r /etc/make.conf ]; then grep "ACCEPT_KEYWORDS" /etc/make.conf > $TMPFILE source $TMPFILE fi fi if [ -z "$ACCEPT_KEYWORDS" ]; then warn "Cannot determine architecture to evaluate - assuming \"~x86\"..." ACCEPT_KEYWORDS="~x86" fi echo -n "Building package list for $ACCEPT_KEYWORDS ebuilds... " >&2 if [ "$ACCEPT_KEYWORDS" != "x86" ]; then if [ -n "$USE" ]; then CMD="ACCEPT_KEYWORDS=\"$ACCEPT_KEYWORDS\" USE=\"$USE\" emerge -pv" else CMD="ACCEPT_KEYWORDS=\"$ACCEPT_KEYWORDS\" emerge -pv" fi else if [ -n "$USE" ]; then CMD="USE=\"$USE\" emerge -pv" else CMD="emerge -pv" fi fi PORTDIR="$( $PORTAGEQ portdir )" PORTDIR="${PORTDIR:-/usr/portage}" [ -d "$PORTDIR" ] || error "Cannot determine \$PORTDIR location" OVERLAY="$( $PORTAGEQ portdir_overlay )" DBPATH="$( $PORTAGEQ vdb_path )" cat /dev/null > $TMPFILE MESSAGE="" # $EQUERY $EOPTS | sed 's/^\[.*\] \[.*\] //' | cut -d" " -f 1 | \ find $DBPATH -type f -name \*.ebuild | xargs grep -H "^KEYWORDS.*[\"= ]${ACCEPT_KEYWORDS}" | \ cut -d: -f1 | cut -d"/" -f5,6 | sort | uniq | \ while read LINE; do [ -z "$MESSAGE" ] && { echo "Done" ; MESSAGE="DONE" ; } DIR="$( echo $LINE | cut -d "/" -f 1 )" EBUILD="$( echo $LINE | cut -d " " -f 1 | cut -d "/" -f 2 )" PACKAGE="$( echo $LINE | sed "s|^.*/|| ; s|-[0-9].*||" )" unset FILE if [ -r "$PORTDIR/$DIR/$PACKAGE/$EBUILD.ebuild" ]; then FILE="$PORTDIR/$DIR/$PACKAGE/$EBUILD.ebuild" verbose "Checking $DIR/$PACKAGE" elif [ -n "$OVERLAY" -a -r "$OVERLAY/$DIR/$PACKAGE/$EBUILD.ebuild" ]; then FILE="$OVERLAY/$DIR/$PACKAGE/$EBUILD.ebuild" verbose "Checking $DIR/$PACKAGE in $OVERLAY" else warn "No package exists for \"$EBUILD\"" echo "$PACKAGE " >> $TMPFILE fi if [ -n "$FILE" ]; then if [ -n "$( grep "^KEYWORDS" "$FILE" | grep "$ACCEPT_KEYWORDS" )" ]; then OUTPUT="$( ACCEPT_KEYWORDS="$ACCEPT_KEYWORDS" $EMERGE $EMERGEOPTS $SLOW $PACKAGE 2>&1 \ | grep -E "^\[ebuild ....U \]|^\[blocks " )" if [ -n "$OUTPUT" ]; then verbose "$OUTPUT" echo "$OUTPUT" \ | grep -Ev "^\[blocks B" \ | sed "s|\[empty/missing/bad digest\]||" \ | sed "s|^.*/||" \ | tr -s [:space:] | cut -d" " -f1 \ >> $TMPFILE fi fi fi done verbose "" >&2 cat $TMPFILE | sort | uniq > $TMPFILE PKGLIST="" for ITEM in $( cat $TMPFILE ); do PKGLIST="$PKGLIST $ITEM" done PKGLIST="$( echo "$PKGLIST" | sed 's/ +/ /g ; s/^ // ; s/ $//' )" [ -n "$PKGLIST" ] && echo "$CMD $PKGLIST" || echo "No updated packages found" die 0