diff options
Diffstat (limited to 'eclass')
-rw-r--r-- | eclass/alternatives-2.eclass | 138 |
1 files changed, 100 insertions, 38 deletions
diff --git a/eclass/alternatives-2.eclass b/eclass/alternatives-2.eclass index fe2f55e95..42150c0db 100644 --- a/eclass/alternatives-2.eclass +++ b/eclass/alternatives-2.eclass @@ -1,16 +1,35 @@ -# Copyright 2010-2013 Gentoo Foundation +# Copyright 2010-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $ +# $Header: $ # Based in part upon 'alternatives.exlib' from Exherbo, which is: # Copyright 2008, 2009 Bo Ørsted Andresen # Copyright 2008, 2009 Mike Kelly # Copyright 2009 David Leverton +# @ECLASS: alternatives-2 +# @MAINTAINER: +# Gentoo Science Project <sci@gentoo.org> +# @BLURB: Manage alternative implementations. +# @DESCRIPTION: +# Autogenerate eselect modules for alternatives and ensure that valid provider +# is set. +# +# Remove eselect modules when last provider is unmerged. +# # If your package provides pkg_postinst or pkg_prerm phases, you need to be -# sure you explicitly run alternatives_pkg_{postinst,prerm} where appropriate. - -ALTERNATIVES_DIR="/etc/env.d/alternatives" +# sure you explicitly run alternatives-2_pkg_{postinst,prerm} where appropriate. + +case "${EAPI:-0}" in + 0|1|2|3) + die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" + ;; + 4|5) + ;; + *) + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" + ;; +esac DEPEND=">=app-admin/eselect-1.4-r100" RDEPEND="${DEPEND} @@ -18,30 +37,50 @@ RDEPEND="${DEPEND} !app-admin/eselect-cblas !app-admin/eselect-lapack" -# alternatives_for alternative provider importance source target [ source target [...]] -alternatives_for() { - #echo alternatives_for "${@}" +EXPORT_FUNCTIONS pkg_postinst pkg_prerm +# @ECLASS-VARIABLE: ALTERNATIVES_DIR +# @INTERNAL +# @DESCRIPTION: +# Alternatives directory with symlinks managed by eselect. +ALTERNATIVES_DIR="/etc/env.d/alternatives" + +# @FUNCTION: alternatives_for +# @USAGE: alternative provider importance source target [source target [...]] +# @DESCRIPTION: +# Set up alternative provider. +# +# EXAMPLE: +# @CODE +# alternatives_for cblas atlas 0 \ +# /usr/$(get_libdir)/pkgconfig/cblas.pc atlas-cblas.pc \ +# /usr/include/cblas.h atlas/cblas.h +# @CODE +alternatives_for() { (( $# >= 5 )) && (( ($#-3)%2 == 0)) || die "${FUNCNAME} requires exactly 3+N*2 arguments where N>=1" - local x dupl alternative=${1} provider=${2} importance=${3} index unique src target ret=0 + local alternative=${1} provider=${2} importance=${3} index src target ret=0 shift 3 - # make sure importance is a signed integer + # Make sure importance is a signed integer if [[ -n ${importance} ]] && ! [[ ${importance} =~ ^[0-9]+(\.[0-9]+)*$ ]]; then eerror "Invalid importance (${importance}) detected" ((ret++)) fi + # Create alternative provider subdirectories under ALTERNATIVES_DIR if needed [[ -d "${ED}${ALTERNATIVES_DIR}/${alternative}/${provider}" ]] || dodir "${ALTERNATIVES_DIR}/${alternative}/${provider}" - # keep track of provided alternatives for use in pkg_{postinst,prerm}. keep a mapping between importance and - # provided alternatives and make sure the former is set to only one value + # Keep track of provided alternatives for use in pkg_{postinst,prerm}. + # Keep a mapping between importance and provided alternatives + # and make sure the former is set to only one value. if ! has "${alternative}:${provider}" "${ALTERNATIVES_PROVIDED[@]}"; then + # Add new provider and set its importance index=${#ALTERNATIVES_PROVIDED[@]} ALTERNATIVES_PROVIDED+=( "${alternative}:${provider}" ) ALTERNATIVES_IMPORTANCE[index]=${importance} [[ -n ${importance} ]] && echo "${importance}" > "${ED}${ALTERNATIVES_DIR}/${alternative}/${provider}/_importance" else + # Set importance for existing provider for((index=0;index<${#ALTERNATIVES_PROVIDED[@]};index++)); do if [[ ${alternative}:${provider} == ${ALTERNATIVES_PROVIDED[index]} ]]; then if [[ -n ${ALTERNATIVES_IMPORTANCE[index]} ]]; then @@ -57,6 +96,7 @@ alternatives_for() { done fi + # Process source-target pairs while (( $# >= 2 )); do src=${1//+(\/)/\/}; target=${2//+(\/)/\/} if [[ ${src} != /* ]]; then @@ -76,8 +116,9 @@ alternatives_for() { dodir "${ALTERNATIVES_DIR}/${alternative}/${provider}${src%/*}" dosym "${reltarget}" "${ALTERNATIVES_DIR}/${alternative}/${provider}${src}" - # say ${ED}/sbin/init exists and links to /bin/systemd (which doesn't exist yet) - # the -e test will fail, so check for -L also + # The -e test will fail if existing symlink points to non-existing target, + # so check for -L also. + # Say ${ED}/sbin/init exists and links to /bin/systemd (which doesn't exist yet). if [[ -e ${ED}${src} || -L ${ED}${src} ]]; then local fulltarget=${target} [[ ${fulltarget} != /* ]] && fulltarget=${src%/*}/${fulltarget} @@ -91,34 +132,48 @@ alternatives_for() { shift 2 done + # Stop if there were any errors [[ ${ret} -eq 0 ]] || die "Errors detected for ${provider}, provided for ${alternative}" } +# @FUNCTION: cleanup_old_alternatives_module +# @USAGE: alternative +# @DESCRIPTION: +# Remove old alternatives module. cleanup_old_alternatives_module() { local alt=${1} old_module="${EROOT%/}/usr/share/eselect/modules/${alt}.eselect" - if [[ -f "${old_module}" && "$(source "${old_module}" &>/dev/null; echo "${ALTERNATIVE}")" == "${alt}" ]]; then - local version="$(source "${old_module}" &>/dev/null; echo "${VERSION}")" + if [[ -f "${old_module}" && $(grep 'ALTERNATIVE=' "${old_module}" | cut -d '=' -f 2) == "${alt}" ]]; then + local version="$(grep 'VERSION=' "${old_module}" | grep -o '[0-9.]\+')" if [[ "${version}" == "0.1" || "${version}" == "20080924" ]]; then - echo rm "${old_module}" + echo "rm ${old_module}" rm "${old_module}" || eerror "rm ${old_module} failed" fi fi } +# @FUNCTION: alternatives-2_pkg_postinst +# @DESCRIPTION: +# Create eselect modules for all provided alternatives if necessary and ensure +# that valid provider is set. +# +# Also remove old eselect modules for provided alternatives. +# +# Provided alternatives are set up using alternatives_for(). alternatives-2_pkg_postinst() { local a alt provider module_version="20090908" + local EAUTO="${EROOT%/}/usr/share/eselect/modules/auto" for a in "${ALTERNATIVES_PROVIDED[@]}"; do alt="${a%:*}" provider="${a#*:}" - if [[ ! -f "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" \ - || "$(source "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" &>/dev/null; echo "${VERSION}")" \ + if [[ ! -f "${EAUTO}/${alt}.eselect" \ + || "$(grep '^VERSION=' "${EAUTO}/${alt}.eselect" | grep -o '[0-9]\+')" \ -ne "${module_version}" ]]; then - #einfo "Creating alternatives module for ${alt}" - if [[ ! -d ${EROOT%/}/usr/share/eselect/modules/auto ]]; then - install -d "${EROOT%/}"/usr/share/eselect/modules/auto || eerror "Could not create eselect modules dir" + if [[ ! -d ${EAUTO} ]]; then + install -d "${EAUTO}" || eerror "Could not create eselect modules dir" fi - cat > "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" <<-EOF - # This module was automatically generated by alternatives.eclass + einfo "Creating alternatives eselect module for ${alt}" + cat > "${EAUTO}/${alt}.eselect" <<-EOF + # This module was automatically generated by alternatives-2.eclass DESCRIPTION="Alternatives for ${alt}" VERSION="${module_version}" MAINTAINER="eselect@gentoo.org" @@ -130,36 +185,43 @@ alternatives-2_pkg_postinst() { EOF fi - #echo eselect "${alt}" update "${provider}" - einfo "Creating ${provider} alternative module for ${alt}" + # Set alternative provider if there is no valid provider selected eselect "${alt}" update "${provider}" cleanup_old_alternatives_module ${alt} done } +# @FUNCTION: alternatives-2_pkg_prerm +# @DESCRIPTION: +# Ensure a valid provider is set in case the package is unmerged and +# remove autogenerated eselect modules for all alternatives when last +# provider is unmerged. +# +# Provided alternatives are set up using alternatives_for(). alternatives-2_pkg_prerm() { - local a alt provider p ignore - [[ -n ${REPLACED_BY_ID} ]] || ignore=" --ignore" + local a alt provider ignore ret + local EAUTO="${EROOT%/}/usr/share/eselect/modules/auto" + # If we are uninstalling, update alternatives to valid provider + [[ -n ${REPLACED_BY_VERSION} ]] || ignore="--ignore" for a in "${ALTERNATIVES_PROVIDED[@]}"; do alt="${a%:*}" provider="${a#*:}" - #echo "Making sure ${alt} has a valid provider" - #echo eselect "${alt}" update${ignore} "${provider}" - eselect "${alt}" update${ignore} "${provider}" && continue - einfo "Removing ${provider} alternative module for ${alt}, current is $(eselect ${alt} show)" - case $? in + eselect "${alt}" update ${ignore} "${provider}" + ret=$? + [[ -n ${REPLACED_BY_VERSION} ]] || \ + einfo "Removing ${provider} alternative module for ${alt}, current is $(eselect ${alt} show)" + case ${ret} in 0) : ;; 2) + # This was last provider for the alternative, remove eselect module einfo "Cleaning up unused alternatives module for ${alt}" - rm "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" || \ - eerror rm "${EROOT%/}/usr/share/eselect/modules/auto/${alt}.eselect" failed + rm "${EAUTO}/${alt}.eselect" || \ + eerror "rm ${EAUTO}/${alt}.eselect failed" ;; *) - eerror eselect "${alt}" update "${provider}" returned $? + eerror "eselect ${alt} update ${provider} returned $?" ;; esac done } - -EXPORT_FUNCTIONS pkg_postinst pkg_prerm |