diff options
-rw-r--r-- | AUTHORS | 7 | ||||
-rw-r--r-- | ChangeLog | 61 | ||||
-rwxr-xr-x | python-updater | 414 | ||||
-rw-r--r-- | python-updater.1 | 111 |
4 files changed, 593 insertions, 0 deletions
@@ -0,0 +1,7 @@ +Authors of python-updater +========================= + +kloeri:Bryan Østergaard <bryan.ostergaard@gmail.com> + Wrote main code. +hawking:Ali Polatel <hawking@gentoo.org> + Current maintainer. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..4b814f9 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,61 @@ +ChangeLog for python-updater +============================ + +This file lists all changes except typo and formatting fixes. + +2008-08-25 Ali Polatel + + * python-updater: Tag version 0.6 + + * python-updater: Echo the PMS command before running, #232860. + + * python-updater: Tell the user to use -o switch when no previous + python versions are found, #232761. + + * python-updater: Make check manual print reason without --verbose, + #232467. + +2008-06-21 Ali Polatel + + * python-updater, man.include, Makefile: List checks in help output + and make indenting a bit nicer. Man page cosmetics. + +2008-06-20 Ali Polatel + + * python-updater: Fixed veinfo + + * 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 + + * +ChangeLog: Added ChangeLog + +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 + + * python-updater: be more specific when searching for package name + +2007-10-29 Ali Polatel + + * python-updater: added dev-libs/boost to PKGS_MANUAL + +2007-10-29 Ali Polatel + + * python-updater: imported python-updater from gentoo-python + +2007-10-29 Ali Polatel + + * .: added projects/python-updater + diff --git a/python-updater b/python-updater new file mode 100755 index 0000000..dff71fb --- /dev/null +++ b/python-updater @@ -0,0 +1,414 @@ +#!/bin/bash +# 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. +# +# OLD_PY_VER = old python version we are upgrading from +# NEW_PY_VER = new python version we are upgrading to +# PKGS_EXCEPTIONS = packages that should NOT be re-emerged for any reason +# PKGS_MANUAL = packages that should be re-emerged even if they don't +# fit the criteria (eg. ones that have python compiled +# statically) +# +# Runtime Variables: +# +# PKGS_TO_REMERGE = list of packages we deem to need re-emerging +# PKGS_OK = list of packages that should be merged without any problems +# PKGS_MISSING = list of packages that are installed, but cannot be merged +# because they have been pruned from portage +# PKGS_MASKED = list of packages that are installed, but masked. +# + +VERSION="0.6" +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" + +PRETEND=0 +IGNORE_VERSIONS=0 +VERBOSE=0 +PKGS_TO_REMERGE="" +PKGS_COUNT_REMERGE=0 +PORTAGE_PYTHON="/usr/bin/python" + +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() { + 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 + Use package manager PM, where PM can be one of: +$(for p in ${SUPPORTED_PMS} ; do +echo -ne $'\t\t '\* ${p} +if [[ ${p} == portage ]]; then + echo ' (Default)' +else + echo +fi +done) + -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 where CHECK can be one of: + * eclass (Disabled by default) + * pylibdir (Enabled by default) + * soname (Enabled by default) + * manual (Enabled by default) + -dCHECK --disable-CHECK + Disable CHECK. See --enable option for a list of checks + +See CHECKS section in the manpage for explanations about checks and +EXAMPLES section to learn how to use them. +EOF_USAGE +} + +# veinfo(verbosity, message) +# einfo message if VERBOSE is bigger than verbosity +veinfo() { + if [[ VERBOSE -ge $1 ]]; then + shift + einfo $@ + 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}" && -e /usr/bin/python${old} ]] + then + echo -n "${old}" + return 0 + fi + done + eerror "Couldn't determine any previous Python version(s)." + eerror "Use -o OLD_PYTHON_VERSION to specify your old python version." + 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 "Couldn'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 + 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" + ;; + -i|--ignore-versions) + IGNORE_VERSIONS=1 + ;; + -P|--package-manager) + shift + PACKAGE_MANAGER="$1" + case "${PACKAGE_MANAGER}" in + portage|pkgcore|paludis) + ;; + *) + echo "unrecognised package manager selected. please select between ${SUPPORTED_PMS}" + 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 + [[ ${PM} == ${PACKAGE_MANAGER} ]] && break + 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 + ;; + esac + shift +done + +# Sanity check +PORTDIR="$(get_portage_portdir)" +[[ $? != 0 ]] && exit 1 + +# Determine old python version +if [[ -z "${OLD_PY_VER}" ]]; then + OLD_PY_VER="$(get_old_pyver)" + if [[ $? != 0 ]]; then + exit 1 + fi +fi + +# Get portage python +PORTAGE_PYTHON="$(get_portage_python ${OLD_PY_VER} ${NEW_PY_VER})" +[[ $? != 0 ]] && exit 1 + + +einfo "Starting Python Updater from ${OLD_PY_VER} to ${NEW_PY_VER} :" +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 + veinfo 2 "Skipping ${CATPKG}, reason: exception" + exception=1 + break; + fi + done + + [[ ${exception} == 1 ]] && continue + + # Check if package is in PKGS_MANUAL + if [[ CHECK_MANUAL -ne 0 ]]; then + for pkg in ${PKGS_MANUAL}; do + if [ -z "${CATPKG##${pkg}}" ]; then + exception=2 + break; + 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 + SLOT=$(< ${content/CONTENTS/SLOT}) + CATPKGVER="${CATPKG}:${SLOT}" + else + CATPKGVER="=${CATPKGVER}" + fi + + if [[ ${exception} = 2 ]]; then + PKGS_TO_REMERGE="${PKGS_TO_REMERGE} ${CATPKGVER}" + eindent + einfo "Adding to list: ${CATPKGVER}" + eindent + einfo "check: manual [Added to list manually, see CHECKS in manpage for more information.]" + eoutdent && eoutdent + continue + fi + + 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}" + eindent + veinfo 1 "check: pylibdir [ Installed file under old python library directory ]" + eoutdent && 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}" + eindent + veinfo 1 "check: soname [ Libraries linked to old libpython found:" + veinfo 1 "${broken_libs}" + veinfo 1 "]" + eoutdent && eoutdent + fi + 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}" + eindent + veinfo 1 "check: eclass [ Ebuild set PYVER=${OLD_PY_VER} ]" + eoutdent && 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" + +# (Pretend to) remerge packages +if [[ -n "${PKGS_TO_REMERGE}" ]]; then + cmd="${PMS_COMMAND[${PMS_INDEX}]} ${PMS_OPTIONS[${PMS_INDEX}]} ${PKGS_TO_REMERGE}" + einfo ${cmd} + ${cmd} +else + einfo "No packages needs to be remerged." +fi + diff --git a/python-updater.1 b/python-updater.1 new file mode 100644 index 0000000..97caa68 --- /dev/null +++ b/python-updater.1 @@ -0,0 +1,111 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36. +.TH PYTHON-UPDATER "1" "August 2008" "python-updater 0.6" "User Commands" +.SH NAME +python-updater \- manual page for python-updater 0.6 +.SH SYNOPSIS +.B python-updater +[\fIOPTION\fR] +.SH DESCRIPTION +python\-updater \fB\-\-\fR Find & rebuild packages broken due to a python upgrade +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print usage +.TP +\fB\-V\fR, \fB\-\-version\fR +Print version +.TP +\fB\-p\fR, \fB\-\-pretend\fR +Pretend (don't do anything) +.TP +\fB\-v\fR, \fB\-\-verbose\fR +Increase verbosity (may be specified multiple times) +.TP +\fB\-o\fR PYVER, \fB\-\-old\-version\fR PYVER +Set old python version to upgrade from to PYVER +.TP +\fB\-i\fR, \fB\-\-ignore\-versions\fR +Ignore versions when remerging packages +(still respects SLOTs) +.TP +\fB\-P\fR PM, \fB\-\-package\-manager\fR PM +Use package manager PM, where PM can be one of: +portage +pkgcore +paludis +.TP +\fB\-c\fR CMD, \fB\-\-command\fR CMD +Pipe found packages to command CMD instead of invoking package +manager. Only for debug and script use. +.TP +\fB\-eCHECK\fR \fB\-\-enable\-CHECK\fR +Enable CHECK where CHECK can be one of: +eclass +pylibdir +soname +manual +.TP +\fB\-dCHECK\fR \fB\-\-disable\-CHECK\fR +Disable CHECK. See \fB\-\-enable\fR option for a list of checks +.PP +See CHECKS section for explanations about checks and +EXAMPLES section to learn how to use them. +.SH EXAMPLES + +\(bu Rebuild packages after a python upgrade. Default options are just fine ;) + + $> python-updater + +\(bu Rebuild packages omitting manually added ones: + + $> python-updater -dmanual + $> python-updater -disable-manual + +\(bu You can use unique substrings instead of names for checks: + + $> python-updater -dm -ep + $> python-updater --disable-m --enable-pylib +.SH 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 +.SH AUTHORS +Bryan Østergaard "kloeri" <bryan.ostergaard@gmail.com> + Wrote main code + +Ali Polatel "hawking" <hawking@gentoo.org> + Current maintainer +.SH ENVIRONMENT + +PYUPDATER_OPTIONS + Default command line options +.SH "REPORTING BUGS" +Submit bug reports to https://bugs.gentoo.org/ +.SH COPYRIGHT +Copyright \(co 2007-2008 Gentoo Foundation, +distributed under the terms of the GNU General Public License v2 |