From f4251f9f75a0f5af65fd07e029828fccce781722 Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Fri, 29 Jan 2010 16:35:52 +0000 Subject: Properly handle packages not supporting installation for multiple Python versions and calling python_set_active_version(). --- ChangeLog | 5 ++ python-updater | 207 +++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 147 insertions(+), 65 deletions(-) diff --git a/ChangeLog b/ChangeLog index d8959bd..5191f6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ ChangeLog for python-updater This file lists all changes except typo and formatting fixes. +2010-01-29 Arfrever Frehtes Taifersar Arahesis + + * python-updater: Properly handle packages not supporting installation for multiple + Python versions and calling python_set_active_version(). + 2009-12-30 Arfrever Frehtes Taifersar Arahesis * python-updater: Don't support undocumented short options. diff --git a/python-updater b/python-updater index 8e2a169..a172dc5 100755 --- a/python-updater +++ b/python-updater @@ -1,6 +1,6 @@ #!/bin/bash # vim: set et sw=4 sts=4 tw=80: -# Copyright 2007-2009 Gentoo Foundation +# Copyright 2007-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # A bit of hackery to update everything that is humanly possible @@ -22,7 +22,11 @@ VERSION="0.8" OLD_PYTHON_VERSIONS="" +OLD_PYTHON2_VERSIONS="" +OLD_PYTHON3_VERSIONS="" NEW_PYTHON_VERSION="$(/usr/bin/python -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')" +NEW_PYTHON2_VERSION="" +NEW_PYTHON3_VERSION="" PKGS_EXCEPTIONS="dev-lang/python sys-apps/portage" PKGS_MANUAL="app-office/gnumeric app-office/dia dev-libs/boost x11-libs/vte" @@ -32,7 +36,9 @@ REINSTALL_IDENTICAL_VERSIONS=0 VERBOSE=0 PKGS_TO_REMERGE="" PKGS_COUNT_REMERGE=0 -PYTHON_VERSIONS="2.1 2.2 2.3 2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3" +PYTHON2_VERSIONS="2.1 2.2 2.3 2.4 2.5 2.6 2.7" +PYTHON3_VERSIONS="3.0 3.1 3.2 3.3" +PYTHON_VERSIONS="${PYTHON2_VERSIONS} ${PYTHON3_VERSIONS}" SUPPORTED_PMS="portage pkgcore paludis" PMS_COMMAND=( "emerge" "pmerge" "paludis" ) @@ -110,34 +116,34 @@ EOF_USAGE # veinfo(verbosity, message) # einfo message if VERBOSE is bigger than verbosity. veinfo() { - if [[ VERBOSE -ge $1 ]]; then + if [[ VERBOSE -ge ${1} ]]; then shift - einfo "$@" + einfo "${@}" fi } # die(message) # Print error message and exit. die() { - eerror "$@" + eerror "${@}" exit 1 } # has_version(cpv) has_version() { if [[ "${PMS_COMMAND[${PMS_INDEX}]}" == "emerge" ]]; then - /usr/bin/portageq has_version / "$1" + /usr/bin/portageq has_version / "${1}" elif [[ "${PMS_COMMAND[${PMS_INDEX}]}" == "pmerge" ]]; then - pquery --vdb "$1" + pquery --vdb "${1}" else - paludis --has-version "$1" + paludis --has-version "${1}" fi } # get_vdb_variable(variable, environment_file) get_vdb_variable() { - local variable="$1" - local environment_file="$2" + local variable="${1}" + local environment_file="${2}" unset "${variable}" local output @@ -166,10 +172,10 @@ get_USE_PYTHON() { USE_PYTHON="$(/usr/bin/portageq envvar USE_PYTHON)" fi else - USE_PYTHON="$(paludis --environment-variable "$1/$2:$3::/?" USE_PYTHON)" + USE_PYTHON="$(paludis --environment-variable "${1}/${2}${3:+:}${3}::/?" USE_PYTHON)" fi if [[ -z "${USE_PYTHON}" ]]; then - USE_PYTHON="${PYTHON2_VERSION} ${PYTHON3_VERSION}" + USE_PYTHON="${NEW_PYTHON2_VERSION} ${NEW_PYTHON3_VERSION}" USE_PYTHON="${USE_PYTHON# }" USE_PYTHON="${USE_PYTHON% }" fi @@ -178,7 +184,7 @@ get_USE_PYTHON() { # get_ebuild_path(CATEGORY, PN, SLOT) get_ebuild_path() { - # These manual calls to Portage API are 2 times faster than 'portageq get_repo_path / "$(portageq metadata / ebuild "$(portageq best_visible / "$1")" repository)"'. + # These manual calls to Portage API are 2 times faster than 'portageq get_repo_path / "$(portageq metadata / ebuild "$(portageq best_visible / "${1}")" repository)"'. /usr/bin/python -c " import sys @@ -188,7 +194,7 @@ if '' in sys.path: import portage dbapi = portage.db['/']['porttree'].dbapi -pkg_list = dbapi.match('$1/$2:$3') +pkg_list = dbapi.match('${1}/${2}${3:+:}${3}') if pkg_list: best_visible = portage.best(pkg_list) if best_visible: @@ -196,24 +202,50 @@ if pkg_list: if repository: repository_path = dbapi.getRepositoryPath(repository[0]) if repository_path: - print(repository_path + '/$1/$2/' + best_visible.split('/')[1] + '.ebuild')" + print(repository_path + '/${1}/${2}/' + best_visible.split('/')[1] + '.ebuild')" } # get_RESTRICT_PYTHON_ABIS(CATEGORY, PN, SLOT) get_RESTRICT_PYTHON_ABIS() { if [[ "${PMS_COMMAND[${PMS_INDEX}]}" =~ ^(emerge|pmerge)$ ]]; then - local ebuild_path="$(get_ebuild_path "$1" "$2" "$3")" + local ebuild_path="$(get_ebuild_path "${1}" "${2}" "${3}")" if [[ -f "${ebuild_path}" ]]; then grep "^RESTRICT_PYTHON_ABIS=" "${ebuild_path}" | sed -e "s/RESTRICT_PYTHON_ABIS=[\"']\(.*\)[\"']/\1/" fi else - paludis --environment-variable "$1/$2:$3::/?" RESTRICT_PYTHON_ABIS + paludis --environment-variable "${1}/${2}${3:+:}${3}::/?" RESTRICT_PYTHON_ABIS + fi +} + +# get_OLD_PYTHON_VERSIONS_REGEX() +get_OLD_PYTHON_VERSIONS_REGEX() { + if [[ -n "${PYTHON_REQUESTED_ACTIVE_VERSION}" ]]; then + if [[ "${PYTHON_REQUESTED_ACTIVE_VERSION}" == "2" ]]; then + echo "${OLD_PYTHON2_VERSIONS_REGEX}" + elif [[ "${PYTHON_REQUESTED_ACTIVE_VERSION}" == "3" ]]; then + echo "${OLD_PYTHON3_VERSIONS_REGEX}" + fi + else + echo "${OLD_PYTHON_VERSIONS_REGEX}" + fi +} + +# get_OLD_PYTHON_SHARED_LIBRARIES_REGEX() +get_OLD_PYTHON_SHARED_LIBRARIES_REGEX() { + if [[ -n "${PYTHON_REQUESTED_ACTIVE_VERSION}" ]]; then + if [[ "${PYTHON_REQUESTED_ACTIVE_VERSION}" == "2" ]]; then + echo "${OLD_PYTHON2_SHARED_LIBRARIES_REGEX}" + elif [[ "${PYTHON_REQUESTED_ACTIVE_VERSION}" == "3" ]]; then + echo "${OLD_PYTHON3_SHARED_LIBRARIES_REGEX}" + fi + else + echo "${OLD_PYTHON_SHARED_LIBRARIES_REGEX}" fi } # Respect PYUPDATER_OPTIONS if [[ -n "${PYUPDATER_OPTIONS}" ]]; then - set -- ${PYUPDATER_OPTIONS} "$@" + set -- ${PYUPDATER_OPTIONS} "${@}" fi # Respect PACKAGE_MANAGER environment variable @@ -227,8 +259,8 @@ for pm in ${SUPPORTED_PMS}; do done # Command Line Parsing -while [[ -n "$1" ]]; do - case "$1" in +while [[ -n "${1}" ]]; do + case "${1}" in -h|--help) usage exit 0 @@ -241,14 +273,14 @@ while [[ -n "$1" ]]; do PRETEND=1 ;; -v|--verbose) - VERBOSE=$(( $VERBOSE + 1 )) + ((VERBOSE++)) ;; --reinstall-identical-versions) REINSTALL_IDENTICAL_VERSIONS=1 ;; -P|--package-manager) shift - PACKAGE_MANAGER="$1" + PACKAGE_MANAGER="${1}" case "${PACKAGE_MANAGER}" in portage|pkgcore|paludis) ;; @@ -267,11 +299,11 @@ while [[ -n "$1" ]]; do ;; --package-manager-command) shift - CUSTOM_PMS_COMMAND="$1" + CUSTOM_PMS_COMMAND="${1}" ;; -c|--command) shift - PIPE_COMMAND="$1" + PIPE_COMMAND="${1}" ;; -eeclass|--enable-eclass) CHECK_ECLASS=1 @@ -317,33 +349,31 @@ while [[ -n "$1" ]]; do ;; --) shift - ADDITIONAL_OPTIONS="$*" + ADDITIONAL_OPTIONS="${*}" break ;; *) usage - echo "Unrecognized option '$1'" + echo "Unrecognized option '${1}'" exit 1 ;; esac shift done -PYTHON2_VERSION="" -PYTHON3_VERSION="" if has_version "=dev-lang/python-2*"; then if [[ "$(readlink /usr/bin/python2)" != "python2."* ]]; then die "'/usr/bin/python2' is not valid symlink" fi - PYTHON2_VERSION="$(/usr/bin/python2 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')" + NEW_PYTHON2_VERSION="$(/usr/bin/python2 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')" fi if has_version "=dev-lang/python-3*"; then if [[ "$(readlink /usr/bin/python3)" != "python3."* ]]; then die "'/usr/bin/python3' is not valid symlink" fi - PYTHON3_VERSION="$(/usr/bin/python3 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')" + NEW_PYTHON3_VERSION="$(/usr/bin/python3 -c 'from sys import version_info; print(".".join([str(x) for x in version_info[:2]]))')" fi -if [[ -z "${PYTHON2_VERSION}" && -z "${PYTHON3_VERSION}" ]]; then +if [[ -z "${NEW_PYTHON2_VERSION}" && -z "${NEW_PYTHON3_VERSION}" ]]; then die "Python 2 and Python 3 not installed" fi @@ -363,7 +393,42 @@ OLD_PYTHON_VERSIONS_REGEX="(${OLD_PYTHON_VERSIONS// /|})" OLD_PYTHON_VERSIONS_REGEX="${OLD_PYTHON_VERSIONS_REGEX//./\.}" OLD_PYTHON_SHARED_LIBRARIES_REGEX="(${OLD_PYTHON_SHARED_LIBRARIES_REGEX})" -einfo $'\e[1;34m'"Starting Python Updater [New main active Python version: ${NEW_PYTHON_VERSION}]"$'\e[0m' +OLD_PYTHON2_SHARED_LIBRARIES_REGEX="" +for python_version in ${PYTHON2_VERSIONS}; do + if [[ "${python_version}" != "${NEW_PYTHON2_VERSION}" ]]; then + OLD_PYTHON2_VERSIONS+="${OLD_PYTHON2_VERSIONS:+ }${python_version}" + soname="$(readlink -n /usr/lib/libpython${python_version}.so)" + if [[ -z "${soname}" ]]; then + # Use relatively safe, default value. + soname="libpython${python_version}.so.1.0" + fi + OLD_PYTHON2_SHARED_LIBRARIES_REGEX+="${OLD_PYTHON2_SHARED_LIBRARIES_REGEX:+|}${soname//./\.}" + fi +done +OLD_PYTHON2_VERSIONS_REGEX="(${OLD_PYTHON2_VERSIONS// /|})" +OLD_PYTHON2_VERSIONS_REGEX="${OLD_PYTHON2_VERSIONS_REGEX//./\.}" +OLD_PYTHON2_SHARED_LIBRARIES_REGEX="(${OLD_PYTHON2_SHARED_LIBRARIES_REGEX})" + +OLD_PYTHON3_SHARED_LIBRARIES_REGEX="" +for python_version in ${PYTHON3_VERSIONS}; do + if [[ "${python_version}" != "${NEW_PYTHON3_VERSION}" ]]; then + OLD_PYTHON3_VERSIONS+="${OLD_PYTHON3_VERSIONS:+ }${python_version}" + soname="$(readlink -n /usr/lib/libpython${python_version}.so)" + if [[ -z "${soname}" ]]; then + # Use relatively safe, default value. + soname="libpython${python_version}.so.1.0" + fi + OLD_PYTHON3_SHARED_LIBRARIES_REGEX+="${OLD_PYTHON3_SHARED_LIBRARIES_REGEX:+|}${soname//./\.}" + fi +done +OLD_PYTHON3_VERSIONS_REGEX="(${OLD_PYTHON3_VERSIONS// /|})" +OLD_PYTHON3_VERSIONS_REGEX="${OLD_PYTHON3_VERSIONS_REGEX//./\.}" +OLD_PYTHON3_SHARED_LIBRARIES_REGEX="(${OLD_PYTHON3_SHARED_LIBRARIES_REGEX})" + +einfo $'\e[1;34mStarting Python Updater...\e[0m' +einfo $'\e[1;36m'"Main active version of Python: ${NEW_PYTHON_VERSION}"$'\e[0m' +einfo $'\e[1;36m'"Active version of Python 2: ${NEW_PYTHON2_VERSION:-(None)}"$'\e[0m' +einfo $'\e[1;36m'"Active version of Python 3: ${NEW_PYTHON3_VERSION:-(None)}"$'\e[0m' if [[ CHECK_SHARED_LINKING -ne 0 ]]; then if ! type -P scanelf >/dev/null 2>&1; then @@ -405,19 +470,24 @@ fi for content in $(find ${PKG_DBDIR}/ -name CONTENTS | sort); do environment_file="${content/CONTENTS/environment.bz2}" - # Extract some variables. PYTHON_ABIS is optional. + # Extract some variables. PYTHON_ABIS and PYTHON_REQUESTED_ACTIVE_VERSION are optional. get_vdb_variable PVR "${environment_file}" || die "PVR missing" - get_vdb_variable SLOT "${environment_file}" || die "SLOT missing" get_vdb_variable PYTHON_ABIS "${environment_file}" + get_vdb_variable PYTHON_REQUESTED_ACTIVE_VERSION "${environment_file}" - # Manually calculate CATEGORY, PF and PN to avoid problems with moved packages. + # Manually calculate CATEGORY, PF, PN and SLOT to avoid problems with moved packages. CATEGORY="$(echo "${environment_file#${PKG_DBDIR}/}" | sed -e "s:/.*::")" PF="$(echo "${environment_file#${PKG_DBDIR}/${CATEGORY}/}" | sed -e "s:/.*::")" PN="${PF%-${PVR}}" + if [[ -f "${content/CONTENTS/SLOT}" ]]; then + SLOT="$(<"${content/CONTENTS/SLOT}")" + else + get_vdb_variable SLOT "${environment_file}" + fi CATPKG="${CATEGORY}/${PN}" CATPKGVER="${CATEGORY}/${PF}" - veinfo 2 "Checking ${CATEGORY}/${PF}:${SLOT}" + veinfo 2 "Checking ${CATEGORY}/${PF}${SLOT:+:}${SLOT}" # Exclude packages that are exceptions, like Portage and Python itself. exception=0 @@ -443,10 +513,9 @@ for content in $(find ${PKG_DBDIR}/ -name CONTENTS | sort); do # Replace SLOT by version number when REINSTALL_IDENTICAL_VERSIONS == 1 # Reinstall identical versions when SLOT doesn't exist, bug #201848 - if [[ REINSTALL_IDENTICAL_VERSIONS -eq 1 || ! -f "${content/CONTENTS/SLOT}" ]]; then + if [[ REINSTALL_IDENTICAL_VERSIONS -eq 1 || -z "${SLOT}" ]]; then CATPKGVER="=${CATPKGVER}" else - SLOT="$(<"${content/CONTENTS/SLOT}")" CATPKGVER="${CATPKG}:${SLOT}" fi @@ -495,9 +564,38 @@ for content in $(find ${PKG_DBDIR}/ -name CONTENTS | sort); do fi fi + if [[ CHECK_STATIC_LINKING -ne 0 ]]; then + binaries="$(scanelf -qs +Py_Initialize < <(grep -E "^obj" "${content}" | cut -d" " -f2) | sed "s/.* //")" + if [[ -n "${binaries}" ]]; then + PKGS_TO_REMERGE+=" ${CATPKGVER}" + eindent + einfo "Adding to list: ${CATPKGVER}" + eindent + veinfo 1 "check: static_linking [ Binaries linked against Python static libraries found:" + eindent + old_IFS="${IFS}" + IFS=$'\n' + for binary in ${binaries}; do + veinfo 1 "${binary}" + done + IFS="${old_IFS}" + eoutdent + veinfo 1 "]" + eoutdent && eoutdent + fi + fi + + if [[ "${PYTHON_REQUESTED_ACTIVE_VERSION}" =~ ^[[:digit:]]+\.[[:digit:]]+$ ]]; then + eindent && eindent + veinfo 2 "Requested active version of Python: \"${PYTHON_REQUESTED_ACTIVE_VERSION}\"" + eoutdent && eoutdent + # Don't run other checks if given package has been built with precisely specified requested active version of Python. + continue + fi + if [[ CHECK_ECLASS_NEED_REBUILD -ne 0 ]]; then get_vdb_variable PYTHON_NEED_REBUILD "${environment_file}" - if echo "${PYTHON_NEED_REBUILD}" | grep -qE "${OLD_PYTHON_VERSIONS_REGEX}"; then + if echo "${PYTHON_NEED_REBUILD}" | grep -qE "$(get_OLD_PYTHON_VERSIONS_REGEX)"; then PKGS_TO_REMERGE+=" ${CATPKGVER}" eindent einfo "Adding to list: ${CATPKGVER}" @@ -514,7 +612,7 @@ for content in $(find ${PKG_DBDIR}/ -name CONTENTS | sort); do # /usr/lib/python$old # /usr/lib32/python$old # /usr/lib64/python$old - if grep -qE "/usr/(include|lib(32|64)?)/python${OLD_PYTHON_VERSIONS_REGEX}" "${content}"; then + if grep -qE "/usr/(include|lib(32|64)?)/python$(get_OLD_PYTHON_VERSIONS_REGEX)" "${content}"; then PKGS_TO_REMERGE+=" ${CATPKGVER}" eindent einfo "Adding to list: ${CATPKGVER}" @@ -526,34 +624,13 @@ for content in $(find ${PKG_DBDIR}/ -name CONTENTS | sort); do fi if [[ CHECK_SHARED_LINKING -ne 0 ]]; then - binaries="$(scanelf -qF "%F %n" < <(grep -E "^obj" "${content}" | cut -d" " -f2) | grep -E "( |,)${OLD_PYTHON_SHARED_LIBRARIES_REGEX}(,|$)")" - if [[ -n "${binaries}" ]]; then - PKGS_TO_REMERGE+=" ${CATPKGVER}" - eindent - einfo "Adding to list: ${CATPKGVER}" - eindent - veinfo 1 "check: shared_linking [ Binaries linked against old Python shared library found:" - eindent - old_IFS="${IFS}" - IFS=$'\n' - for binary in ${binaries}; do - veinfo 1 "${binary}" - done - IFS="${old_IFS}" - eoutdent - veinfo 1 "]" - eoutdent && eoutdent - fi - fi - - if [[ CHECK_STATIC_LINKING -ne 0 ]]; then - binaries="$(scanelf -qs +Py_Initialize < <(grep -E "^obj" "${content}" | cut -d" " -f2) | sed "s/.* //")" + binaries="$(scanelf -qF "%F %n" < <(grep -E "^obj" "${content}" | cut -d" " -f2) | grep -E "( |,)$(get_OLD_PYTHON_SHARED_LIBRARIES_REGEX)(,|$)")" if [[ -n "${binaries}" ]]; then PKGS_TO_REMERGE+=" ${CATPKGVER}" eindent einfo "Adding to list: ${CATPKGVER}" eindent - veinfo 1 "check: static_linking [ Binaries linked against Python static library found:" + veinfo 1 "check: shared_linking [ Binaries linked against old Python shared libraries found:" eindent old_IFS="${IFS}" IFS=$'\n' @@ -569,7 +646,7 @@ for content in $(find ${PKG_DBDIR}/ -name CONTENTS | sort); do if [[ CHECK_ECLASS -ne 0 ]]; then get_vdb_variable PYVER "${environment_file}" - if echo "${PYVER}" | grep -qE "${OLD_PYTHON_VERSIONS_REGEX}"; then + if echo "${PYVER}" | grep -qE "$(get_OLD_PYTHON_VERSIONS_REGEX)"; then PKGS_TO_REMERGE+=" ${CATPKGVER}" eindent einfo "Adding to list: ${CATPKGVER}" @@ -584,7 +661,7 @@ done # Pipe to command if we have one if [[ -n "${PIPE_COMMAND}" ]]; then echo "${PKGS_TO_REMERGE}" | ${PIPE_COMMAND} - exit $? + exit "${?}" fi if [[ "${PMS_COMMAND[${PMS_INDEX}]}" == "emerge" ]] ; then -- cgit v1.2.3-65-gdbad