Dear List,

This module is to replace the existing one that is shipped with
<app-admin/eselect-postgresql-1.0.3. It is an entire rewrite.

Changes can be tracked at:
http://git.overlays.gentoo.org/gitweb/?p=proj/pgsql-patches.git;a=shortlog;h=refs/heads/eselect

Before you start reading the attached module, please bear in mind that I
am a novice at writing BASH scripts, and am not intimately familiar with
all the nuances of the language.

There is some duplication of work within the module when compared with
the current postgresql-{base,server}-*.ebuilds in the tree. The plan is
to move that work being handled in the ebuilds to the module.

Setting a service slot has been dropped from the module as it is no
longer necessary.

Features:
* Supports --brief output
* Prefix compatible
* Slot specific application links (e.g., psql90, createdb84)
* Automatically sets the highest slot available as the default unless a
  valid slot is already set
* Properly orders LDPATH giving preference to the set slot and then
  lists the other slots in descending order

Thank you.

Sincerely,
  Mr. Aaron W. Swenson (TitanOfOld)
# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id: $

inherit config multilib output package-manager path-manipulation

DESCRIPTION="Manage active PostgreSQL client applications and libraries"
MAINTAINER="pgsql-b...@gentoo.org"
SVN_DATE='$Date: $'
VERSION="1.0.4"

# Global Data
B_PATH="${EROOT%/}/usr"
E_PATH="${EROOT%/}/etc/eselect/postgresql"
ENV_FILE="${EROOT%/}/etc/env.d/50postgresql"
if [ -r ${E_PATH}/active -a -n ${E_PATH}/active ] ; then
        ACTIVE_SLOT=$(<${E_PATH}/active)
else
        ACTIVE_SLOT="(none)"
fi
LIB_LIST=$(list_libdirs)
if [[ ${LIB_LIST} =~ .*lib64.* && "$(ls -d ${B_PATH}/lib64/postgresql-*/lib)" 
!= "" ]] ; then
        LIBDIR="lib64"
elif [[ ${LIB_LIST} =~ .*lib32.* && "$(ls -d ${B_PATH}/lib32/postgresql-*/lib)" 
!= "" ]] ; then
        LIBDIR="lib32"
else
        LIBDIR="lib"
fi

### Linker Function ###
# Takes three arguments:
#   - Full source path (e.g. /usr/lib/postgresql-9.0/lib/lib*.{a,so})
#   - Full target directory path (e.g. /usr/bin)
#   - Suffix (Optional) (e.g 84 to make /usr/bin/psql84)
linker() {
        local source_dir=$1
        local target_dir=$2
        local suffix=$3
        local link_source

        for link_source in $(eval ls ${source_dir} 2> /dev/null) ; do
                local link_target="${target_dir%/}/$(basename 
${link_source})${suffix}"

                # For good measure, remove target before creating the symlink
                [ -h ${link_target} ] && rm -f ${link_target}
                [ -e ${link_target} ] && die -q "The target '${link_target}' 
still exists and could not be removed!"

                ln -s ${link_source} ${link_target} || die -q "Unable to create 
link!"
                echo ${link_target} >> ${E_PATH}/active.links${suffix}
        done
}

