diff options
Diffstat (limited to 'app-admin/eselect/files/eselect-1.4.9-alternatives.patch')
-rw-r--r-- | app-admin/eselect/files/eselect-1.4.9-alternatives.patch | 1603 |
1 files changed, 1603 insertions, 0 deletions
diff --git a/app-admin/eselect/files/eselect-1.4.9-alternatives.patch b/app-admin/eselect/files/eselect-1.4.9-alternatives.patch new file mode 100644 index 000000000..1d541722c --- /dev/null +++ b/app-admin/eselect/files/eselect-1.4.9-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 : |