diff --git a/Pmodules/bash b/Pmodules/bash index e5e6aa0..9f0bf8f 100644 --- a/Pmodules/bash +++ b/Pmodules/bash @@ -8,8 +8,34 @@ if [ ${BASH_VERSINFO:-0} -lt 3 ]; then return 1 fi +############################################################################ +# some sanity checks +# +if [[ ! -d ${PMODULES_ROOT} ]]; then + echo "Oops: ${PMODULES_ROOT}: Set as Pmodules root, but this is not a directory." 1>&2 + return 1 +fi +if [[ ! -d ${PMODULES_HOME} ]]; then + echo "Oops: ${PMODULES_HOME}: Set as Pmodules home, but this is not a directory." 1>&2 + return 1 +fi + ############################################################################# -# implement module comand as function +# initialize bash completion +# +if [[ -r "${PMODULES_HOME}/init/bash_completion" ]]; then + source "${PMODULES_HOME}/init/bash_completion" +fi + +############################################################################# +# legacy... +# +unset MODULE_VERSION +unset MODULE_VERSION_STACK +unset MODULESHOME + +############################################################################# +# implement module comand as shell function # module() { unset BASH_ENV @@ -56,125 +82,6 @@ module() { } export -f module -############################################################################# -# helper functions -# -std::append_path () { - local -r P="$1" - local -r d="$2" - - if ! echo ${!P} | egrep -q "(^|:)${d}($|:)" ; then - if [[ -z ${!P} ]]; then - eval $P=\"${d}\" - else - eval $P=\"${!P}:${d}\" - fi - fi -} - -# -# Replace or remove a directory in a path variable. -# -# To remove a dir: -# std::replace_path PATH -# -# To replace a dir: -# std::replace_path PATH /replacement/path -# -# Args: -# $1 name of the shell variable to set (e.g. PATH) -# $2 a grep pattern identifying the element to be removed/replaced -# $3 the replacement string (use "" for removal) -# -# Based on solution published here: -# https://stackoverflow.com/questions/273909/how-do-i-manipulate-path-elements-in-shell-scripts -# -std::replace_path () { - local -r path="$1" - local -r removepat="$2" - local -r replacestr="$3" - - local -r removestr=$(echo "${!path}" | tr ":" "\n" | grep -m 1 "^$removepat\$") - export $path="$(echo "${!path}" | tr ":" "\n" | sed "s:^${removestr}\$:${replacestr}:" | - sed '/^\s*$/d' | tr "\n" ":" | sed -e 's|^:||' -e 's|:$||')" -} - -save_env() { - local s='' - while (( $# > 0 )); do - s+="$( typeset -p $1 );" - shift - done - echo export PMODULES_ENV=$( "${PMODULES_HOME}/sbin/base64" --wrap=0 <<< "$s" ) -} - -############################################################################ -# some sanity checks -# -if [[ ! -d ${PMODULES_ROOT} ]]; then - echo "Oops: ${PMODULES_ROOT}: Set as Pmodules root, but this is not a directory." 1>&2 - return 1 -fi -if [[ ! -d ${PMODULES_HOME} ]]; then - echo "Oops: ${PMODULES_HOME}: Set as Pmodules home, but this is not a directory." 1>&2 - return 1 -fi - -############################################################################# -# setup environment -# -declare -x LOADEDMODULES='' -declare -x _LMFILES_='' -declare -x MODULEPATH='' -declare -x PMODULES_USED_GROUPS -for group in ${PMODULES_DEFAULT_GROUPS//:/ }; do - std::append_path MODULEPATH "${PMODULES_ROOT}/${group}/${PMODULES_MODULEFILES_DIR}" - std::append_path PMODULES_USED_GROUPS "${group}" -done -declare -x UsedReleases='' -for r in ${PMODULES_DEFAULT_RELEASES//:/ }; do - std::append_path UsedReleases "${r}" -done - -#eval $(save_env UsedReleases PMODULES_DEFAULT_RELEASES PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES) -unset UsedReleases -#unset PMODULES_DEFAULT_RELEASES -#unset PMODULES_DEFAULT_GROUPS -#unset PMODULES_DEFINED_RELEASES - -std::replace_path PATH "${PMODULES_HOME%/*}/.*" -std::replace_path MANPATH "${PMODULES_HOME%/*}/.*" -std::append_path PATH "${PMODULES_HOME}/bin" - -if [[ -r /etc/man.config ]]; then - declare _manconf='/etc/man.config' -elif [[ -r /etc/man.conf ]]; then - declare _manconf='/etc/man.conf' -fi -if [[ -n ${_manconf} ]]; then - while read name value rest; do - std::append_path MANPATH "${value}" - done < <(grep "^MANPATH\s" "${_manconf}") - unset _manconf -else - std::append_path MANPATH "${PMODULES_HOME}/share/man" - std::append_path MANPATH "/usr/share/man" -fi - -############################################################################# -# initialize bash completion -# -if [[ -r "${PMODULES_HOME}/init/bash_completion" ]]; then - source "${PMODULES_HOME}/init/bash_completion" -fi - -############################################################################# -# legacy... -# -unset MODULE_VERSION -unset MODULE_VERSION_STACK -unset MODULESHOME - # Local Variables: # mode: sh # sh-basic-offset: 8 diff --git a/Pmodules/libmodules.tcl b/Pmodules/libmodules.tcl index e15f31c..05d114b 100644 --- a/Pmodules/libmodules.tcl +++ b/Pmodules/libmodules.tcl @@ -28,7 +28,6 @@ proc module-addgroup { group } { global version debug "called with arg $group" - set Variant [file join {*}$::variant] set GROUP [string toupper $group] regsub -- "-" ${GROUP} "_" GROUP @@ -41,14 +40,18 @@ proc module-addgroup { group } { if { [module-info mode load] } { debug "mode is load" foreach overlay $::PmodulesOverlays { - set dir $overlay/$group/$::PmodulesModulfilesDir/$Variant + set dir [file join \ + $overlay \ + $group \ + $::PmodulesModulfilesDir \ + {*}$::variant] if { [file isdirectory $dir] } { prepend-path MODULEPATH $dir } } - prepend-path PMODULES_USED_GROUPS $group + prepend-path UsedGroups $group debug "mode=load: new MODULEPATH=$env(MODULEPATH)" - debug "mode=load: new PMODULES_USED_GROUPS=$env(PMODULES_USED_GROUPS)" + debug "mode=load: new UsedGroups=$env(UsedGroups)" } elseif { [module-info mode remove] } { set GROUP [string toupper $group] debug "remove hierarchical group '${GROUP}'" @@ -70,17 +73,25 @@ proc module-addgroup { group } { } debug "mode=remove: $env(MODULEPATH)" foreach overlay $::PmodulesOverlays { - remove-path MODULEPATH $overlay/$group/$::PmodulesModulfilesDir/$Variant + remove-path MODULEPATH [file join \ + $overlay \ + $group \ + $::PmodulesModulfilesDir \ + {*}$::variant] } debug "mode=remove: $env(PMODULES_USED_GROUPS)" - remove-path PMODULES_USED_GROUPS $group + remove-path UsedGroups $group } if { [module-info mode switch2] } { debug "mode=switch2" foreach overlay $::PmodulesOverlays { - append-path MODULEPATH $overlay/$group/$::PmodulesModulfilesDir/[module-info name] + append-path MODULEPATH [file join \ + $::PmodulesRoot \ + $group \ + $::PmodulesModulfilesDir \ + [module-info name]] } - append-path PMODULES_USED_GROUPS ${group} + append-path UsedGroups ${group} } } diff --git a/Pmodules/libstd.bash b/Pmodules/libstd.bash index 1773f17..ad7f0e6 100644 --- a/Pmodules/libstd.bash +++ b/Pmodules/libstd.bash @@ -67,16 +67,16 @@ std::get_abspath() { } std::append_path () { - local -r P=$1 - local -r d=$2 + local -r P="$1" + local -r d="$2" if ! echo ${!P} | egrep -q "(^|:)${d}($|:)" ; then - if [[ -z ${!P} ]]; then - eval $P=${d} - else - eval $P=${!P}:${d} - fi - fi + if [[ -z ${!P} ]]; then + eval $P=\"${d}\" + else + eval $P=\"${!P}:${d}\" + fi + fi } std::prepend_path () { @@ -105,6 +105,33 @@ std::remove_path() { eval ${P}="${new_path:1}" } +# +# Replace or remove a directory in a path variable. +# +# To remove a dir: +# std::replace_path PATH +# +# To replace a dir: +# std::replace_path PATH /replacement/path +# +# Args: +# $1 name of the shell variable to set (e.g. PATH) +# $2 a grep pattern identifying the element to be removed/replaced +# $3 the replacement string (use "" for removal) +# +# Based on solution published here: +# https://stackoverflow.com/questions/273909/how-do-i-manipulate-path-elements-in-shell-scripts +# +std::replace_path () { + local -r path="$1" + local -r removepat="$2" + local -r replacestr="$3" + + local -r removestr=$(echo "${!path}" | tr ":" "\n" | grep -m 1 "^$removepat\$") + export $path="$(echo "${!path}" | tr ":" "\n" | sed "s:^${removestr}\$:${replacestr}:" | + sed '/^\s*$/d' | tr "\n" ":" | sed -e 's|^:||' -e 's|:$||')" +} + # # split file name # diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 0b057f4..bf8e968 100755 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -76,7 +76,7 @@ pbuild::save_env() { pbuild::export_env ${shell} PMODULES_ENV } -trap 'pbuild::save_env ${g_shell} Overlays PMODULES_OVERLAYS GroupDepths UsedReleases UseFlags PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES PMODULES_DEFAULT_RELEASES' EXIT +trap 'pbuild::save_env ${g_shell} Overlays PMODULES_OVERLAYS GroupDepths UsedReleases UseFlags UsedGroups PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES PMODULES_DEFAULT_RELEASES' EXIT print_version() { echo " @@ -504,8 +504,7 @@ is_group () { # not yet cached or not a group local overlay='' get_overlay_of_group overlay "${group}" || return 1 - get_group_depths "${root}" "${group}" - return 0 + get_group_depths "${overlay}" "${group}" } # @@ -534,7 +533,7 @@ find_overlay () { } is_used_group() { - [[ :${PMODULES_USED_GROUPS}: =~ :$1: ]] + [[ :${UsedGroups}: =~ :$1: ]] } module_is_loaded() { @@ -1161,7 +1160,7 @@ subcommand_avail() { get_group_depth () { local -r group="$1" local -r dir="${group}/${PMODULES_MODULEFILES_DIR}" - test -d "${dir}" || return 0 + test -d "${dir}" || return 1 local tmp=$(find "${dir}" -depth -type f -o -type l 2>/dev/null| head -1) local -a tmp2=( ${tmp//\// } ) local depth=${#tmp2[@]} @@ -1233,7 +1232,7 @@ subcommand_use() { local f local r std::info "Used groups:\n" - for f in ${PMODULES_USED_GROUPS//:/ }; do + for f in ${UsedGroups//:/ }; do std::info "\t${f}\n" done std::info "\nUnused groups:\n" @@ -1283,6 +1282,9 @@ subcommand_use() { } use () { + declare -g UsedGroups + declare -g MODULEPATH + local dirs_to_add=() while (( $# > 0)); do arg="$1" @@ -1311,7 +1313,7 @@ subcommand_use() { Overlays[${overlay}]=1 PMODULES_OVERLAYS="${PMODULES_OVERLAYS}:${overlay}" get_group_depths "${!Overlays[@]}" - for group in ${PMODULES_USED_GROUPS//:/ }; do + for group in ${UsedGroups//:/ }; do local dir="${overlay}/${group}/${PMODULES_MODULEFILES_DIR}" if [[ -d "${dir}" ]]; then std::prepend_path MODULEPATH "${dir}" @@ -1324,9 +1326,9 @@ subcommand_use() { std::die 3 "%s %s: cannot add group to module path -- %s\n" \ "${CMD}" "${FUNCNAME[0]##*_}" "${arg}" fi - std::append_path PMODULES_USED_GROUPS "${arg}" + std::append_path UsedGroups "${arg}" for overlay in "${!Overlays[@]}"; do - for group in ${PMODULES_USED_GROUPS//:/ }; do + for group in ${UsedGroups//:/ }; do local dir="${overlay}/" dir+="${group}/${PMODULES_MODULEFILES_DIR}" if [[ -d "${dir}" ]]; then @@ -1346,7 +1348,7 @@ subcommand_use() { shift done - pbuild::export_env ${g_shell} MODULEPATH PMODULES_USED_GROUPS + pbuild::export_env ${g_shell} MODULEPATH UsedGroups } local opts=() @@ -1439,7 +1441,7 @@ subcommand_unuse() { std::die 3 "%s %s: cannot remove group from module path -- %s\n" \ "${CMD}" "${FUNCNAME[0]##*_}" "${arg}" fi - std::remove_path PMODULES_USED_GROUPS "${arg}" + std::remove_path UsedGroups "${arg}" dirs_to_remove+=( ${modulefiles_dir} ) elif [[ -d ${arg} ]]; then @@ -1455,8 +1457,8 @@ subcommand_unuse() { shift done - declare -gx PMODULES_USED_GROUPS - pbuild::export_env ${g_shell} PMODULES_USED_GROUPS + declare -gx UsedGroups + pbuild::export_env ${g_shell} UsedGroups [[ ${#dirs_to_remove[@]} == 0 ]] && return for dir in "${dirs_to_remove[@]}"; do subcommand_generic1 unuse "${dir}" @@ -1492,13 +1494,20 @@ reset_modulepath() { } reset_used_groups() { - PMODULES_USED_GROUPS='' + UsedGroups='' local group for group in ${PMODULES_DEFAULT_GROUPS}; do - std::append_path PMODULES_USED_GROUPS "${group}" + std::append_path UsedGroups "${group}" done } +reset_used_releases() { + declare -g UsedReleases='' + for r in ${PMODULES_DEFAULT_RELEASES//:/ }; do + std::append_path UsedReleases "${r}" + done +} + ############################################################################## # # purge @@ -1507,7 +1516,7 @@ subcommand_purge() { subcommand_generic0 purge "$@" reset_modulepath reset_used_groups - pbuild::export_env ${g_shell} MODULEPATH PMODULES_USED_GROUPS + pbuild::export_env ${g_shell} MODULEPATH UsedGroups } ############################################################################## @@ -1544,21 +1553,51 @@ subcommand_list() { "${modulecmd}" "${g_shell}" list "${opts[@]}" } +init_path() { + std::replace_path PATH "${PMODULES_HOME%/*}/.*" + std::append_path PATH "${PMODULES_HOME}/bin" +} + +init_manpath() { + std::replace_path MANPATH "${PMODULES_HOME%/*}/.*" + + if [[ -r /etc/man.config ]]; then + declare _manconf='/etc/man.config' + elif [[ -r /etc/man.conf ]]; then + declare _manconf='/etc/man.conf' + fi + if [[ -n ${_manconf} ]]; then + while read name value rest; do + std::append_path MANPATH "${value}" + done < <(grep "^MANPATH\s" "${_manconf}") + unset _manconf + else + std::append_path MANPATH "${PMODULES_HOME}/share/man" + std::append_path MANPATH "/usr/share/man" + fi +} + ############################################################################## pmodules_init() { - declare -g LOADEDMODULES='' - declare -g _LMFILES_='' + declare -gx LOADEDMODULES='' + declare -gx _LMFILES_='' declare -Ag Overlays=([${PMODULES_ROOT}]="1") - declare -xg PMODULES_OVERLAYS="${PMODULES_ROOT}" + declare -gx PMODULES_OVERLAYS="${PMODULES_ROOT}" + declare -g UsedGroups='' + declare -gx MODULEPATH='' declare -Ag GroupDepths='()' - declare -g UsedReleases='' declare -g UseFlags=() - for r in ${PMODULES_DEFAULT_RELEASES//:/ }; do - std::append_path UsedReleases "${r}" - done reset_modulepath reset_used_groups + reset_used_releases + init_path + init_manpath + pbuild::export_env "${g_shell}" \ + LOADEDMODULES \ + _LMFILES_ \ + MODULEPATH \ + PATH } ############################################################################## @@ -1582,7 +1621,7 @@ subcommand_clear() { esac done pmodules_init - pbuild::export_env ${g_shell} LOADEDMODULES PMODULES_USED_GROUPS MODULEPATH _LMFILES_ + pbuild::export_env ${g_shell} LOADEDMODULES MODULEPATH _LMFILES_ } ############################################################################## @@ -1658,6 +1697,7 @@ subcommand_search() { local -r tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ || std::die 1 "Oops: unable to create tmp file!\n" local group + # loop over all groups for group in "${!GroupDepths[@]}"; do # loop over all directories which can be added to # MODULEPATH inside current group