### Unlinker Function ###
# Takes one argument:
#   - Full path to active links file (e.g. /etc/eselect/postgresql/active.links)
unlinker() {
        local active_link_file=$1
        if [ -r ${active_link_file} ] ; then
                local active_links=($(<${active_link_file}))
                for (( i=0; $i < ${#active_links[@]}; i++ )) ; do
                        [ -h ${active_links[$i]} ] && rm -f ${active_links[$i]}
                        [ -e ${active_links[$i]} ] && die -q "The target 
'${active_links[$i]}' still exists and could not be removed!"
                done

                rm -f ${active_link_file}
        fi
}

### Get Slots Function ###
# Find all available slots in the preferred LIBDIR and return them.
get_slots() {
        echo $(ls -dv ${B_PATH}/${LIBDIR}/postgresql-* 2> /dev/null | sed -re 
's#^.+-##')
}

### List Action ###
describe_list() {
        echo "List available PostgreSQL slots."
}

do_list() {
        write_list_start "Available PostgreSQL Slots"

        if $(is_output_mode brief) ; then
                echo $(get_slots)
        else
                local slot
                for slot in $(get_slots) ; do
                        local postgres_ebuilds=""
                        local src
                        for src in 
${E_PATH}/slots/${slot}/{server,service,base,docs} ; do
                                [ -r ${src} ] && source ${src}
                        done

                        case "${slot}" in
                                "${ACTIVE_SLOT}" ) write_kv_list_entry 
"$(highlight_marker ${slot})" "${postgres_ebuilds//postgresql-/}";;
                                *                ) write_kv_list_entry 
"${slot}" "${postgres_ebuilds//postgresql-/}";;
                        esac
                done

                [ -z "${postgres_ebuilds}" ] && write_warning_msg "No slots 
available."
        fi
}

### Show Action ###
describe_show() {
        echo "Show which slot is currently active."
}

do_show() {
        echo ${ACTIVE_SLOT}
}

### Show Service Action ###
# Here for backwards compatibility with ebuilds
describe_show-service()  {
        echo "Deprecated. For ebuild use; returns no useful information."
}

do_show-service() {
        echo 1
}

### Set Action ###
describe_set() {
        echo "Create symbolic links for PostgreSQL libraries and applications."
}

do_set() {
        local SLOT=$1
        if [ ! -d ${B_PATH}/${LIBDIR}/postgresql-${SLOT} ] ; then
                die -q "Not a valid slot."
        fi

        echo "Setting ${SLOT} as the default installation..."

        # Remove the active links to start a fresh list
        echo -ne "\tRemoving old links..."
        unlinker ${E_PATH}/active.links
        echo "done."

        echo -ne "\tGenerating new links..."
        # Sources and targets for header files
        local sources=(
                ${B_PATH}/include/postgresql-${SLOT}
                ${B_PATH}/include/postgresql-${SLOT}/libpq-fe.h
                ${B_PATH}/include/postgresql-${SLOT}/pg_config_manual.h
                ${B_PATH}/include/postgresql-${SLOT}/libpq
                ${B_PATH}/include/postgresql-${SLOT}/postgres_ext.h
        )
        local targets=(
                ${B_PATH}/include/postgresql
                ${B_PATH}/include/libpq-fe.h
                ${B_PATH}/include/pg_config_manual.h
                ${B_PATH}/include/libpq
                ${B_PATH}/include/postgres_ext.h
        )
        # The linker function cannot accomadate this special purpose.
        local i
        for (( i=0; $i < ${#sources[@]}; i++ )) ; do
                # Remove target before creating the symlink
                rm -f ${targets[$i]}

                # Check if link_target still exists
                [ -e ${targets[$i]} ] && die -q "The target '${targets[$i]}' 
exists and could not be removed!"

                ln -s ${sources[$i]} ${targets[$i]} || die -q "Unable to create 
link!"
                echo ${targets[$i]} >> ${E_PATH}/active.links
        done

        # Link modules to /usr/lib{,lib32,lib64}/
        local x
        for x in ${LIB_LIST} ; do
                if [ -d ${B_PATH}/${x}/postgresql-${SLOT}/${x} ] ; then
                        # 'linker' function doesn't work for linking 
directories.
                        # Default lib path
                        ln -s ${B_PATH}/${x}/postgresql-${SLOT}/${x} 
${B_PATH}/${x}/postgresql
                        echo ${B_PATH}/${x}/postgresql >> ${E_PATH}/active.links
                        # Linker works for files
                        linker 
"${B_PATH}/${x}/postgresql-${SLOT}/${x}/lib*.{a,dylib,so}" "${B_PATH}/${x}"
                fi
        done

        # Link binaries to /usr/bin/
        linker "${B_PATH}/${LIBDIR}/postgresql-${SLOT}/bin/*" "${B_PATH}/bin"

        # Default share path
        ln -s ${B_PATH}/share/postgresql-${SLOT} ${B_PATH}/share/postgresql
        echo ${B_PATH}/share/postgresql >> ${E_PATH}/active.links

        echo ${SLOT} > ${E_PATH}/active
        echo "done."
        echo -e "\033[1mSetting ${SLOT} as default was successful!\033[0m"
}

### Unset Action ###
describe_unset() {
        echo "Remove symbolic links."
}

do_unset() {
        local SLOT=$1
        if [ "${SLOT}" = "${ACTIVE_SLOT}" ] ; then
                echo -n "Unsetting ${SLOT} as the default installation..."
                unlinker ${E_PATH}/active.links
                rm -f ${E_PATH}/active
                echo "done."
        else
                echo "Inactive slot selected. No work to do."
        fi
}

### Reset Action ###
describe_reset() {
        echo "Recreate symbolic links for currently active slot."
}

do_reset() {
        [ "${ACTIVE_SLOT}" = "(none)" ] && die -q "No active slot to reset."
        do_unset ${ACTIVE_SLOT}
        do_set ${ACTIVE_SLOT}
}

### Update Action ###
describe_update() {
        echo "Refreshes all symbolic links managed by this module"
}

do_update() {
        # Check for files managed by postgresql.eselect before 1.0
        [ -h /etc/eselect/postgresql/active ] && ACTIVE_SLOT="$(basename 
$(canonicalise /etc/eselect/postgesql/active))"
        # Remove service file outright.
        [ -h /etc/eselect/postgresql/service ] && rm -f 
/etc/eselect/postgresql/service

        local slots=($(get_slots))
        local index=${#slots[@]}

        # In case all slots have been unmerged
        if [ ${index} -eq 0 ] ; then
                write_warning_msg "No slots found!"
                write_warning_msg "Removing files (Control-C to abort) in..."
                local i=6
                while [ $[i--] -gt 0 ] ; do
                        echo -n " $i"
                        sleep 1
                done
                for sym_links in ${E_PATH}/active.links* ; do
                        unlinker ${sym_links}
                done
                rm -f ${E_PATH}/active
                rm -f ${ENV_FILE}
                do_action env update &> /dev/null
                echo "Done!"
                return 0
        fi

        # Reset, otherwise set the highest slot available.
        if [[ ${slots[@]} =~ ${ACTIVE_SLOT} ]] ; then
                do_reset
        else
                # best_version doesn't work here as pkg_postrm runs before the 
world
                # file is updated, thereby returning a false positive.
                do_set ${slots[$index-1]}
        fi

        echo -en "\nCleaning out old links before refreshing..."
        local sym_links
        for sym_links in ${E_PATH}/active.links?* ; do
                unlinker ${sym_links}
        done
        echo "done."

        # Update paths to libs and docs
        local ldpath
        local x
        for x in ${LIB_LIST} ; do
                [ -h ${B_PATH}/${x}/postgresql ] && 
ldpath+="${B_PATH}/${x}/postgresql:"
        done
        ldpath="${ldpath%:}"
        local manpath="${B_PATH}/share/postgresql/"
        while [ $[--index] -gt -1 ] ; do
                local curslot="${slots[$index]}"
                echo -n "Refreshing symbolic links for ${curslot} applications 
(like /usr/bin/psql${curslot//.})..."
                for x in ${LIB_LIST} ; do
                        local 
lib_path="${B_PATH}/${x}/postgresql-${curslot}/${x}/"
                        [ -d ${lib_path} ] && ldpath+=":${lib_path}"
                done
                local share_path="${B_PATH}/share/postgresql-${curslot}/"
                [ -d ${share_path} ] && manpath+=":${share_path}"
                linker "${B_PATH}/${LIBDIR}/postgresql-${curslot}/bin/*" 
"${B_PATH}/bin" "${curslot//.}"
                echo "done."
        done

        # Remove environment files that have been generated by the ebuilds
        rm -f ${ENV_FILE}-*

        store_config ${ENV_FILE} LDPATH "${ldpath}"
        store_config ${ENV_FILE} MANPATH "${manpath}"
        do_action env update &> /dev/null
}

Reply via email to