diff options
author | Ali Polatel <hawking@gentoo.org> | 2008-06-20 17:46:02 +0000 |
---|---|---|
committer | Ali Polatel <hawking@gentoo.org> | 2008-06-20 17:46:02 +0000 |
commit | ce0e380e3a91d437277fdd03336eeb56a6e73491 (patch) | |
tree | a9150ceaea946577817fddb1547e5e2efc33a23c | |
parent | Added ChangeLog (diff) | |
download | python-updater-ce0e380e3a91d437277fdd03336eeb56a6e73491.tar.gz python-updater-ce0e380e3a91d437277fdd03336eeb56a6e73491.tar.bz2 python-updater-ce0e380e3a91d437277fdd03336eeb56a6e73491.zip |
Splitted checks. Respect PYUPDATER_OPTIONS. Bashified tests. Added man page.
-rw-r--r-- | ChangeLog | 26 | ||||
-rw-r--r-- | Makefile | 25 | ||||
-rw-r--r-- | man.include | 60 | ||||
-rwxr-xr-x | python-updater | 340 |
4 files changed, 355 insertions, 96 deletions
@@ -3,32 +3,40 @@ ChangeLog for python-updater This file lists all changes except typo and formatting fixes. -2008-01-04 Ali Polatel <hawking@gentoo.org> +2008-06-20 Ali Polatel - * ChangeLog: Added ChangeLog + * python-updater, +man.include, +Makefile: Splitted checks and added + command line options for them. Added new tests eclass and soname. + Respect PYUPDATER_OPTIONS environment variable for default command + line options. Bashified tests. Added man page and Makefile to do + common tasks. Fixed ChangeLog. -2008-01-04 Ali Polatel <hawking@gentoo.org> +2008-01-04 Ali Polatel - * AUTHORS: Added AUTHORS + * +ChangeLog: Added ChangeLog -2007-12-13 Ali Polatel <hawking@gentoo.org> +2008-01-04 Ali Polatel + + * +AUTHORS: Added AUTHORS + +2007-12-13 Ali Polatel * python-updater: Don't ignore versions when SLOT doesn't exist, bug 201848 -2007-11-04 Ali Polatel <hawking@gentoo.org> +2007-11-04 Ali Polatel * python-updater: be more specific when searching for package name -2007-10-29 Ali Polatel <hawking@gentoo.org> +2007-10-29 Ali Polatel * python-updater: added dev-libs/boost to PKGS_MANUAL -2007-10-29 Ali Polatel <hawking@gentoo.org> +2007-10-29 Ali Polatel * python-updater: imported python-updater from gentoo-python -2007-10-29 Ali Polatel <hawking@gentoo.org> +2007-10-29 Ali Polatel * .: added projects/python-updater diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..885ae36 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +# Makefile for python-updater +MAN_INCLUDE=man.include +VERSION=$(shell ./python-updater -V) +FILES=AUTHORS ChangeLog python-updater python-updater.1 +PKGDIR=python-updater-$(VERSION) +TARBALL=$(PKGDIR)-tar.bz2 + +all: python-updater.1 tarball + +python-updater.1: python-updater $(MAN_INCLUDE) + help2man -L en_GB.UTF-8 -Ni $(MAN_INCLUDE) ./python-updater -o $@ + sed -i -e 's/ in the manpage//' $@ + +.PHONY: all clean tarball upload +clean: + rm -fr python-updater.1 *.bz2 $(PKGDIR) || true +tarball: + mkdir $(PKGDIR) + cp $(FILES) $(PKGDIR) + tar cjf $(TARBALL) $(PKGDIR) + rm -fr $(PKGDIR) +upload: + scp $(TARBALL) dev.gentoo.org:/space/distfiles-local + ssh dev.gentoo.org chmod ug+rw dev.gentoo.org:/space/distfiles-local/$(TARBALL) + diff --git a/man.include b/man.include new file mode 100644 index 0000000..33d52c7 --- /dev/null +++ b/man.include @@ -0,0 +1,60 @@ +[CHECKS] +pylibdir + Find packages that installed files under old python library dir, + /usr/lib/python$old/site-packages where $old is old python version + Enabled by default. + +soname + Find packages that have files linked to old libpython (requires pax-utils) + Enabled by default. + +eclass + Find packages that inherited python.eclass and set PYVER to old + python version. The packages found by this check may not be + broken. + Disabled by default. + +manual + python-updater has a list of packages that are known to break + by python upgrades but can't be determined by methods specified + above. This check can be disabled if you're sure you've rebuilt + the package once and it's OK now. + Enabled by default. + +Checks can be enabled/disabled on command line with -e/--enable and -d/--disable +switches. + +See EXAMPLES for a list examples. + +See ENVIRONMENT on how to set default options to override +[COPYRIGHT] +Copyright (c) 2007-2008 Gentoo Foundation +Distributed under the terms of the GNU General Public License v2 +[REPORTING BUGS] +Submit bug reports to https://bugs.gentoo.org/ +[AUTHORS] +Bryan Ăstergaard "kloeri" <bryan.ostergaard@gmail.com> + Wrote main code + +Ali Polatel "hawking" <hawking@gentoo.org> + Current maintainer +[EXAMPLES] + +* Rebuild packages after a python upgrade. Default options are just fine ;) + + $> python-updater + +* Rebuild packages omitting manually added ones: + + $> python-updater -dmanual + $> python-updater -disable-manual + +* You can use unique substrings instead of names for checks: + + $> python-updater -dm -ep + $> python-updater --disable-m --enable-pylib + +[ENVIRONMENT] + +PYUPDATER_OPTIONS + Default command line options diff --git a/python-updater b/python-updater index 1c9d247..4fd5559 100755 --- a/python-updater +++ b/python-updater @@ -1,5 +1,8 @@ #!/bin/bash -# vim: set et sw=4 sts=4 : +# vim: set et sw=4 sts=4 tw=80: +# Copyright 2007-2008 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + # A bit of hackery to update everything that is humanly possible # that maybe related to an older version of python. This script can # be run as many times as you like. @@ -20,19 +23,15 @@ # PKGS_MASKED = list of packages that are installed, but masked. # +VERSION="0.5" NEW_PY_VER=$(python -V 2>&1 | sed 's:Python ::' | cut -d. -f1-2) PKGS_EXCEPTIONS="dev-lang/python sys-apps/portage" PKGS_MANUAL="app-office/gnumeric app-office/dia dev-libs/boost x11-libs/vte" -# portage variables -PKG_DBDIR=/var/db/pkg -PORTDIR=`portageq portdir` -PORTDIR_OVERLAYS=`portageq portdir_overlay` - PRETEND=0 -DIRECT_ONLY=0 IGNORE_VERSIONS=0 +VERBOSE=0 PKGS_TO_REMERGE="" PKGS_COUNT_REMERGE=0 PORTAGE_PYTHON="/usr/bin/python" @@ -41,51 +40,146 @@ SUPPORTED_PMS="portage pkgcore paludis" PMS_COMMAND=( "emerge" "pmerge" "paludis" ) PMS_OPTIONS=( "-vD1" "-Do" "-i1" ) +# Checks +CHECK_ECLASS=0 +CHECK_MANUAL=1 +CHECK_PYLIBDIR=1 +CHECK_SONAME=1 + # load the gentoo-style info macros, but hack to get around # it thinking this is an rc script EBUILD="1" source /etc/init.d/functions.sh +# portage variables +PKG_DBDIR=/var/db/pkg + +# usage() +# display usage usage() { - echo "usage: python-updater [-h|-p|-o X.X]" - echo " --help, -h help" - echo " --pretend, -p pretend (don't do anything)" - echo " --old-version, -o X.X set old python version to upgrade from [default: ${OLD_PY_VER}]" - echo " --ignore-versions, -i ignore versions when remerging packages (still respects SLOTs)" - echo " --direct-only don't consider indirect aka manually added packages" - echo " --package-manager, -P name select between ${SUPPORTED_PMS} [default: portage]" + cat <<EOF_USAGE +${0##*/} -- Find & rebuild packages broken due to a python upgrade + +Usage: python-updater [OPTION] + +Options: + -h, --help Print usage + -V, --version Print version + -p, --pretend Pretend (don't do anything) + -v, --verbose Increase verbosity (may be specified multiple times) + -o PYVER, --old-version PYVER + Set old python version to upgrade from to PYVER + -i, --ignore-versions + Ignore versions when remerging packages + (still respects SLOTs) + -P PM, --package-manager PM + Select between ${SUPPORTED_PMS} [default: portage] + -c CMD, --command CMD + Pipe found packages to command CMD instead of invoking package + manager. Only for debug and script use. + -eCHECK --enable-CHECK + Enable CHECK + -dCHECK --disable-CHECK + Disable CHECK + +See CHECKS section in the manpage for a list of checks and EXAMPLES section to +learn how to use them. +EOF_USAGE } -# -# Sanity check -# +# veinfo(verbosity, message) +# einfo message if VERBOSE is bigger than verbosity +veinfo() { + if [[ VERBOSE > $1 ]]; then + shift + einfo $@ + fi +} -if [ -z "${PORTDIR}" ]; then - eerror "Unable to proceed. Can not find PORTDIR. Make sure the command:" - eerror " " - eerror " portageq portdir" - eerror " " - eerror "returns a value. If it doesn't, make sure you have updated to" - eerror "latest portage version." - eerror " " - eerror "Report bugs to http://bugs.gentoo.org/" - exit 1 -fi +# get_old_pyver() +# Find old python version, return non-zero if not found +get_old_pyver() { + for old in 2.5 2.4 2.3 2.2 2.1; do + if [[ "${old}" != "${NEW_PY_VER}" ]]; then + if [[ -e /usr/bin/python${old} ]]; then + echo -n "${old}" + return 0 + fi + fi + done + eerror "Couldn't determine any previous Python version(s)." + return 1 +} + +# get_portage_python(oldpy=2.4,newpy=2.5) +# Find where portage is, in python2.2 or somewhere else? +get_portage_python() { + local oldpy newpy + if [[ ! -z "$1" ]]; then + oldpy="$1" + else + oldpy=2.4 + fi + + if [ ! -z "$2" ]; then + newpy="$2" + else + newpy=2.5 + fi + + pybin=/usr/bin/python + for py in ${pybin} ${pybin}${oldpy} ${pybin}${newpy}; do + if ${py} -c "import portage" > /dev/null 2>&1; then + echo -n "${py}" + return 0 + fi + done + eerror "Could't determine portage python" + return 1 +} + +# get_portage_portdir() +# Check if portage knows about PORTDIR and return it +get_portage_portdir() { + local portdir="$(/usr/bin/portageq portdir)" + + if [[ -z "${portdir}" ]]; then + eerror "Unable to proceed. Can not find PORTDIR. Make sure the command:" + eerror " " + eerror " portageq portdir" + eerror "returns a value. If it doesn't, make sure you have updated to" + eerror "latest portage version." + eerror " " + eerror "Report bugs to http://bugs.gentoo.org/" + return 1 + else + echo -n "${portdir}" + return 0 + fi +} + +# Respect PYUPDATER_OPTIONS +if [[ -n "${PYUPDATER_OPTIONS}" ]]; then + set -- ${PYUPDATER_OPTIONS} $@ +fi -# -# # Command Line Parsing -# -# -while [ -n "$1" ]; do +while [[ -n "$1" ]]; do case "$1" in -h|--help) usage exit 0 ;; + -V|--version) + echo "${VERSION}" + exit 0 + ;; -p|--pretend) PRETEND=1 ;; + -v|--verbose) + VERBOSE=$(( $VERBOSE + 1 )) + ;; -o|--old-version) shift OLD_PY_VER="$1" @@ -93,9 +187,6 @@ while [ -n "$1" ]; do -i|--ignore-versions) IGNORE_VERSIONS=1 ;; - --direct-only) - DIRECT_ONLY=1 - ;; -P|--package-manager) shift PACKAGE_MANAGER="$1" @@ -107,7 +198,7 @@ while [ -n "$1" ]; do exit ;; esac - + # PMS_INDEX is used to select the right commands and options for the selected package manager PMS_INDEX=0 for PM in ${SUPPORTED_PMS}; do @@ -115,7 +206,35 @@ while [ -n "$1" ]; do PMS_INDEX=$((${PMS_INDEX} + 1)) done ;; - *) + -c|--command) + shift + PIPE_COMMAND="$1" + ;; + -ee*|--enable-e*) + CHECK_ECLASS=1 + ;; + -de*|--disable-e*) + CHECK_ECLASS=0 + ;; + -em*|--enable-m*) + CHECK_MANUAL=1 + ;; + -dm*|--disable-m*) + CHECK_MANUAL=0 + ;; + -ep*|--enable-p*) + CHECK_PYLIBDIR=1 + ;; + -dp*|--disable-p*) + CHECK_PYLIBDIR=0 + ;; + -es*|--enable-s*) + CHECK_SONAME=1 + ;; + -ds*|--disable-s*) + CHECK_SONAME=0 + ;; + *) usage echo "unrecognised option: $1" exit 0 @@ -124,67 +243,72 @@ while [ -n "$1" ]; do shift done +# Sanity check +PORTDIR="$(get_portage_portdir)" +[[ $? != 0 ]] && exit 1 + # Determine old python version if [[ -z "${OLD_PY_VER}" ]]; then - for old in 2.5 2.4 2.3 2.2 2.1; do - if [ "${old}" != "${NEW_PY_VER}" ]; then - if [ -e /usr/bin/python${old} ] ; then - OLD_PY_VER=${old} - break; - fi - fi - done -fi - - -if [ -z "${OLD_PY_VER}" ] ; then - eerror "Can't determine any previous Python version(s)." - exit 1 + OLD_PY_VER="$(get_old_pyver)" + if [[ $? -ne 0 ]]; then + exit 1 + fi fi -# -# Test where portage is, in python2.2 or somewhere else? -# -for py in /usr/bin/python /usr/bin/python${OLD_PY_VER} /usr/bin/python${NEW_PY_VER}; do - if ${py} -c "import portage" > /dev/null 2>&1; then - PORTAGE_PYTHON=${py} - break; - fi -done +# Get portage python +PORTAGE_PYTHON="$(get_portage_python ${OLD_PY_VER} ${NEW_PY_VER})" +[[ $? != 0 ]] && exit 1 -# -# -# Find all packages that have installed something in -# /usr/lib/python${OLD_PY_VER} -# -# -OLD_MODULES_DIRS="/usr/lib/python${OLD_PY_VER} /usr/lib32/python${OLD_PY_VER} /usr/lib64/python${OLD_PY_VER}" -OLD_INCLUDE_DIR=/usr/include/python${OLD_PY_VER} einfo "Starting Python Updater from ${OLD_PY_VER} to ${NEW_PY_VER} :" -einfo "Searching for packages with files in ${OLD_MODULES_DIRS} .." +if [[ CHECK_SONAME -ne 0 ]]; then + if ! type -P scanelf >/dev/null 2>&1; then + ewarn "scanelf not found!" + ewarn "check soname is disabled." + CHECK_SONAME=0 + else + veinfo 1 'check "soname" enabled.' + OLD_SONAME="$(readlink -n /usr/lib/libpython${OLD_PY_VER}.so)" + if [[ -z "${OLD_SONAME}" ]]; then + ewarn "Couldn't find old libpython soname" + ewarn "Disabling soname check." + CHECK_SONAME=0 + fi + fi +else + veinfo 1 'check "soname" disabled.' +fi +[[ CHECK_PYLIBDIR -ne 0 ]] \ + && veinfo 1 'check "pylibdir" enabled.' \ + || veinfo 1 'check "pylibdir" disabled.' +[[ CHECK_ECLASS -ne 0 ]] \ + && veinfo 1 'check "eclass" enabled.' \ + || veinfo 1 'check "eclass" disabled.' +[[ CHECK_MANUAL -ne 0 ]] \ + && veinfo 1 'check "manual" enabled.' \ + || veinfo 1 'check "manual" disabled.' # iterate thru all the installed package's contents for content in `find ${PKG_DBDIR} -name CONTENTS`; do # extract the category, package name and package version CATPKGVER=$(echo ${content} | sed "s:${PKG_DBDIR}/\(.*\)/CONTENTS:\1:") CATPKG="${CATPKGVER%%-[0-9]*}" + veinfo 2 "Checking ${CATPKGVER}" # exclude packages that are an exception, like portage and python itself. exception=0 for exp in ${PKGS_EXCEPTIONS}; do - if [ -z "${CATPKG##${exp}}" ]; then + if [[ -z "${CATPKG##${exp}}" ]]; then + veinfo 2 "Skipping ${CATPKG}, reason: exception" exception=1 break; fi done - - if [ ${exception} = 1 ]; then - continue; - fi - + + [[ ${exception} == 1 ]] && continue + # Check if package is in PKGS_MANUAL - if [[ DIRECT_ONLY -ne 1 ]]; then + if [[ CHECK_MANUAL -ne 0 ]]; then for pkg in ${PKGS_MANUAL}; do if [ -z "${CATPKG##${pkg}}" ]; then exception=2 @@ -192,7 +316,7 @@ for content in `find ${PKG_DBDIR} -name CONTENTS`; do fi done fi - + # replace version number by SLOT if IGNORE_VERSIONS != 0 # Don't ignore versions when SLOT doesn't exist, bug 201848 if [[ IGNORE_VERSIONS -ne 0 && -f "${content/CONTENTS/SLOT}" ]]; then @@ -201,23 +325,65 @@ for content in `find ${PKG_DBDIR} -name CONTENTS`; do else CATPKGVER="=${CATPKGVER}" fi - - if [ ${exception} = 2 ]; then + + if [[ ${exception} = 2 ]]; then PKGS_TO_REMERGE="${PKGS_TO_REMERGE} ${CATPKGVER}" - einfo "Adding to list (manually): ${CATPKGVER}" - continue; + eindent + einfo "Adding to list: ${CATPKGVER}" + veinfo 1 "check: manual [Added to list manually]" + eoutdent + continue fi - - for OLD_MODULES_DIR in ${OLD_MODULES_DIRS}; do - if fgrep "${OLD_MODULES_DIR}" ${content} > /dev/null; then + + if [[ CHECK_PYLIBDIR -ne 0 ]]; then + # Search for possible old python dirs in CONTENTS + # /usr/include/python$old + # /usr/lib/python$old + # /usr/lib32/python$old + # /usr/lib64/python$old + if grep -qe "/usr/\(include\|lib\(32\|64\)\?\)/python${OLD_PY_VER}" ${content}; then PKGS_TO_REMERGE="${PKGS_TO_REMERGE} ${CATPKGVER}" + eindent einfo "Adding to list: ${CATPKGVER}" - elif fgrep "${OLD_INCLUDE_DIR}" ${content} > /dev/null; then + veinfo 1 "check: pylibdir [ Installed file under old python library directory ]" + eoutdent + continue + fi + fi + + if [[ CHECK_SONAME -ne 0 ]]; then + broken_libs="$(scanelf -qBN ${OLD_SONAME} < <( + grep -e '^obj' ${content} | cut -d' ' -f2))" + if [[ -n "${broken_libs}" ]]; then PKGS_TO_REMERGE="${PKGS_TO_REMERGE} ${CATPKGVER}" + eindent + einfo "Adding to list: ${CATPKGVER}" + veinfo 1 "check: soname [ Libraries linked to old libpython found:" + veinfo 1 "${broken_libs}" + veinfo 1 "]" + eoutdent fi - done + fi + + if [[ CHECK_ECLASS -ne 0 ]]; then + ENVIRON="${content/CONTENTS/environment.bz2}" + if bzip2 -dc ${ENVIRON} | grep -qe "^\(export \)\?PYVER=${OLD_PY_VER}"; then + PKGS_TO_REMERGE="${PKGS_TO_REMERGE} ${CATPKGVER}" + eindent + einfo "Adding to list: ${CATPKGVER}" + veinfo 1 "check: environ [ Ebuild set PYVER=${OLD_PY_VER} ]" + eoutdent + continue + fi + fi done +# Pipe to command if we have one +if [[ -n "${PIPE_COMMAND}" ]]; then + echo "${PKGS_TO_REMERGE}" | ${PIPE_COMMAND} + exit $? +fi + # only pretending? [[ PRETEND -eq 1 ]] && PMS_OPTIONS[${PMS_INDEX}]="${PMS_OPTIONS[${PMS_INDEX}]}p" |