# Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Id: $ inherit config multilib DESCRIPTION="Manage active PostgreSQL client applications and libraries" MAINTAINER="pgsql-bugs@gentoo.org" VERSION="1.0.11" # Global Data B_PATH="${EROOT%/}/usr" E_PATH="${EROOT%/}/etc/eselect/postgresql" ENV_FILE="${EROOT%/}/etc/env.d/50postgresql" active_slot() { if [[ -r ${E_PATH}/active && -n ${E_PATH}/active ]] ; then echo $( <"${E_PATH}"/active ) else echo "(none)" fi } lib_dir() { local lib_list=$(list_libdirs) if [[ ${lib_list} =~ .*lib64.* && \ -n $(ls -d ${B_PATH}/lib64/postgresql-*/lib64 2> /dev/null) ]] ; then echo "lib64" elif [[ ${lib_list} =~ .*lib32.* && \ -n $(ls -d ${B_PATH}/lib32/postgresql-*/lib32 2> /dev/null) ]] ; then echo "lib32" else echo "lib" fi } ### Linker Function ### # Takes four arguments: # - Full source path (e.g. /usr/lib/postgresql-9.0/lib) # - Pattern to search for # - Full target directory path (e.g. /usr/bin) # - Suffix (Optional) (e.g 84 to make /usr/bin/psql84) linker() { local source_dir=$1 local pattern=$2 local target_dir=$3 local suffix=$4 local link_source local findings local rel_source # Prevent passed patterns from being globbed # If this module is run in /usr, '-name lib*' ends up globbing 'lib*', # passing to 'find' the pattern '-name lib lib32 lib64' and find interprets # those as path arguments causing failure. set -f findings=$(find -L "${source_dir}" -maxdepth 1 -mindepth 1 ${pattern}) set +f for link_source in ${findings} ; 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!" # Create relative links so that they work both here and inside the new # root if $ROOT is not "/". rel_source=$(relative_name "${link_source}" "${target_dir}") ln -s "${rel_source}" "${link_target}" || die -q "Unable to create link!" echo "${link_target##${ROOT%/}/}" >> "${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 "${ROOT%/}/${active_links[$i]}" ]] && \ rm -f "${ROOT%/}/${active_links[$i]}" [[ -e "${ROOT%/}/${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 lib_dir() and return them. get_slots() { local slot local found_slots for slot in $(find "${B_PATH}/$(lib_dir)/" -maxdepth 1 -type d \ -regex '.*postgresql-[0-9][0-9]*\.[0-9][0-9]*' | \ sed -re 's#.*([0-9]+\.[0-9]+)$#\1#' | sort -n) do # Check that pg_config exists for this slot, otherwise we have # a false positive. [[ -x "${B_PATH}/$(lib_dir)/postgresql-${slot}/bin/pg_config" ]] && \ found_slots+=( ${slot} ) done echo ${found_slots[@]} } ### 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}/$(lib_dir)/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 rel_source local i for (( i=0; $i < ${#sources[@]}; i++ )) ; do # Remove target before creating the symlink [[ -h ${targets[$i]} ]] && 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!" # Create relative links so that they work both here and inside the new # root if $ROOT is not "/" rel_source=$(relative_name "${sources[$i]}" "$(dirname "${targets[$i]}")") ln -s "$rel_source" "${targets[$i]}" || die -q "Unable to create link!" echo "${targets[$i]##${ROOT%/}/}" >> "${E_PATH}"/active.links done # Link modules to /usr/lib{,32,64}/ local x for x in $(list_libdirs) ; do if [[ -d ${B_PATH}/${x}/postgresql-${SLOT}/${x} ]] ; then # 'linker' function doesn't work for linking directories. # Default lib path - create a relative link ln -s "postgresql-${SLOT}/${x}" "${B_PATH}/${x}/postgresql" echo "${B_PATH##${ROOT%/}/}/${x}/postgresql" >> \ "${E_PATH}"/active.links # Linker works for files linker "${B_PATH}/${x}/postgresql-${SLOT}/${x}/" \ "-name lib*" "${B_PATH}/${x}" fi done # Link binaries to /usr/bin/ linker "${B_PATH}/$(lib_dir)/postgresql-${SLOT}/bin/" \ "-type f" "${B_PATH}/bin" # Default share path - use a relative link here by just specifying the # base name ln -s "postgresql-${SLOT}" "${B_PATH}/share/postgresql" echo "${B_PATH##${ROOT%/}/}/share/postgresql" >> "${E_PATH}/active.links" echo ${SLOT} > "${E_PATH}/active" echo "done." echo "Setting ${SLOT} as default was successful!" } ### 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." echo "Setting a new slot as the default." do_update else echo "Inactive slot selected. No work to do." fi } ### Reset Action ### describe_reset() { echo "Recreate symbolic links for currently active slot." } do_reset() { local SLOT=$(active_slot) [[ ${SLOT} = "(none)" ]] && die -q "No active slot to reset." do_unset ${SLOT} do_set ${SLOT} } ### Update Action ### describe_update() { echo "Refreshes all symbolic links managed by this module" } do_update() { local slot=$(active_slot) # Check for files managed by postgresql.eselect before 1.0 if [[ -h ${E_PATH}/active ]] ; then slot="$(basename $(canonicalise ${E_PATH}/active)))" rm -f "${E_PATH}/active" fi # Remove service file outright. [[ -h ${E_PATH}/service ]] && rm -f "${E_PATH}/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 local sym_links 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[@]} =~ ${slot} ]] ; then do_set ${slot} 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 $(list_libdirs) ; do [[ -h ${B_PATH}/${x}/postgresql ]] && \ ldpath+="${B_PATH}/${x}/postgresql:" done ldpath="${ldpath%:}" local manpath="${B_PATH}/share/postgresql/man/" while [[ $[--index] -gt -1 ]] ; do local curslot="${slots[$index]}" echo -n "Refreshing symbolic links for ${curslot} applications (like " echo -n "/usr/bin/psql${curslot//.})..." for x in $(list_libdirs) ; do local lib_path="${B_PATH}/${x}/postgresql-${curslot}/${x}/" [[ -d ${lib_path} ]] && ldpath+=":${lib_path}" done local tmp_manpath="${B_PATH}/share/postgresql-${curslot}/man/" [[ -d ${tmp_manpath} ]] && manpath+=":${tmp_manpath}" linker "${B_PATH}/$(lib_dir)/postgresql-${curslot}/bin/" \ "-type f" "${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 }