aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Lecher <jlec@gentoo.org>2016-12-10 11:50:41 +0100
committerJustin Lecher <jlec@gentoo.org>2016-12-10 11:50:41 +0100
commite6c2d58871a6a2270cef983c00fcb9301f88f08a (patch)
tree08096e05a55b20b8684e61169f3c680153e7c0a7 /app-admin/eselect/files/eselect-1.4.8-alternatives.patch
parentsci-libs/gsl: Version Bump (diff)
downloadsci-e6c2d58871a6a2270cef983c00fcb9301f88f08a.tar.gz
sci-e6c2d58871a6a2270cef983c00fcb9301f88f08a.tar.bz2
sci-e6c2d58871a6a2270cef983c00fcb9301f88f08a.zip
app-admin/eselect: Version Bump
Package-Manager: portage-2.3.3 Signed-off-by: Justin Lecher <jlec@gentoo.org>
Diffstat (limited to 'app-admin/eselect/files/eselect-1.4.8-alternatives.patch')
-rw-r--r--app-admin/eselect/files/eselect-1.4.8-alternatives.patch1603
1 files changed, 1603 insertions, 0 deletions
diff --git a/app-admin/eselect/files/eselect-1.4.8-alternatives.patch b/app-admin/eselect/files/eselect-1.4.8-alternatives.patch
new file mode 100644
index 000000000..1d541722c
--- /dev/null
+++ b/app-admin/eselect/files/eselect-1.4.8-alternatives.patch
@@ -0,0 +1,1603 @@
+ bin/Makefile.am | 1 +
+ bin/eselect.in | 150 +++++++++++-
+ libs/Makefile.am | 7 +-
+ libs/alternatives-common.bash.in | 510 +++++++++++++++++++++++++++++++++++++++
+ libs/alternatives.bash.in | 316 ++++++++++++++++++++++++
+ modules/Makefile.am | 1 +
+ modules/alternatives.eselect | 178 ++++++++++++++
+ modules/modules.eselect | 288 ++++++++++++++--------
+ 8 files changed, 1343 insertions(+), 108 deletions(-)
+
+diff --git a/bin/Makefile.am b/bin/Makefile.am
+index 20902c1..ad08867 100644
+--- a/bin/Makefile.am
++++ b/bin/Makefile.am
+@@ -4,6 +4,7 @@ EXTRA_DIST = eselect.in
+ dosed = @SED@ -e 's%\@BASH\@%$(BASH)%g' \
+ -e 's%\@DATADIR\@%$(datadir)%g' \
+ -e 's%\@EPREFIX\@%$(EPREFIX)%g' \
++ -e 's%\@LIBEXECDIR\@%$(datadir)%g' \
+ -e 's%\@VERSION\@%$(VERSION)$(EXTRAVERSION)%g'
+
+ % : %.in
+diff --git a/bin/eselect.in b/bin/eselect.in
+index 934a10a..5242ed3 100755
+--- a/bin/eselect.in
++++ b/bin/eselect.in
+@@ -22,10 +22,18 @@ ESELECT_DATA_PATH="@DATADIR@/eselect"
+ # Where are modules installed by default?
+ ESELECT_DEFAULT_MODULES_PATH="${ESELECT_DATA_PATH}/modules"
+
++# Where are auto-generated modules placed? (e.g. from alternatives-2.eclass)
++ESELECT_AUTO_GENERATED_MODULES_PATH="${ESELECT_DEFAULT_MODULES_PATH}/auto"
++
++# Where the users store their modules
++ESELECT_USER_MODULES_PATH="${ROOT}${HOME}/.eselect/modules"
++
+ # Look in these places for modules
+-ESELECT_MODULES_PATH=( \
+- "${HOME}/.eselect/modules" \
+- "${ESELECT_DEFAULT_MODULES_PATH}" )
++ESELECT_MODULES_PATH=(
++ "${ESELECT_USER_MODULES_PATH}}"
++ "${ESELECT_DEFAULT_MODULES_PATH}"
++ "${ESELECT_AUTO_GENERATED_MODULES_PATH}"
++)
+
+ # Look in this place for libraries
+ ESELECT_CORE_PATH="${ESELECT_DATA_PATH}/libs"
+@@ -64,12 +72,27 @@ fi
+ # Load core functions
+ source "${ESELECT_CORE_PATH}/core.bash" || exit 255
+ # Load necessary functions for the main script
+-inherit manip output path-manipulation tests
++inherit manip output path-manipulation tests config
+
+ # Sneaky trick to make die in subshells work. If you don't get
+ # it, don't ask...
+ trap 'echo "exiting" >&2; exit 250' 15
+
++# es_find_module foo
++# Find and echo the filename of the foo module. If there's no foo module,
++# die.
++es_find_module() {
++ local modname="$1" modpath="" modfile=""
++ [[ -z ${modname} ]] && die "Usage: ${FUNCNAME} <module>"
++ for modpath in "${ESELECT_MODULES_PATH[@]}" ; do
++ [[ -f ${modpath}/${modname}.eselect ]] && break
++ done
++
++ modfile="${modpath}/${modname}.eselect"
++ [[ -r ${modfile} ]] || die -q "Can't load module ${modname}"
++ echo ${modfile}
++}
++
+ # es_do_usage
+ # Display eselect usage
+ es_do_usage() {
+@@ -81,14 +104,10 @@ es_do_usage() {
+ es_do_help() {
+ es_do_usage
+ echo
+- # display all recognized global options
+- write_list_start "Global options:"
+- write_kv_list_entry "--brief" "Make output shorter"
+- write_kv_list_entry "--colour=<yes|no|auto>" \
+- "Enable or disable colour output (default 'auto')"
++ es_do_list-options
+ echo
+ # display all available eselect modules
+- do_action modules list
++ es_do_list-modules
+ }
+
+ # es_do_version
+@@ -100,6 +119,114 @@ es_do_version() {
+ echo "Distributed under the terms of the GNU GPL version 2 or later."
+ }
+
++# es_do_list-options
++# Display all recognized global options
++es_do_list-options() {
++ write_list_start "Global options:"
++ write_kv_list_entry "--brief" "Make output shorter"
++ write_kv_list_entry "--colour=<yes|no|auto>" "Enable or disable colour output (default 'auto')"
++ write_kv_list_entry "--debug" "Debug eselect (enable set -x)"
++}
++
++# es_do_list-modules
++# Display all available eselect modules DEPRECATED
++es_do_list-modules() {
++ do_action modules list $@
++}
++
++### print-* actions, for use with bash_completion and zsh-completion ###
++
++# es_do_print-modules
++#
++# Display all availble eselect modules in a way that's useful to bash
++# completion / zsh completion
++es_do_print-modules() {
++ local ret=1 path module group groupname want_descriptions
++
++ while [[ -n $@ ]]; do
++ case "${1}" in
++ --descriptions)
++ want_descriptions='yes' ;;
++ --group)
++ groupname=${2}
++ [[ -z "$groupname" ]] && die -q "Required option (group name) missing."
++ shift ;;
++ esac
++ shift
++ done
++
++ if [[ ${groupname} == Built-in || -z ${groupname} ]]; then
++ for module in help usage version print-{modules,actions,options}; do
++ echo "${module}"
++ done
++ [[ ${groupname} == Built-in ]] && return 0
++ fi
++
++ # TODO: factor this out in modules.eselect's do_list()
++ for path in "${ESELECT_MODULES_PATH[@]}" ; do
++ [[ -d "${path}" ]] || continue
++ for file in "${path}"/*.eselect ; do
++ [[ -f "${file}" ]] || continue
++ if [[ -n "${groupname}" ]]; then
++ group=$(load_config "${file}" ESELECT_MODULE_GROUP)
++ [[ "${groupname}" == "${group}" ||
++ ( "${groupname}" == Extra && -z "${group}" ) ]] || continue
++ fi
++ module="${file##*/}"
++ module="${module%%.eselect}"
++ echo "${module}${want_descriptions:+:$(load_config "${file}" DESCRIPTION)}"
++ ret=0
++ done
++ done
++ return $ret
++}
++
++# es_do_print-actions
++#
++# Display all available actions for the given module.
++es_do_print-actions() {
++ local modfile="$(es_find_module "${1}")" actions action want_descriptions
++ [[ "${2}" == "--descriptions" ]] && want_descriptions='yes'
++ (
++ source "${modfile}" 2>/dev/null \
++ || die "Couldn't source ${modfile}"
++ actions=( $(declare -F \
++ | sed -n -e 's/^declare\s\+-f\s\+do_//p' \
++ | egrep -v '^(action|help|usage|version)$' \
++ | sort ) )
++ for action in "${actions[@]}" ; do
++ echo "${action}${want_descriptions:+:$(describe_${action})}"
++ done
++ )
++}
++
++# es_do_print-options
++#
++# Display all available options for the given module and action
++es_do_print-options() {
++ local modfile action want_descriptions
++
++ [[ "${1}" == "--descriptions" ]] && want_descriptions='yes' && shift
++
++ if [[ -z ${1} ]]; then
++ echo "--debug${want_descriptions:+:Debug eselect (enable set -x)}"
++ echo "--no-color${want_descriptions:+:Disable coloured output}"
++ echo "--no-colour${want_descriptions:+:Disable coloured output}"
++ elif [[ -n ${2} ]]; then
++ modfile="$(es_find_module "${1}")"
++ action=${2}
++ shift 2
++ (
++ source "${modfile}" 2>/dev/null \
++ || die "Couldn't source ${modfile}"
++ is_function options_${action} || return 1
++ options_${action} ${want_descriptions:+--descriptions} "$@" || return 2
++ )
++ else
++ die "Usage: ${FUNCNAME} [--descriptions] [<module> <action>]"
++ fi
++}
++
+ ### main code ###
+
+ # figure out what the action is. we need to know whether we're
+@@ -141,6 +268,9 @@ while [[ ${1##--} != "$1" ]]; do
+ *) die -q "Invalid argument for ${1%%=*} option" ;;
+ esac
+ ;;
++ debug)
++ set -x
++ ;;
+ help|version)
+ [[ -z ${action} ]] || die -q "Too many parameters"
+ action=${1##--}
+diff --git a/libs/Makefile.am b/libs/Makefile.am
+index 027ef73..a5fe373 100644
+--- a/libs/Makefile.am
++++ b/libs/Makefile.am
+@@ -1,6 +1,8 @@
+ eselectlibsdir = $(datadir)/$(PACKAGE_NAME)/libs/
+
+ eselectlibs_DATA = \
++ alternatives.bash \
++ alternatives-common.bash \
+ config.bash \
+ core.bash \
+ default.eselect \
+@@ -14,6 +16,8 @@ eselectlibs_DATA = \
+ tests.bash
+
+ EXTRA_DIST = \
++ alternatives.bash.in \
++ alternatives-common.bash.in \
+ config.bash.in \
+ core.bash.in \
+ default.eselect.in \
+@@ -30,7 +34,8 @@ dosed = @SED@ \
+ -e 's%\@SED\@%@SED@%g' \
+ -e 's%\@PORTAGEQ\@%@PORTAGEQ@%g' \
+ -e 's%\@ENV_UPDATE\@%@ENV_UPDATE@%g' \
+- -e 's%\@CANONICALISE\@%@CANONICALISE@%g'
++ -e 's%\@CANONICALISE\@%@CANONICALISE@%g' \
++ -e 's%\@sysconfdir\@%@sysconfdir@%g'
+
+ %.bash : %.bash.in
+ @$(dosed) $< > $@
+diff --git a/libs/alternatives-common.bash.in b/libs/alternatives-common.bash.in
+new file mode 100644
+index 0000000..8753b89
+--- /dev/null
++++ b/libs/alternatives-common.bash.in
+@@ -0,0 +1,510 @@
++# Copyright (c) 2005-2015 Gentoo Foundation
++# Copyright (c) 2008 Mike Kelly
++# Copyright (c) 2009-2013 David Leverton
++# Copyright (c) 2009-2014 Bo Ørsted Andresen
++#
++# This file is part of the 'eselect' tools framework.
++#
++# eselect is free software: you can redistribute it and/or modify it under the
++# terms of the GNU General Public License as published by the Free Software
++# Foundation, either version 2 of the License, or (at your option) any later
++# version.
++#
++# eselect is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
++# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License along with
++# eselect. If not, see <http://www.gnu.org/licenses/>.
++
++inherit config output path-manipulation tests
++
++: "${ALTERNATIVESDIR_ROOTLESS:=@sysconfdir@/env.d/alternatives}"
++: "${ALTERNATIVESDIR_ROOT:=${ROOT%/}}"
++ALTERNATIVESDIR="${ALTERNATIVESDIR_ROOT}${ALTERNATIVESDIR_ROOTLESS}"
++
++get_current_provider() {
++ local dieprefix="Could not determine current provider for ${ALTERNATIVE}"
++ if [[ -L ${ALTERNATIVESDIR}/${ALTERNATIVE}/_current ]]; then
++ local provider=$(readlink "${ALTERNATIVESDIR}/${ALTERNATIVE}/_current" || die "${dieprefix}: readlink ${symlink} failed")
++ [[ ${provider} == */* ]] && die "${dieprefix}: malformed target for ${symlink}"
++
++ if [[ -L ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider} ||
++ ( -e ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider} && ! -d ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider} ) ]]; then
++ die "${dieprefix}: ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider} is not a directory"
++ fi
++
++ echo "${provider}"
++
++ elif [[ -e ${ALTERNATIVESDIR}/${ALTERNATIVE}/_current ]]; then
++ die "${dieprefix}: ${ALTERNATIVESDIR}/${ALTERNATIVE}/_current is not a symlink"
++ fi
++}
++
++compare_importance() {
++ local IFS=.
++ local a=( ${1} ) b=( ${2} )
++ local -i i=0
++ while (( i<${#a[@]} && i<${#b[@]} )); do
++ if (( a[i]<b[i] )); then
++ return 0
++ elif (( a[i]>b[i] )); then
++ return 1
++ fi
++ i+=1
++ done
++ (( i<${#b[@]} ))
++}
++
++sort_providers() {
++ local begin=${1:-0}
++ local count=${2:-${#providers[@]}}
++ [[ ${count} -le 1 ]] && return 0
++ sort_providers ${begin} $((count/2))
++ sort_providers $((begin+count/2)) $((count-count/2))
++ local left=( "${providers[@]:begin:count/2}" )
++ local right=( "${providers[@]:begin+count/2:count-count/2}" )
++ local -i x i=0 j=0
++ for (( x=begin; x<begin+count; ++x )); do
++ if (( j>=${#right[@]} )) || { (( i<${#left[@]} )) && compare_importance "${left[i]%%:*}" "${right[j]%%:*}"; }; then
++ providers[x]=${left[i++]}
++ else
++ providers[x]=${right[j++]}
++ fi
++ done
++}
++
++get_providers() {
++ local p= importance providers=()
++ for p in "${ALTERNATIVESDIR}/${ALTERNATIVE}"/* ; do
++ [[ -d ${p} && ! -L ${p} ]] || continue
++ p=${p##*/}
++
++ [[ -e "${ALTERNATIVESDIR}/${ALTERNATIVE}/${p}/_importance" ]] && \
++ importance=$(< "${ALTERNATIVESDIR}/${ALTERNATIVE}/${p}/_importance")
++ importance=${importance:-0}
++ [[ "${importance}" =~ ^[0123456789]+(\.[0123456789]+)*$ ]] || die "_importance (${importance}) for ${p} is not a dot-separated list of integers"
++
++ providers+=( "${importance}:${p}" )
++ done
++
++ sort_providers
++ for (( p=${#providers[@]}-1 ; p>=0 ; --p )); do
++ echo "${providers[p]#*:}"
++ done
++}
++
++has_provider() {
++ local provider=${1} item providers=( $(get_providers) )
++ for item in ${providers[@]}; do
++ [[ ${item} == ${provider} ]] && return 0
++ done
++ return 1
++}
++
++_options_parameters() {
++ [[ -n ${2} && ${2} != --descriptions ]] && die -q "Unrecognised option ${2}"
++ local describe_func=describe_${1#options_}_options descriptions=${2} opt options oldifs=$IFS
++ if is_function ${describe_func}; then
++ IFS=$'\n'
++ options=( $(${describe_func}) )
++ IFS=$oldifs
++ for opt in "${options[@]}"; do
++ [[ ${opt} == --* ]] || continue
++ if [[ -n ${descriptions} ]]; then
++ echo "${opt/ : /:}"
++ else
++ echo "${opt%% : *}"
++ fi
++ done
++ fi
++}
++
++### set action stub ###
++
++# not available in "eselect alternatives", but needed by do_update
++
++alternatives_do_set() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++
++ local force provider providers
++ if [[ ${1} == --force ]]; then
++ force=yes
++ shift
++ fi
++ local idx=${1}
++ if [[ ${1} == +(-|+|[[:digit:]]) ]]; then
++ idx=${1#+(-|+)}
++ providers=( $(get_providers) )
++ (( ${idx} <= ${#providers[@]} )) || die -q "The given provider with index (${idx}) does not exist"
++ provider=${providers[${idx}-1]}
++ else
++ provider="${1}"
++ fi
++ [[ -z "${provider}" ]] && die -q "Missing required parameter 'provider'"
++ local dieprefix="Could not set provider ${provider} for alternative ${ALTERNATIVE}"
++
++ if [[ ! -d ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider} ]] ; then
++ if is_number ${provider} ; then
++ providers=( $(get_providers) )
++ [[ -n ${providers[${idx}-1]} ]] && \
++ die -q "The given provider (${provider}) does not exist"
++ fi
++ die -q "The given provider (${provider}) does not exist"
++ fi
++
++ local symlink newsymlinks=() oldsymlinks=()
++
++ while read -r -d '' symlink; do
++ local nicesymlink=${symlink#.}
++ nicesymlink=${nicesymlink//+(\/)/\/}
++ [[ ${nicesymlink} == /* ]] || die "${dieprefix}: bad symlink ${symlink}?"
++ [[ ${nicesymlink} == */ ]] && die "${dieprefix}: bad symlink ${symlink}?"
++
++ newsymlinks+=( "${nicesymlink}" )
++ done < <(
++ cd "${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider}" || die "${dieprefix}: cd failed"
++ find . -type l -print0 | LC_ALL=C sort -r -u -z)
++ [[ ${#newsymlinks[@]} -gt 0 ]] || die "${dieprefix}: does not provide any symlinks?"
++
++ if [[ -f ${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list ]]; then
++ while read -r -d '' symlink; do
++ local nicesymlink=${symlink//+(\/)/\/}
++ [[ ${nicesymlink} == /* ]] || die "${dieprefix}: old provider ${oldcur} provides bad symlink ${symlink}?"
++ [[ ${nicesymlink} == */ ]] && die "${dieprefix}: old provider ${oldcur} provides bad symlink ${symlink}?"
++
++ oldsymlinks+=( "${nicesymlink}" )
++ done < <(LC_ALL=C sort -r -u -z "${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list")
++ [[ ${#oldsymlinks[@]} -gt 0 ]] || die "${dieprefix}: old provider ${oldcur} does not provide any symlinks?"
++
++ elif [[ -L ${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list || -e ${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list ]]; then
++ die "${dieprefix}: ${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list is not a file"
++ fi
++
++ local pass errors=
++ for pass in check perform; do
++ local -i new_i=0 old_i=0
++ while [[ -n ${newsymlinks[new_i]} || -n ${oldsymlinks[old_i]} ]]; do
++
++ if ( LC_ALL=C; [[ ${newsymlinks[new_i]} < ${oldsymlinks[old_i]} ]] ); then
++ if [[ ${pass} == check ]]; then
++ if [[ -L ${EROOT%/}${oldsymlinks[old_i]} ]]; then
++ :
++ elif [[ -d ${EROOT%/}${oldsymlinks[old_i]} ]]; then
++ write_error_msg "Can't remove ${EROOT%/}${oldsymlinks[old_i]}: is a directory${force:+ which is a fatal error that cannot be ignored by --force}"
++ errors=yes
++ elif [[ -e ${EROOT%/}${oldsymlinks[old_i]} ]]; then
++ if [[ -n ${force} ]]; then
++ write_warning_msg "Removing ${EROOT%/}${oldsymlinks[old_i]} due to --force: is not a symlink"
++ else
++ write_error_msg "Refusing to remove ${EROOT%/}${oldsymlinks[old_i]}: is not a symlink (use --force to override)"
++ errors=yes
++ fi
++ fi
++
++ elif [[ ${pass} == perform ]]; then
++ rm -f "${EROOT%/}${oldsymlinks[old_i]}" || die "${dieprefix}: rm failed"
++ else
++ die "${dieprefix}: unknown \${pass} ${pass}???"
++ fi
++
++ old_i+=1
++
++ else
++ local target=${ALTERNATIVESDIR_ROOTLESS#${EPREFIX}/}/${ALTERNATIVE}/_current${newsymlinks[new_i]} dir=${newsymlinks[new_i]%/*}
++ while [[ -n ${dir} ]]; do
++ target=../${target}
++ dir=${dir%/*}
++ done
++
++ if [[ ${pass} == check ]]; then
++ if [[ -L ${EROOT%/}${newsymlinks[new_i]} ]]; then
++ :
++ elif [[ -d ${EROOT%/}${newsymlinks[new_i]} ]]; then
++ write_error_msg "Can't overwrite ${EROOT%/}${newsymlinks[new_i]}: is a directory${force:+ which is a fatal error that cannot be ignored by --force}"
++ errors=yes
++ elif [[ -e ${EROOT%/}${newsymlinks[new_i]} ]]; then
++ if [[ -n ${force} ]]; then
++ write_warning_msg "Overwriting ${EROOT%/}${newsymlinks[new_i]} due to --force: is not a symlink"
++ else
++ write_error_msg "Refusing to overwrite ${EROOT%/}${newsymlinks[new_i]}: is not a symlink (use --force to override)"
++ errors=yes
++ fi
++ fi
++
++ elif [[ ${pass} == perform ]]; then
++ mkdir -p "${EROOT%/}${newsymlinks[new_i]%/*}" || die "${dieprefix}: mkdir -p failed"
++ ln -snf "${target#/}" "${EROOT%/}${newsymlinks[new_i]}" || die "${dieprefix}: ln -snf failed"
++ else
++ die "${dieprefix}: unknown \${pass} ${pass}???"
++ fi
++
++ [[ ${newsymlinks[new_i]} == ${oldsymlinks[old_i]} ]] && old_i+=1
++ new_i+=1
++ fi
++ done
++
++ [[ -n ${errors} ]] && die "${dieprefix}: see previous errors"
++ done
++
++ local oldcur="$(get_current_provider)"
++ ln -snf "${provider}" "${ALTERNATIVESDIR}/${ALTERNATIVE}/_current" || die "${dieprefix}: ln -snf failed"
++
++ : >"${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list" || die "${dieprefix}: emptying/creating _current_list failed"
++ for symlink in "${newsymlinks[@]}"; do
++ echo -n -e "${symlink}\\0" >>"${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list" || die "${dieprefix}: appending ${symlink} to _current_list failed"
++ done
++ return 0
++}
++
++### add action ###
++alternatives_describe_add() {
++ echo "Add provider to selected alternative"
++}
++
++alternatives_describe_add_parameters() {
++ echo "<provider> <importance> <source> <target> [<source> <target> [...]]"
++}
++
++alternatives_describe_add_options() {
++ echo "<provider> : the name of the alternative provider"
++ echo "<importance> : interger value, representing the importance of the provider"
++ echo "<source> : source of the symlink"
++ echo "<target> : destination for the symlink"
++}
++
++alternatives_do_add() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++
++ (( $# >= 4 )) && (( ($#-2)%2 == 0)) || \
++ die "exactly 3+N*2 arguments where N>=1 required"
++ local provider=${1}
++ local importance=${2}
++ shift 2
++ local index src target ret=0
++ local provider_dir="${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider}"
++
++ # Creating base dir
++ if [[ ! -e "${provider_dir}" ]]; then
++ mkdir -p "${provider_dir}" || die "Failed to create ${provider_dir}"
++ elif [[ ! -d "${provider_dir}" ]]; then
++ die "${provider_dir} exists but is a file"
++ else
++ die "${provider_dir} already present. You need to remove it before adding it again"
++ fi
++
++ # Make sure importance is a signed integer
++ if [[ -n ${importance} ]] && ! [[ ${importance} =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
++ die "Invalid importance (${importance}) detected"
++ else
++ # Setting importance
++ echo ${importance} > "${provider_dir}/_importance"
++ fi
++
++ # Process source-target pairs
++ while (( $# >= 2 )); do
++ src=${1//+(\/)/\/}; target=${2//+(\/)/\/}
++ if [[ ${src} != /* ]]; then
++ die "Source path must be absolute, but got ${src}"
++ else
++ local reltarget= dir=${provider_dir#${ALTERNATIVESDIR_ROOT}${EPREFIX}}${src%/*}
++ while [[ -n ${dir} ]]; do
++ reltarget+=../
++ dir=${dir%/*}
++ done
++
++ reltarget=${reltarget%/}
++ [[ ${target} == /* ]] || reltarget+=${src%/*}/
++ reltarget+=${target}
++ mkdir -p "${provider_dir}${src%/*}" || die "Failed to create ${provider_dir}${src%/*}"
++ ln -sf "${reltarget}" "${provider_dir}${src}" || die "Failed to create symlink"
++ # 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}
++# if [[ -e ${ED}${fulltarget} || -L ${ED}${fulltarget} ]]; then
++# die "${src} defined as provider for ${fulltarget}, but both already exist in \${ED}"
++# else
++# mv "${ED}${src}" "${ED}${fulltarget}" || die
++# fi
++# fi
++ fi
++ shift 2
++ done
++}
++
++alternatives_options_add() {
++ _options_parameters ${FUNCNAME#alternatives_} "$@"
++}
++
++### remove action ###
++
++alternatives_describe_remove() {
++ echo "Remove a provider for selected alternative"
++}
++
++alternatives_describe_remove_parameters() {
++ echo "<provider>"
++}
++
++alternatives_describe_remove_options() {
++ echo "<provider> : the name of the alternative provider to be removed"
++}
++
++alternatives_do_remove() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++
++ if [[ -d "${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider}" ]]; then
++ rm -r "${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider}" || \
++ die "Failed to remove '${provider}' for '${ALTERNATIVE}'"
++ else
++ einfo "'${provider}' is not a provider for '${ALTERNATIVE}'"
++ fi
++}
++
++alternatives_options_remove() {
++ _options_parameters ${FUNCNAME#alternatives_} "$@"
++}
++
++### update action ###
++
++# available in both "eselect alternatives" and individual modules
++
++alternatives_describe_update() {
++ echo "Set a default provider if no valid one currently exists"
++}
++
++alternatives_describe_update_parameters() {
++ echo "[--best] [--ignore] <provider>"
++}
++
++alternatives_describe_update_options() {
++ echo "--best : update to the best provider even if one is already selected"
++ echo "--ignore : update to any valid provider EXCEPT the specified provider"
++ echo "<provider> : the name of the provider to use"
++}
++
++alternatives_do_update() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++
++ local p cur=$(get_current_provider) providers=( $(get_providers) ) best ignore
++ if [[ "--best" == ${1} ]] ; then
++ shift
++ best=1
++ fi
++ if [[ "--ignore" == ${1} ]] ; then
++ # Try everything except setting the provider to the given
++ # one. So, if it isn't the given one, we end up doing
++ # nothing. Bug #128
++ shift
++ ignore=${1}
++ fi
++ [[ -n ${best} && -n ${1} && -z ${ignore} ]] && die -q "Cannot specify both --best and a provider"
++
++ if [[ -n ${best} ]] ; then
++ # set best provider
++ : # fall through to "switch to first available" loop below
++ elif [[ $# == "0" ]] && [[ -z ${cur} ]]; then
++ # if nothing is specified
++ : # fall through to "switch to first available" loop below
++ elif [[ ${cur} == ${1} && -z ${ignore} ]]; then
++ # if current provider was just updated, reselect it since it could have changed
++ alternatives_do_set "${cur}" && return 0
++ elif [[ -n ${cur} && ${cur} != ${ignore} ]] ; then
++ # verify existing provider's symlinks
++ local p= bad=0
++ while read -r -d '' p ; do
++ [[ -L "${EROOT%/}${p}" && -e "${EROOT%/}${p}" ]] || (( bad++ ))
++ done < "${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list"
++
++ [[ "${bad}" -eq 0 ]] && return 0
++ # fix existing provider if possible
++ has "${cur}" "${providers[@]}" && alternatives_do_set "${cur}" && return 0
++ elif has "${1}" "${providers[@]}" && [[ -z ${ignore} ]] ; then
++ # switch to new provider if none was set before or it can't be fixed
++ alternatives_do_set "${1}" && return 0
++ fi
++
++ # if no valid provider has been selected switch to first available, valid
++ # provider, sorted according to importance
++ for p in "${providers[@]}"; do
++ [[ ${ignore} != ${p} ]] && alternatives_do_set "${p}" && return 0
++ done
++
++ # if a provider is set but no providers are available anymore cleanup
++ cur=$(get_current_provider)
++ if [[ -n ${cur} ]]; then
++ alternatives_do_unset "${cur}" && return 2
++ fi
++ # if no provider is set and none are available that are not ignored, return 2 for cleanup
++ [[ -z ${providers[@]} || ${providers[@]} == ${ignore} ]] && return 2
++
++ # we tried everything to select a valid provider, but failed
++ return 1
++}
++
++alternatives_options_update() {
++ _options_parameters ${FUNCNAME#alternatives_} "$@"
++ if [[ -n ${ALTERNATIVE} ]]; then
++ get_providers
++ else
++ for alt in ${ALTERNATIVESDIR_ROOTLESS}/_*/*/_importance; do
++ echo ${alt} | cut -d/ -f5
++ done | sort -u
++ fi
++}
++
++### unset action stub ###
++
++# not available in "eselect alternatives", but needed by do_update
++
++alternatives_do_unset() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++
++ local force=
++ if [[ ${1} == --force ]]; then
++ force=yes
++ shift
++ fi
++
++ local cur="$(get_current_provider)" p=
++ [[ -n "${cur}" ]] || die -q "Nothing to unset"
++ local dieprefix="Could not unset provider for ${ALTERNATIVE}"
++
++ local one=false symlink pass errors=
++ for pass in check perform; do
++ while read -r -d '' symlink; do
++ one=true
++ if [[ ${pass} == check ]]; then
++ if [[ -L ${EROOT%/}${symlink} ]]; then
++ :
++ elif [[ -d ${EROOT%/}${symlink} ]]; then
++ write_error_msg "Can't remove ${EROOT%/}${symlink}: is a directory${force:+ which is a fatal error that cannot be ignored by --force}"
++ errors=yes
++ elif [[ -e ${EROOT%/}${symlink} ]]; then
++ if [[ -n ${force} ]]; then
++ write_warning_msg "Removing ${EROOT%/}${symlink} due to --force: is not a symlink"
++ else
++ write_error_msg "Refusing to remove ${EROOT%/}${symlink}: is not a symlink (use --force to override)"
++ errors=yes
++ fi
++ fi
++
++ elif [[ ${pass} == perform ]]; then
++ rm -f "${EROOT%/}${symlink}" || die "${dieprefix}: rm failed"
++ else
++ die "${dieprefix}: unknown \${pass} ${pass}???"
++ fi
++ done <"${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list"
++
++ [[ -n ${errors} ]] && die "${dieprefix}: see previous errors"
++ done
++
++ ${one} || die "${dieprefix}: does not provide any symlinks?"
++
++ rm "${ALTERNATIVESDIR}/${ALTERNATIVE}"/{_current,_current_list} || die "${dieprefix}: rm failed"
++}
++
++# vim: set ft=eselect sw=4 sts=4 ts=4 et tw=80 :
+diff --git a/libs/alternatives.bash.in b/libs/alternatives.bash.in
+new file mode 100644
+index 0000000..cf4fa36
+--- /dev/null
++++ b/libs/alternatives.bash.in
+@@ -0,0 +1,316 @@
++# Copyright (c) 2005-2015 Gentoo Foundation
++# Copyright (c) 2008 Mike Kelly
++# Copyright (c) 2009-2013 David Leverton
++# Copyright (c) 2009-2014 Bo Ørsted Andresen
++#
++# This file is part of the 'eselect' tools framework.
++#
++# eselect is free software: you can redistribute it and/or modify it under the
++# terms of the GNU General Public License as published by the Free Software
++# Foundation, either version 2 of the License, or (at your option) any later
++# version.
++#
++# eselect is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
++# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License along with
++# eselect. If not, see <http://www.gnu.org/licenses/>.
++
++inherit alternatives-common
++
++### show action ###
++describe_show() {
++ echo "Show the current provider in use for ${ALTERNATIVE}"
++}
++
++do_show() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++ local current="$(get_current_provider)"
++ if [[ -z "${current}" ]] ; then
++ echo "(none)"
++ return 2
++ fi
++ echo "${current}"
++}
++
++options_show() {
++ :
++}
++
++### list action ###
++describe_list() {
++ echo "Lists all available providers for ${ALTERNATIVE}"
++}
++
++do_list() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++ local n cur= providers=( $(get_providers) )
++ write_list_start "Available providers for ${ALTERNATIVE}:"
++
++ cur="$(get_current_provider)"
++
++ if [[ -n "${providers[@]}" ]] ; then
++ for (( n = 0 ; n < ${#providers[@]} ; ++n )) ; do
++ [[ ${cur} == "${providers[${n}]}" ]] && \
++ providers[${n}]="${providers[${n}]} $(highlight '*')"
++ done
++ write_numbered_list "${providers[@]}"
++ else
++ write_kv_list_entry "(none found)" ""
++ fi
++}
++
++options_list() {
++ :
++}
++
++### files action ###
++describe_files() {
++ echo "Lists symlinks provided by the currently selected provider"
++}
++
++do_files() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++
++ local cur="$(get_current_provider)" p=
++ [[ -n "${cur}" ]] || die -q "No selected provider, hence no symlinks provided"
++ local dieprefix="Could not list symlinks provided for ${ALTERNATIVE}"
++
++ local errors symlink rootsymlink
++ while read -r -d '' symlink; do
++ rootsymlink="${EROOT%/}${symlink}"
++ rootsymlink=${rootsymlink//+(\/)/\/}
++ echo "${rootsymlink}"
++ if [[ -L ${rootsymlink} ]]; then
++ if [[ ! -e ${rootsymlink} ]]; then
++ write_error_msg "${rootsymlink} is dangling symlink"
++ errors=yes
++ fi
++ elif [[ -d ${rootsymlink} ]]; then
++ write_error_msg "${rootsymlink} is a directory"
++ errors=yes
++ elif [[ -e ${rootsymlink} ]]; then
++ write_error_msg "${rootsymlink} exists but is not a symlink"
++ errors=yes
++ else
++ write_error_msg "${rootsymlink} does not exist"
++ errors=yes
++ fi
++ done <"${ALTERNATIVESDIR}/${ALTERNATIVE}/_current_list"
++}
++
++options_files() {
++ :
++}
++
++### set action ###
++
++describe_set() {
++ echo "Sets a provider for ${ALTERNATIVE}"
++}
++
++describe_set_parameters() {
++ echo "[ --force ] <provider>"
++}
++
++describe_set_options() {
++ echo "--force : overwrite or remove existing non-symlink files (but not directories) if necessary"
++ echo "<provider> : the name of the provider to use or the index of the provider preceeded by a dash"
++}
++
++do_set() {
++ # implementation defined in alternatives-common.bash as needed by do_update
++ alternatives_do_set "$@"
++}
++
++options_set() {
++ _options_parameters $FUNCNAME "$@"
++ get_providers
++}
++
++### add action ###
++
++describe_add() {
++ alternatives_describe_add
++}
++
++describe_add_parameters() {
++ alternatives_describe_add_parameters
++}
++
++describe_add_options() {
++ alternatives_describe_add_options
++}
++
++do_add() {
++ alternatives_do_add
++
++ # make sure we have something selected
++ eselect ${provider} show > /dev/null || eselect ${provider} update --best
++}
++
++### remove action ###
++
++describe_remove() {
++ alternatives_describe_remove
++}
++
++describe_remove_parameters() {
++ alternatives_describe_remove_parameters
++}
++
++describe_remove_options() {
++ alternatives_describe_remove_options
++}
++
++do_remove() {
++ local ret
++ alternatives_do_remove
++
++# if no provider is present, remove whole alternative
++ eselect ${provider} update --best > /dev/null; ret=$?
++ case ret in
++ 0)
++ # All good
++ :;;
++ 2)
++ # No provider present anymore
++ eselect alternatives remove ${ALTERNATIVE};;
++ *)
++ write_error_msg "Failed to remove ${ALTERNATIVE}"
++ errors=yes
++ esac
++}
++
++### update action ###
++
++# all functions implemented in alternatives-common.bash as defined for
++# both "eselect alternatives" and individual modules
++
++describe_update() {
++ alternatives_describe_update
++}
++
++describe_update_parameters() {
++ alternatives_describe_update_parameters
++}
++
++describe_update_options() {
++ alternatives_describe_update_options
++}
++
++do_update() {
++ alternatives_do_update "$@"
++}
++
++options_update() {
++ alternatives_options_update
++}
++
++### unset action ###
++
++describe_unset() {
++ echo "Unset any symlinks created for the current provider for ${ALTERNATIVE}."
++}
++
++describe_unset_parameters() {
++ echo "[ --force ]"
++}
++
++describe_unset_options() {
++ echo "--force : remove existing non-symlink files (but not directories) if necessary"
++}
++
++do_unset() {
++ # implementation defined in alternatives-common.bash as needed by do_update
++ alternatives_do_unset "$@"
++}
++
++options_unset() {
++ _options_parameters $FUNCNAME "$@"
++ get_current_provider
++}
++
++### script action ###
++
++describe_script() {
++ echo "Output an evalable script fragment to set PATH, LD_LIBRARY_PATH and MANPATH to use the specified provider"
++}
++
++describe_script_parameters() {
++ echo "[--sh | --csh] [<provider>]"
++}
++
++describe_script_options() {
++ echo "--sh : use Bourne shell syntax (default)"
++ echo "--csh : use C shell syntax"
++ echo "<provider> : the provider to use or the index of the provider (if not specified, use the system default)"
++}
++
++do_script() {
++ [[ -z "${ALTERNATIVE}" ]] && die "Need to set ALTERNATIVE in the eselect module"
++ local syntax=sh provider providers
++ if [[ ${1} == --sh ]]; then
++ shift
++ elif [[ ${1} == --csh ]]; then
++ syntax=csh
++ shift
++ fi
++
++ local idx=${!}
++ if [[ ${idx} == +(-|+|[[:digit:]]) ]]; then
++ idx=${1#+(-|+)}
++ providers=( $(get_providers) )
++ (( ${idx} <= ${#providers[@]} )) || die -q "The given provider with index (${idx}) does not exist"
++ provider=${providers[${idx}-1]}
++ else
++ provider="${idx}"
++ fi
++ [[ -z "${provider}" ]] && die -q "Missing required parameter 'provider'"
++
++ if [[ ! -d ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider} ]] ; then
++ if is_number ${provider} ; then
++ providers=( $(get_providers) )
++ [[ -n ${providers[${idx}-1]} ]] && \
++ die -q "The given provider (${provider}) does not exist"
++ fi
++ die -q "The given provider (${provider}) does not exist"
++ fi
++
++ local variables=( PATH LD_LIBRARY_PATH MANPATH )
++ [[ -n ${!default_*} ]] && local ${!default_*}
++ local default_LD_LIBRARY_PATH=$(grep '^[^#]' "${EROOT%/}"/etc/ld.so.conf | tr '\n' ':')/lib:/usr/lib
++ local default_MANPATH=$(MANPATH= man -C"${EROOT%/}"/etc/man.conf -w)
++
++ local var IFS=:
++ for var in "${variables[@]}"; do
++ local defvar=default_${var} path paths=( )
++ for path in ${!var}; do
++ [[ ${path} == ${ALTERNATIVESDIR_ROOTLESS}/${ALTERNATIVE}/* ]] && continue
++ [[ -n ${provider} && -d ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider}/${path#/} ]] && paths+=( "${ALTERNATIVESDIR_ROOTLESS}/${ALTERNATIVE}/${provider}/${path#/}" )
++ paths+=( "${path}" )
++ done
++
++ [[ -n ${provider} ]] && for path in ${!defvar}; do
++ [[ -d ${ALTERNATIVESDIR}/${ALTERNATIVE}/${provider}/${path#/} ]] && paths+=( "${ALTERNATIVESDIR_ROOTLESS}/${ALTERNATIVE}/${provider}/${path#/}" )
++ done
++
++ local newval=${paths[*]}
++ if [[ ${newval} != ${!var} ]]; then
++ newval=${newval//\'/\'\\\'\'}
++ if [[ ${syntax} == sh ]]; then
++ echo "${var}='${newval}'; export ${var}"
++ else
++ echo "setenv ${var} '${newval}'"
++ fi
++ fi
++ done
++}
++
++options_script() {
++ _options_parameters $FUNCNAME "$@"
++ get_providers
++}
++
++# vim: set ft=eselect sw=4 sts=4 ts=4 et tw=80 :
+diff --git a/modules/Makefile.am b/modules/Makefile.am
+index 75ebe02..92127b6 100644
+--- a/modules/Makefile.am
++++ b/modules/Makefile.am
+@@ -1,6 +1,7 @@
+ modulesdir=$(datadir)/$(PACKAGE_NAME)/modules/
+
+ modules_DATA = \
++ alternatives.eselect \
+ editor.eselect \
+ env.eselect \
+ kernel.eselect \
+diff --git a/modules/alternatives.eselect b/modules/alternatives.eselect
+new file mode 100644
+index 0000000..840b9c5
+--- /dev/null
++++ b/modules/alternatives.eselect
+@@ -0,0 +1,178 @@
++# Copyright (c) 2005-2015 Gentoo Foundation
++# Copyright (c) 2008 Mike Kelly
++# Copyright (c) 2009-2013 David Leverton
++# Copyright (c) 2009-2014 Bo Ørsted Andresen
++#
++# This file is part of the 'eselect' tools framework.
++#
++# eselect is free software: you can redistribute it and/or modify it under the
++# terms of the GNU General Public License as published by the Free Software
++# Foundation, either version 2 of the License, or (at your option) any later
++# version.
++#
++# eselect is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
++# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License along with
++# eselect. If not, see <http://www.gnu.org/licenses/>.
++
++inherit alternatives-common
++
++DESCRIPTION="Maintain Alternatives symlinks"
++VERSION="20150521"
++MAINTAINER="sci@gentoo.org"
++
++show_extra_help_text() {
++ cat <<- ENDOFTEXT
++ This module is intended for internal use when a package is installed,
++ updated or removed. For alternatives for which it is likely that
++ users will need control over which provider is selected, there will be
++ a separate eselect module installed to do so.
++ ENDOFTEXT
++}
++
++# all functions implemented in alternatives-common.bash as defined for
++# both "eselect alternatives" and individual modules
++
++### update action ###
++
++describe_update() {
++ alternatives_describe_update
++}
++
++describe_update_parameters() {
++ echo "<alternative> $(alternatives_describe_update_parameters)"
++}
++
++describe_update_options() {
++ echo "<alternative> : the name of the alternative to set a provider for"
++ alternatives_describe_update_options
++}
++
++do_update() {
++ local ALTERNATIVE=$1
++ shift
++ [[ -z "${ALTERNATIVE}" ]] && die -q "Missing required parameter 'alternative'"
++ alternatives_do_update "$@"
++}
++
++options_update() {
++ alternatives_options_update
++}
++
++### create action ###
++
++describe_create() {
++ echo "Create a new alternative"
++}
++
++describe_create_parameters() {
++ echo "<alternative>"
++}
++
++describe_create_options() {
++ echo "<alternative> : the name of the alternative to create"
++}
++
++do_create() {
++ [[ $# == 1 ]] || die "Need exactly one alternative name"
++
++ local auto_dir="${ESELECT_AUTO_GENERATED_MODULES_PATH}"
++ local auto_file="${auto_dir}/${1}.eselect"
++
++ if [[ ! -e "${auto_file}" ]]; then
++ if [[ ! -e "${auto_dir}" ]]; then
++ mkdir -p "${auto_dir}" || die "Failed to create ${auto_dir}"
++ elif [[ ! -d "${auto_dir}" ]]; then
++ die "${auto_dir} exists but is a file"
++ fi
++ cat >> ${auto_file} <<- ENDOFTEXT
++ DESCRIPTION="${DESCRIPTION} for ${1}"
++ VERSION="${VERSION}"
++ MAINTAINER="${MAINTAINER}"
++ ESELECT_MODULE_GROUP="Alternatives"
++
++ ALTERNATIVE="${1}"
++
++ inherit alternatives
++ ENDOFTEXT
++ fi
++}
++
++### delete action ###
++
++describe_delete() {
++ echo "Delete an existing alternative"
++}
++
++describe_delete_parameters() {
++ echo "<alternative>"
++}
++
++describe_delete_options() {
++ echo "<alternative> : the name of the alternative to delete"
++}
++
++do_delete() {
++ [[ $# == 1 ]] || die "Need exactly one alternative name"
++
++ local auto_dir="${ESELECT_AUTO_GENERATED_MODULES_PATH}"
++ local auto_file="${auto_dir}/${1}.eselect"
++
++ if [[ -e "${auto_file}" ]]; then
++ rm "${auto_file}" || die "Failed to remove alternative: ${1}"
++ fi
++}
++
++### add action ###
++
++describe_add() {
++ alternatives_describe_add
++}
++
++describe_add_parameters() {
++ echo "<alternative> $(alternatives_describe_add_parameters)"
++}
++
++describe_add_options() {
++ echo "<alternative> : the name of the alternative to add a provider for"
++ alternatives_describe_add_options
++}
++
++do_add() {
++ local ALTERNATIVE=$1
++ shift
++ [[ -z "${ALTERNATIVE}" ]] && die -q "Missing required parameter 'alternative'"
++ alternatives_do_add "$@"
++}
++
++options_add() {
++ alternatives_options_add
++}
++
++### remove action ###
++
++describe_remove() {
++ alternatives_describe_remove
++}
++
++describe_remove_parameters() {
++ echo "<alternative> $(alternatives_describe_remove_parameters)"
++}
++
++describe_remove_options() {
++ echo "<alternative> : the name of the alternative to remove a provider from"
++ alternatives_describe_remove_options
++}
++
++do_remove() {
++ local ALTERNATIVE=$1
++ shift
++ [[ -z "${ALTERNATIVE}" ]] && die -q "Missing required parameter 'alternative'"
++ alternatives_do_remove "$@"
++}
++
++options_remove() {
++ alternatives_options_remove
++}
+diff --git a/modules/modules.eselect b/modules/modules.eselect
+index 038f630..78dcbab 100644
+--- a/modules/modules.eselect
++++ b/modules/modules.eselect
+@@ -2,7 +2,7 @@
+ # Copyright 2006-2015 Gentoo Foundation
+ # Distributed under the terms of the GNU GPL version 2 or later
+
+-inherit config
++inherit config output tests
+
+ DESCRIPTION="Query eselect modules"
+ MAINTAINER="eselect@gentoo.org"
+@@ -15,57 +15,94 @@ describe_list() {
+ echo "List all available modules"
+ }
+
+-describe_list_options() {
+- echo "--only-names : Output names of modules only"
+-}
+-
+ # List all installed modules
+ do_list() {
+- local only_names path file module name desc
+- local -a extra_modules
+-
+- if [[ ${1#--} = only-names ]]; then
+- only_names=1
+- shift
+- fi
+- [[ $# -gt 0 ]] && die -q "Too many parameters"
+-
+- for path in "${ESELECT_MODULES_PATH[@]}" ; do
+- [[ -d ${path} ]] || continue
+- for file in "${path}"/*.eselect ; do
+- [[ -f ${file} ]] || continue
+- extra_modules=( "${extra_modules[@]}" "${file}" )
+- done
+- done
+-
+- if [[ -n ${only_names} ]]; then
+- # This is mainly intended for bash completion
+- echo "help"
+- echo "usage"
+- echo "version"
+- for module in "${extra_modules[@]}" ; do
+- name=${module##*/}
+- echo "${name%%.eselect}"
+- done
+- else
+- write_list_start "Built-in modules:"
+- write_kv_list_entry "help" "Display a help message"
+- write_kv_list_entry "usage" "Display a usage message"
+- write_kv_list_entry "version" "Display version information"
+-
+- if [[ ${#extra_modules[@]} -gt 0 ]] ; then
+- echo
+- write_list_start "Extra modules:"
+- for module in "${extra_modules[@]}" ; do
+- name=${module##*/}
+- name=${name%%.eselect}
+- desc=$(ESELECT_MODULE_NAME=${name} \
+- load_config "${module}" DESCRIPTION)
+- desc=${desc:-No description available}
+- write_kv_list_entry "${name}" "${desc}"
+- done
+- fi
+- fi
++ local path file module name desc group groups Extra_modules
++
++ write_list_start "Built-in modules:"
++ write_kv_list_entry "help" "Display a help message"
++ write_kv_list_entry "usage" "Display a usage message"
++ write_kv_list_entry "version" "Display version information"
++ write_kv_list_entry "print-modules" "Print eselect modules"
++ write_kv_list_entry "print-actions" "Print actions for a given module"
++ write_kv_list_entry "print-options" "Print options for a given action"
++
++ for path in "${ESELECT_MODULES_PATH[@]}" ; do
++ [[ -d ${path} ]] || continue
++ for file in ${path}/*.eselect ; do
++ [[ -f ${file} ]] || continue
++ group=$(load_config "${file}" ESELECT_MODULE_GROUP)
++ if [[ -n ${group} ]]; then
++ has ${group} ${groups} || groups+=" ${group}"
++ declare ${group}_modules+=" ${file}"
++ else
++ Extra_modules+=" ${file}"
++ fi
++ done
++ done
++
++ for group in ${groups} Extra; do
++ local m
++ m="${group}_modules"
++ if [[ -n ${!m} ]] ; then
++ echo
++ write_list_start "${group} modules:"
++ for module in ${!m}; do
++ name=${module##*/}
++ name=${name%%.eselect}
++ desc=$(load_config "${module}" DESCRIPTION)
++ desc=${desc:-No description available}
++ write_kv_list_entry "${name}" "${desc}"
++ done
++ fi
++ done
++}
++
++### group action
++
++describe_group() {
++ echo "Lists all available modules belonging to a specified group."
++}
++
++describe_group_parameters() {
++ echo "<group>"
++}
++
++do_group() {
++ local path file groupname="$1" group module modules name desc
++ [[ -z "$groupname" ]] && die -q "Required option (group name) missing."
++
++ if [[ ${groupname} == Built-in ]]; then
++ write_list_start "Built-in modules:"
++ write_kv_list_entry "help" "Display a help message"
++ write_kv_list_entry "usage" "Display a usage message"
++ write_kv_list_entry "version" "Display version information"
++ return 0
++ fi
++
++ for path in "${ESELECT_MODULES_PATH[@]}" ; do
++ [[ -d ${path} ]] || continue
++ for file in ${path}/*.eselect ; do
++ [[ -f ${file} ]] || continue
++ group=$(load_config "${file}" ESELECT_MODULE_GROUP)
++ [[ ${groupname} == ${group} ||
++ ( ${groupname} == Extra && -z ${group} ) ]] || continue
++ modules+=" ${file}"
++ done
++ done
++
++ if [[ -n ${modules} ]] ; then
++ write_list_start "${groupname} modules:"
++ for module in ${modules}; do
++ name=${module##*/}
++ name=${name%%.eselect}
++ desc=$(load_config "${module}" DESCRIPTION)
++ desc=${desc:-No description available}
++ write_kv_list_entry "${name}" "${desc}"
++ done
++ else
++ die -q "No modules belonging to ${groupname} was found"
++ fi
+ }
+
+ ### has action
+@@ -75,56 +112,113 @@ describe_has() {
+ }
+
+ describe_has_parameters() {
+- echo "<module>"
++ echo "<module>"
+ }
+
+ do_has() {
+- [[ -z $1 ]] && die -q "Required option (module name) missing"
+- [[ $# -gt 1 ]] && die -q "Too many parameters"
+-
+- local modname=$1 modpath
+- for modpath in "${ESELECT_MODULES_PATH[@]}" ; do
+- [[ -f ${modpath}/${modname}.eselect ]] && return 0
+- done
+- return 1
++ [[ -z $1 ]] && die -q "Required option (module name) missing"
++ [[ $# -gt 1 ]] && die -q "Too many parameters"
++ local modname="$1" modpath
++ [[ -z "$modname" ]] && die -q "Required option (module name) missing."
++ for modpath in "${ESELECT_MODULES_PATH[@]}" ; do
++ [[ -f "${modpath}/${modname}.eselect" ]] && return 0
++ done
++ return 1
+ }
+
+ ### add action
+-# *** Commented out. Do we really want to have an eselect module that is
+-# *** installing other modules in a system directory? Also, this should
+-# *** go together with a "remove" action.
+-
+-# describe_add() {
+-# echo "Install the given module file somewhere that eselect can find it."
+-# echo "By default, install to \$HOME/.eselect/modules/, unless running as "
+-# echo "root. Then, install to ${ESELECT_DATA_PATH}/modules/."
+-# }
+-
+-# describe_add_parameters() {
+-# echo "<module_file>"
+-# }
+-
+-# do_add() {
+-# local local_path="${ROOT}${HOME}/.eselect/modules/" module_file
+-# local force_default=0
+-#
+-# if [[ $1 = "--force-default-location" ]] ; then
+-# force_default=1
+-# shift
+-# fi
+-# module_file=$1
+-#
+-# [[ -z ${module_file} ]] && die -q "Required option (module file) missing"
+-#
+-# # TODO: Don't install the module "somewhere", depending on write access.
+-# # Add an option to control if it goes to the user's or to the system dir.
+-# if ! cp "${module_file}" "${ESELECT_DEFAULT_MODULES_PATH}" &> /dev/null ; then
+-# [[ ${force_default} == 1 ]] \
+-# && die -q "Failed to install module file to default modules path"
+-#
+-# mkdir -p "${local_path}" \
+-# || die -q "Failed to create module install directory"
+-# cp "${module_file}" "${local_path}" \
+-# || die -q "Failed to install module file"
+-# fi
+-# }
++
++describe_add() {
++ echo "Install a module file"
++}
++
++describe_add_options() {
++ echo "--default : install as global module (default if root)"
++ echo "--user : install as user's module"
++}
++
++describe_add_parameters() {
++ echo "<module_file>"
++}
++
++do_add() {
++ local module_file module_path
++ case $1 in
++ --default)
++ module_path="${ESELECT_DEFAULT_MODULES_PATH}"
++ shift
++ ;;
++ --user)
++ module_path="${ESELECT_USER_MODULES_PATH}"
++ mkdir -p "${module_path}" || die -q "Failed to create directory ${module_path}"
++ shift
++ ;;
++ *) : ;;
++ esac
++ module_file=$1
++
++ [[ -z ${module_file} ]] && die -q "Required module file missing"
++
++ if [[ -n ${module_path} ]]; then
++ cp "${module_file}" "${module_path}" &> /dev/null || \
++ die -q "Failed to install module file to ${module_path}"
++ else
++ if ! cp "${module_file}" "${ESELECT_DEFAULT_MODULES_PATH}" &> /dev/null ; then
++ mkdir -p "${ESELECT_USER_MODULES_PATH}" \
++ || die -q "Failed to create directory ${ESELECT_USER_MODULES_PATH}"
++ cp "${module_file}" "${ESELECT_USER_MODULES_PATH}" \
++ || die -q "Failed to install module file ${module_file}"
++ fi
++ fi
++}
++
++### remove action
++
++describe_remove() {
++ echo "Remove the given module name"
++}
++
++describe_remove_options() {
++ echo "--default : remove global module (default if root)"
++ echo "--alternatives : remove generated alternatives module"
++ echo "--user : remove user module"
++}
++
++describe_remove_parameters() {
++ echo "<module>"
++}
++
++do_remove() {
++ local module_name module_path ret
++ case $1 in
++ --alternatives)
++ module_path="${ESELECT_GENERATED_MODULES_PATH}"
++ shift
++ ;;
++ --default)
++ module_path="${ESELECT_DEFAULT_MODULES_PATH}"
++ shift
++ ;;
++ --user)
++ module_path="${ESELECT_USER_MODULES_PATH}"
++ shift
++ ;;
++ *) : ;;
++ esac
++ module_name=$1
++
++ [[ -z ${module_name} ]] && die -q "Required module name missing"
++
++ if [[ -n ${module_path} ]]; then
++ rm "${module_path}/${module_name}.eselect" &> /dev/null
++ ret=$?
++ else
++ for module_path in "${ESELECT_MODULES_PATH[@]}" ; do
++ rm "${module_path}/${module_name}.eselect" &> /dev/null
++ ret=$?
++ done
++ fi
++ [[ ${ret} != 0 ]] && die -q "Failed to remove module ${module_name}"
++}
++
++# vim: set ft=eselect sw=4 sts=4 ts=4 et tw=80 :