From f5aaff58421d21af353eeff0b3b9d26c9a1b3f41 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Apr 2021 09:35:12 +0200 Subject: [PATCH 01/94] libmodules.tcl: some unconditional debug output removed --- Pmodules/libmodules.tcl | 1 - 1 file changed, 1 deletion(-) diff --git a/Pmodules/libmodules.tcl b/Pmodules/libmodules.tcl index 3a830d3..12690a9 100644 --- a/Pmodules/libmodules.tcl +++ b/Pmodules/libmodules.tcl @@ -21,7 +21,6 @@ if {[info exists env(PMODULES_DEBUG)] && $env(PMODULES_DEBUG)} { proc debug {msg} {} } -puts stderr "loading libmodules" debug "loading libmodules" proc _pmodules_parse_pmodules_env { } { From bfc754efa1830ee687c25f08a9591c3146c59dd2 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Apr 2021 09:37:56 +0200 Subject: [PATCH 02/94] tcllib added, version set to 1.1.1 --- build | 8 ++++---- config/versions.conf | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build b/build index 3495bcb..5a3d960 100755 --- a/build +++ b/build @@ -356,12 +356,12 @@ pmodules::compile() { build bash fi - if [[ ! -f "${PMODULES_HOME}/sbin/find" ]] || [[ ${opt_force} == 'yes' ]]; then - build findutils + if [[ ! -e "${PMODULES_HOME}/${UTILBIN_DIR}/tclsh" ]] || [[ ${opt_force} == 'yes' ]]; then + build Tcl fi - if [[ ! -e "${PMODULES_HOME}/sbin/tclsh" ]] || [[ ${opt_force} == 'yes' ]]; then - build Tcl + if [[ ! -e "${PMODULES_HOME}/lib/tcllib1.20" ]] || [[ ${opt_force} == 'yes' ]]; then + build tcllib fi if [[ ! -e "${PMODULES_HOME}/libexec/modulecmd.bin" ]] || [[ ${opt_force} == 'yes' ]]; then diff --git a/config/versions.conf b/config/versions.conf index 37deb08..f106cbc 100644 --- a/config/versions.conf +++ b/config/versions.conf @@ -4,5 +4,6 @@ findutils 4.7.0 getopt 1.1.6 gettext 0.21 modules 3.2.10.1 -Pmodules 1.1.0 +Pmodules 1.1.1 Tcl 8.6.10 +tcllib 1.20 From a53bf42479c8c4d39664785838f7d72f590bb565 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Apr 2021 09:41:06 +0200 Subject: [PATCH 03/94] modulecmd: use IFS saved as the beginning for restoring --- Pmodules/modulecmd.bash.in | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index cd7afdc..ed2c61d 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -476,10 +476,9 @@ subcommand_load() { "No module specified" fi - local saved_IFS="${IFS}"; IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${saved_IFS} + IFS=${__IFS} local m='' for m in "${args[@]}"; do @@ -900,10 +899,9 @@ get_available_modules() { # if no modulefile could be found # find_module() { - local saved_IFS=${IFS}; IFS=':' local -a dirs=($3) - IFS=${saved_IFS} + IFS=${__IFS} local -r module="$4" for dir in "${dirs[@]}"; do @@ -1519,10 +1517,9 @@ unuse directory|group|release... subcommand_unuse() { local -r subcommand='unuse' - local saved_IFS=${IFS}; IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${saved_IFS} + IFS=${__IFS} unuse() { unuse_overlay() { @@ -2275,10 +2272,9 @@ subcommand_search() { shift done if [[ -z "${src_prefix}" ]]; then - local saved_IFS="${IFS}"; IFS=':' local -a src_prefix=(${PMODULES_OVERLAYS}) - IFS=${saved_IFS} + IFS=${__IFS} fi if [[ "${opt_use_releases}" == ":" ]]; then From a415cdc1367e3d4ac6731ca7a3c40e2a35fca5b4 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Apr 2021 09:44:03 +0200 Subject: [PATCH 04/94] modulecmd: follow links in find cmd --- Pmodules/modulecmd.bash.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index ed2c61d..bc25b65 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -870,7 +870,7 @@ get_available_modules() { mods+=( "${mod}" ${release} "${dir}/${mod}" ) dict[${mod}]=1 fi - done < <(${find} ${entries} \ + done < <(${find} -L ${entries} \ \( -type f -o -type l \) \ -not -name ".*" \ -ipath "${module}*") @@ -913,7 +913,7 @@ find_module() { # a version number has been specified. But we still might # have the same module/version with different use flags. # Releases we ignore in this case. - modules=$(${find} "${dir}" -type f -not -name ".*" \ + modules=$(${find} -L "${dir}" -type f -not -name ".*" \ -ipath "${dir}/${module}*" \ | cut -b${col}-) for mod in "${modules[@]}"; do @@ -936,7 +936,7 @@ find_module() { # difficult. We have to load the newest version taking # the used releases and flags into account. (( col += ${#module} + 1 )) - modules=( $(${find} "${dir}" -type f -not -name ".*" \ + modules=( $(${find} -L "${dir}" -type f -not -name ".*" \ -ipath "${dir}/${module}/*" \ | cut -b${col}- \ | sort -rV ) ) @@ -1182,7 +1182,7 @@ compute_group_depth () { local group=${dir%/*} local group=${group##*/} [[ -n "${GroupDepths[${group}]}" ]] && return 0 - local -i depth=$(${find} "${dir}" -depth \( -type f -o -type l \) \ + local -i depth=$(${find} -L "${dir}" -depth \( -type f -o -type l \) \ -printf "%d" -quit 2>/dev/null) (( depth-=2 )) # if a group doesn't contain a modulefile, depth is negativ From 5661f69169b24768dae9968eac2ac58b12df9789 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Apr 2021 09:45:39 +0200 Subject: [PATCH 05/94] modulecmd: get_available_modules(): bugfix - it was expected that all modules are in an overlay. This is wrong. a user may add a modulefile directory with module use DIR. --- Pmodules/modulecmd.bash.in | 40 ++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index bc25b65..70b2079 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -846,26 +846,32 @@ get_available_modules() { "${dir}" \ "${mod}" [[ :${releases}: =~ ${release} ]] || continue - # - # add to list of available modules, if - # - first time found by name only - # - in same overlay as first found - # - new version and not hidden by overlay - local name="${mod%/*}" local add='no' - if [[ -z "${modulenames[${name}]}" ]]; then - if [[ "${Overlays[$overlay]}" == 'h' ]]; then - modulenames[${name}]="${overlay}" - else - modulenames[${name}]='0' + if [[ -n "${overlay}" ]]; then + # module is in an overlay + # + # add to list of available modules, if + # - first time found by name only + # - in same overlay as first found + # - new version and not hidden by overlay + local name="${mod%/*}" + if [[ -z "${modulenames[${name}]}" ]]; then + if [[ "${Overlays[$overlay]}" == 'h' ]]; then + modulenames[${name}]="${overlay}" + else + modulenames[${name}]='0' + fi + add='yes' + elif [[ "${modulenames[${name}]}" == "${overlay}" ]]; then + add='yes' + elif [[ "${modulenames[${name}]}" == '0' ]] \ + && [[ -z ${dict[${mod}]} ]]; then + add='yes' fi + else + # module is NOT in an overlay add='yes' - elif [[ "${modulenames[${name}]}" == "${overlay}" ]]; then - add='yes' - elif [[ "${modulenames[${name}]}" == '0' ]] \ - && [[ -z ${dict[${mod}]} ]]; then - add='yes' - fi + fi if [[ "${add}" == 'yes' ]]; then mods+=( "${mod}" ${release} "${dir}/${mod}" ) dict[${mod}]=1 From b62841239c67b28fec49ee53977fc5e46037dbdc Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Apr 2021 09:48:27 +0200 Subject: [PATCH 06/94] modulecmd: bugfix in use/unuse overlay - Since Pmodules itself can be loaded as module, it must be possible to add/remove overlays if no modules are loaded or only a Pmodules module. --- Pmodules/modulecmd.bash.in | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 70b2079..020f225 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1323,7 +1323,7 @@ subcommand_use() { use () { use_overlay() { - if [[ -n "${_LMFILES_}" ]]; then + if [[ -n "${_LMFILES_}" ]] && [[ ${LOADEDMODULES} != Pmodules/* ]]; then std::die 3 "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ "overlays can be added as long as no modules are loaded!" \ @@ -1529,12 +1529,11 @@ subcommand_unuse() { unuse() { unuse_overlay() { - [[ -n "${_LMFILES_}" ]] && \ - std::die 3 "%s %s: %s -- %s" \ + if [[ -n "${_LMFILES_}" ]] && [[ ${LOADEDMODULES} != Pmodules/* ]]; then std::die 3 "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ - "overlays can be removed as long as modules are loaded!" \ + "overlays can NOT be removed as long as modules are loaded!" \ "${overlay}" - + fi overlay=${overlay%:*} # ignore any modifier overlay=${overlay%/} # remove trailing '/' if there is one [[ -d "${overlay}" ]] || \ From 7ddd9b0ed78f71a8ee0d1c115f44f765133d0f4e Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Apr 2021 09:51:19 +0200 Subject: [PATCH 07/94] modulecmd: bugfix in initializing env. variable needed for overlays. - if we switch from a Pmodules version without overlay support to a Pmodule version with, some environment variables must be initialzed. --- Pmodules/modulecmd.bash.in | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 020f225..297a87b 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -2608,8 +2608,30 @@ if [[ -z "${Subcommands[${subcommand}]}" ]]; then std::die 1 "${CMD}: unknown sub-command -- ${subcommand}" fi +_init_overlay_map() { + local overlay + for overlay in "${!Overlays[@]}"; do + local group + for group in ${UsedGroups//:/ }; do + local dir="${overlay}/${group}/${PMODULES_MODULEFILES_DIR}" + if [[ -d "${dir}" ]]; then + MapDirsToOverlays[${dir}]=${overlay} + fi + done + done +} + if [[ -n ${PMODULES_ENV} ]]; then eval "$("${base64}" -d <<< "${PMODULES_ENV}" 2>/dev/null)" + # if we load a Pmodules version with overlay support, + # PMODULES_OVERLAYS might not be set. Since libmodules.tcl + # reads PMODULES_ENV we have to save the environment. + if [[ -z "${PMODULES_OVERLAYS}" ]]; then + declare -g PMODULES_OVERLAYS="${PMODULES_ROOT}" + declare -Ag Overlays=([${PMODULES_ROOT}]="0") + _init_overlay_map + save_env + fi else pmodules_init fi From 15fb22e4c8e5e3907d4c2f98cb009caaead89fc4 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:02:53 +0200 Subject: [PATCH 08/94] build script: commented out lines to build coreutils removed --- build | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build b/build index 5a3d960..cdd6ac4 100755 --- a/build +++ b/build @@ -338,10 +338,6 @@ pmodules::compile() { echo " root of Pmodules environment: ${prefix}" echo " Pmodule prefix: ${PMODULES_HOME}" - #if [[ ! -f "${PMODULES_HOME}/${UTILBIN_DIR}/base64" ]] || [[ ${opt_force} == 'yes' ]]; then - # build coreutils - #fi - if [[ "${OS}" == 'Darwin' ]]; then if [[ ! -f "${PMODULES_HOME}/${UTILBIN_DIR}/getopt" ]] || [[ ${opt_force} == 'yes' ]]; then build getopt From 0b8059efac4e6fcc1cfa3cf469e3be8e754aa148 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:05:09 +0200 Subject: [PATCH 09/94] libmodules.tcl: refactor some variable names, review - name of dictionary of overlay renamed from Overlays to OverlayDict - get list of overlays from PMODULES_ENV (OverlayList), PMODULES_OVERLAYS has been removed --- Pmodules/libmodules.tcl | 52 ++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/Pmodules/libmodules.tcl b/Pmodules/libmodules.tcl index 12690a9..d886a90 100644 --- a/Pmodules/libmodules.tcl +++ b/Pmodules/libmodules.tcl @@ -3,7 +3,7 @@ # switch/swap # unload modules if parent removed # -package require base64 + if {[info exists env(PMODULES_DEBUG)] && $env(PMODULES_DEBUG)} { proc debug {msg} { @@ -23,14 +23,27 @@ if {[info exists env(PMODULES_DEBUG)] && $env(PMODULES_DEBUG)} { debug "loading libmodules" +package require base64 + +set ::MODULEFILES_DIR "modulefiles" + proc _pmodules_parse_pmodules_env { } { + debug "enter" foreach line [split [base64::decode $::env(PMODULES_ENV)] "\n"] { - if { ![regexp -- {.* -[aA] (.*)=\((.*)\)} $line -> name value] } { + if { ![regexp -- {.* -[aAx]* (.*)=\((.*)\)} $line -> name value] } { continue } switch $name { - Overlays { - array set ::Overlays [regsub -all {[]=[]} $value " "] + OverlayDict { + array set ::OverlayDict [regsub -all {[]=[]} $value " "] + } + OverlayList { + array set tmp [regsub -all {[]=[]} $value " "] + set ::OverlayList {} + set l [lsort [array names tmp]] + foreach k $l { + lappend ::OverlayList $tmp($k) + } } } } @@ -55,20 +68,23 @@ proc module-addgroup { group } { debug "mode=[module-info mode]" if { [module-info mode load] } { array set overlayed_groups {} - foreach overlay [lreverse_n $::PmodulesOverlays 1] { + foreach overlay [lreverse_n $::OverlayList 1] { debug "overlay=$overlay" if {![info exists overlayed_groups($group)]} { + debug "group=$group" + debug "::variant=$::variant" set dir [file join \ $overlay \ $group \ - $::PmodulesModulfilesDir \ + $::MODULEFILES_DIR \ {*}$::variant] if { [file isdirectory $dir] } { + debug "prepend $dir to MODULEPATH " prepend-path MODULEPATH $dir } } # don't add if overlayed - if { [string compare $::Overlays($overlay) "g"] == 0 } { + if { [string compare $::OverlayDict($overlay) "g"] == 0 } { # get groups in this overlay set dirs [glob -directory $overlay -type d {[A-Z]*}] foreach dir $dirs { @@ -76,9 +92,8 @@ proc module-addgroup { group } { } } } + debug "end foreach" prepend-path UsedGroups $group - debug "mode=load: new MODULEPATH=$env(MODULEPATH)" - debug "mode=load: new UsedGroups=$env(UsedGroups)" } elseif { [module-info mode remove] } { set GROUP [string toupper $group] debug "mode=remove: hierarchical group '${GROUP}'" @@ -99,11 +114,11 @@ proc module-addgroup { group } { debug "mode=remove: no orphan modules to unload" } debug "mode=remove: $env(MODULEPATH)" - foreach overlay $::PmodulesOverlays { + foreach overlay $::OverlayList { set dir [file join \ $overlay \ $group \ - $::PmodulesModulfilesDir \ + $::MODULEFILES_DIR \ {*}$::variant] remove-path MODULEPATH $dir } @@ -136,7 +151,6 @@ proc lreverse_n { list n } { set res } -debug "test" # # set standard environment variables # @@ -291,15 +305,15 @@ proc ModulesHelp { } { # intialize global vars # Modulefile is something like # -# ${PMODULES_ROOT}/group/${PMODULES_MODULEFILES_DIR}/name/version +# ${PMODULES_ROOT}/group/modulefiles/name/version # or -# ${PMODULES_ROOT}/group/${PMODULES_MODULEFILES_DIR}/X1/Y1/name/version +# ${PMODULES_ROOT}/group/modulefiles/X1/Y1/name/version # or -# ${PMODULES_ROOT}/group/${PMODULES_MODULEFILES_DIR}/X1/Y1//X2/Y2/name/version +# ${PMODULES_ROOT}/group/modulefiles/X1/Y1//X2/Y2/name/version # proc _find_overlay { modulefile_components } { - debug "_is_in_overlay" - foreach overlay $::PmodulesOverlays { + debug "_find_overlay()" + foreach overlay $::OverlayList { debug "$overlay" if { [string range $overlay end end] == "/" } { set overlay [string range $overlay 0 end-1] @@ -314,6 +328,7 @@ proc _find_overlay { modulefile_components } { return $overlay_components } } + debug "not found" return {} } @@ -332,8 +347,6 @@ proc _pmodules_init_global_vars { } { global variant global PREFIX # prefix of package - set ::PmodulesOverlays [split $::env(PMODULES_OVERLAYS) ':'] - set ::PmodulesModulfilesDir $::env(PMODULES_MODULEFILES_DIR) set modulefile_components [file split $::ModulesCurrentModulefile] set overlay_components [_find_overlay ${modulefile_components}] @@ -360,6 +373,7 @@ proc _pmodules_init_global_vars { } { debug "group of module $name: $group" } + if { [info exists ::whatis] } { module-whatis "$whatis" } From ef1d10aa3d6506a0945816013c38b640624a6234 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:17:52 +0200 Subject: [PATCH 10/94] modulecmd.bash.in: unset IFS instead of restoring a default --- Pmodules/modulecmd.bash.in | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 297a87b..63d8f71 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -47,9 +47,8 @@ fi declare verbosity_lvl=${PMODULES_VERBOSITY:-'verbose'} -# we use newline as internal field separator -IFS=$' \t\n' -declare -r __IFS=${IFS} # used to restore IFS +# use default IFS +unset IFS shopt -s nullglob @@ -478,7 +477,7 @@ subcommand_load() { IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${__IFS} + unset IFS local m='' for m in "${args[@]}"; do @@ -494,7 +493,7 @@ subcommand_load() { IFS=':' local -a toks=($m) - IFS=${__IFS} + unset IFS local group='' local release='' if is_group "${toks[0]}"; then @@ -1141,11 +1140,9 @@ subcommand_avail() { if (( ${#pattern[@]} == 0 )); then pattern+=( '' ) fi - local -a modulepath IFS=':' - modulepath=(${MODULEPATH}) - IFS=${__IFS} - + local -a modulepath=(${MODULEPATH}) + unset IFS local overlay='' local group='' local -A modulepath_of_group @@ -1249,7 +1246,7 @@ subcommand_use() { local -r subcommand='use' IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${__IFS} + unset IFS local add2path_func='std::append_path' group_is_used() { @@ -1525,8 +1522,7 @@ subcommand_unuse() { local -r subcommand='unuse' IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${__IFS} - + unset IFS unuse() { unuse_overlay() { if [[ -n "${_LMFILES_}" ]] && [[ ${LOADEDMODULES} != Pmodules/* ]]; then std::die 3 "%s %s: %s -- %s" \ @@ -2186,12 +2182,12 @@ subcommand_search() { # get dependencies encoded in directory name local deps=() local -i j - IFS='/' + IFS='/' # note: IFS is used to concat in the for loop! local toks=( ${modulefile} ) for ((j = -depth-2; j < -2; j += 2)); do deps+=( "${toks[*]: $j:2}" ); done - IFS=${__IFS} + unset IFS fi echo ${name} ${release} ${group} ${modulefile} \ From 6674333728eeb854abff82dc59e438c3300a48dc Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:23:31 +0200 Subject: [PATCH 11/94] modulecmd.bash.in: call logger via variable with full path --- Pmodules/modulecmd.bash.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 63d8f71..9592945 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -22,6 +22,10 @@ declare -r sort awk=$(PATH=/bin:/usr/bin /usr/bin/which awk) declare -r awk rm=$(PATH=/bin:/usr/bin /usr/bin/which rm) +declare -r rm +logger=$(PATH=/bin:/usr/bin /usr/bin/which logger) +declare -r logger + if [[ $(uname -s) == 'Darwin' ]]; then declare -r getopt="${libexecdir}/getopt" declare -r find="${libexecdir}/find" @@ -624,7 +628,7 @@ subcommand_load() { [[ ${release} != stable ]]; then std::info "%s" "${msg}" fi - logger "${msg}" + ${logger} -t Pmodules "${msg}" done # fix LOADEDMODULES LOADEDMODULES="${_LMFILES_}" From 3eb18304436cfe1067f6e3d5a86f351b8c19cf6f Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:26:42 +0200 Subject: [PATCH 12/94] modulecmd.bash.in: save_env(): no need to export UsedGroups --- Pmodules/modulecmd.bash.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 9592945..1752c24 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -112,6 +112,7 @@ save_env() { local s=$(typeset -p ${vars[@]}) declare -g PMODULES_ENV=$( "${base64}" --wrap=0 <<< "$s" ) export_env 'PMODULES_ENV' + unset UsedGroups } trap 'save_env ' EXIT From a75e766cbc0a3b5c133a5c24eb51e31284d06a1f Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:29:21 +0200 Subject: [PATCH 13/94] modulecmd.bash.in: get_release(): redirect release file to upvar --- Pmodules/modulecmd.bash.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 1752c24..e319b7c 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -144,8 +144,7 @@ get_release() { local -r releasefile="${modulefile%/*}/.release-${modulefile##*/}" if [[ -r ${releasefile} ]]; then # read releasefile, remove empty lines, spaces etc - local -r data=$( < "${releasefile}" ) - std::upvar $1 "${data}" + std::upvar $1 $( < "${releasefile}" ) else std::upvar $1 'unstable' fi From f9430563e58a849c49cfb587e9df441ec10eb573 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:34:55 +0200 Subject: [PATCH 14/94] modulecmd.bash.in: cleanup --- Pmodules/modulecmd.bash.in | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index e319b7c..390fb2e 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -178,7 +178,7 @@ find_overlay () { local group="${path#${overlay}/}" group=${group%%/*} std::upvar $2 "${group}" - return 0 + return 0 } module_is_loaded() { @@ -302,10 +302,6 @@ subcommand_load() { local prefix='' local m='' - IFS=':' - local -a modulepath=(${MODULEPATH}) - IFS=${__IFS} - # # Test whether a given module is available. # The passed module-name can be From 376be20d35fe716f1b0487cd7ac51c78624c135b Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:35:52 +0200 Subject: [PATCH 15/94] modulecmd.bash.in: reset_modulepath() must be global --- Pmodules/modulecmd.bash.in | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 390fb2e..cb2da82 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1715,6 +1715,24 @@ subcommand_refresh() { subcommand_generic0 'refresh' "$@" } +# +# help function, used during initialization and for purging all modules +# +reset_modulepath() { + MODULEPATH='' + local group + local overlay + for overlay in "${!OverlayDict[@]}"; do + for group in ${PMODULES_DEFAULT_GROUPS}; do + local dir="${overlay}/${group}/${PMODULES_MODULEFILES_DIR}" + if [[ -d "${dir}" ]]; then + std::prepend_path MODULEPATH "${dir}" + Dir2OverlayMap[${dir}]=${overlay} + fi + done + done +} + pmodules_init() { declare -gx LOADEDMODULES='' declare -gx _LMFILES_='' @@ -1735,21 +1753,6 @@ pmodules_init() { g_env_must_be_saved='yes' } - reset_modulepath() { - MODULEPATH='' - local group - local overlay - for overlay in "${!Overlays[@]}"; do - for group in ${PMODULES_DEFAULT_GROUPS}; do - local dir="${overlay}/${group}/${PMODULES_MODULEFILES_DIR}" - if [[ -d "${dir}" ]]; then - std::prepend_path MODULEPATH "${dir}" - MapDirsToOverlays[${dir}]=${overlay} - fi - done - done - } - reset_used_releases() { declare -g UsedReleases='' for r in ${PMODULES_DEFAULT_RELEASES//:/ }; do From 05aa3d0e4237acfa21ec0a086d349592a711ed1e Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:37:54 +0200 Subject: [PATCH 16/94] modulecmd.bash.in: new global function get_overlay_of_moduledir() --- Pmodules/modulecmd.bash.in | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index cb2da82..d16ca62 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -117,6 +117,19 @@ save_env() { trap 'save_env ' EXIT +get_overlay_of_moduledir() { + local "$1" + local -r moduledir=$2 + + if [[ ! -v Dir2OverlayMap[${moduledir}] ]]; then + for overlay in "${OverlayList[@]}" 'other'; do + [[ ${moduledir} == ${overlay}/* ]] && break + done + Dir2OverlayMap[${moduledir}]="${overlay}" + fi + std::upvar $1 "${Dir2OverlayMap[${moduledir}]}" +} + # # get release of module # Note: From cc7b4b10cd351eaabd5d134df63fa3c4e43c6fbb Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:40:41 +0200 Subject: [PATCH 17/94] modulecmd.bash.in: is_group(): upvar with $1 must be declared local --- Pmodules/modulecmd.bash.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index d16ca62..40c14a3 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -431,6 +431,7 @@ subcommand_load() { # hierarchical depth of a group must always be the same. # is_group () { + local "$1" find_an_overlay_providing_group () { local "$1" local -r group="$2/${PMODULES_MODULEFILES_DIR}" From 0751e9c7435e6fa411e27f1254af0e40fc846bee Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:45:05 +0200 Subject: [PATCH 18/94] modulecnd.bash.in: find_module(): changes in arguments $3 and $4 - $3 is now the module to load - $4 is now an array of the splitted MODULEPATH --- Pmodules/modulecmd.bash.in | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 40c14a3..aa37ae7 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -563,7 +563,7 @@ subcommand_load() { fi fi # handle extended module names local release='' - find_module current_modulefile release "${MODULEPATH}" "${m}" + find_module current_modulefile release "${m}" "${modulepath[@]}" if [[ -z ${current_modulefile} ]]; then local text='' get_load_hints text @@ -902,8 +902,8 @@ get_available_modules() { # find module(file) to load. Input arguments are # $1 upvar: return module file # $2 upvar: return module release -# $3 a modulepath (usually MODULEPATH) -# $4 module to load +# $3 module to load +# $4 a modulepath (usually MODULEPATH) # # The module name can be # name @@ -918,10 +918,10 @@ get_available_modules() { # if no modulefile could be found # find_module() { - IFS=':' - local -a dirs=($3) - IFS=${__IFS} - local -r module="$4" + local "$1" + local "$2" + local -r module="$3" + local -a dirs=("${@:4}") for dir in "${dirs[@]}"; do test -d "${dir}" || continue From bf030e81b5279681ed06d440bdaf916371f9e8ec Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:47:59 +0200 Subject: [PATCH 19/94] modulecmd.bash.in: subcommand_load(): update Dir2OverlayMap - after loading a module the dictionary mapping a directory to an overlay must be updated if a new hierarchical group was added --- Pmodules/modulecmd.bash.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index aa37ae7..7e28f24 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -646,7 +646,9 @@ subcommand_load() { while read dir; do [[ "${dir: -1}" == "/" ]] || dir+="/" LOADEDMODULES="${LOADEDMODULES//${dir}}" + get_overlay_of_moduledir overlay "${dir}" done <<< "${MODULEPATH//:/$'\n'}" + g_env_must_be_saved='yes' export_env 'LOADEDMODULES' } From dc52066b7ec689012cc476f5a6561757f1105011 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:51:40 +0200 Subject: [PATCH 20/94] modulecmd.bash.in: improve readable of module avail --- Pmodules/modulecmd.bash.in | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 7e28f24..3e5fdd4 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1084,14 +1084,15 @@ subcommand_avail() { human_readable_output() { output_header "$1" - local -i column=$cols - local -i colsize=16 + local -a available_modules=() + local mod='' + local -i max_length=1 for ((i=0; i<${#mods[@]}; i+=3)); do if [[ ${verbosity_lvl} == 'verbose' ]]; then local release=${mods[i+1]} case ${mods[i+1]} in stable ) - mod=${mods[i]} + mod="${mods[i]}" ;; * ) mod="${mods[i]}(${release:0:1})" @@ -1100,9 +1101,17 @@ subcommand_avail() { else mod=${mods[i]} fi + local -i n=${#mod} + (( n > max_length )) && (( max_length=n )) + available_modules+=("${mod}") + done + IFS=$'\n' available_modules=($(sort <<<"${available_modules[*]}")) + unset IFS + local -i span=$(( max_length / 16 + 1 )) # compute column size + local -i colsize=$(( span * 16 )) # as multiple of 16 + local -i column=$cols # force a line-break + for mod in "${available_modules[@]}"; do local -i len=${#mod} - local -i span=$(( len / 16 + 1 )) - local -i colsize=$(( span * 16 )) if (( column+len >= cols )); then printf -- "\n" 1>&2 column=0 From 1932db23d0c1e526b7cdb38577d034fd1eff6c29 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:54:29 +0200 Subject: [PATCH 21/94] modulecmd.bash.in: sub.._avail(): use variable reference not dict using a variable reference makes it possible to pass an array to get_available_modules() insteas a colon separated string --- Pmodules/modulecmd.bash.in | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 3e5fdd4..0443ed7 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1170,26 +1170,27 @@ subcommand_avail() { unset IFS local overlay='' local group='' - local -A modulepath_of_group local -a groups=() for dir in "${modulepath[@]}"; do group='other' find_overlay overlay group "${dir}" - if [[ ${modulepath_of_group[${group}]} ]]; then - modulepath_of_group[${group}]+=:${dir} - else - modulepath_of_group[${group}]=${dir} - groups+=( "${group}" ) - fi + if [[ -v modulepath_${group} ]]; then + path+=("${dir}") + else + typeset -a modulepath_${group}="${dir}" + typeset -n path=modulepath_${group} + groups+=("${group}") + fi done - local string - for string in "${pattern[@]}"; do + local p + for p in "${pattern[@]}"; do for group in "${groups[@]}"; do + declare -n path=modulepath_${group} get_available_modules \ mods \ - "${string}" \ + "${p}" \ "${opt_use_releases}" \ - "${modulepath_of_group[${group}]}" + "${path[@]}" [[ ${#mods[@]} == 0 ]] && continue From 624b2757ffbbfd05f7dd65a0c6379361ff1bddc4 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 00:58:42 +0200 Subject: [PATCH 22/94] modulecmd.bash.in: subcommand_unuse(): cleanup --- Pmodules/modulecmd.bash.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 0443ed7..c632c2d 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1551,7 +1551,8 @@ subcommand_unuse() { unset IFS unuse() { unuse_overlay() { - if [[ -n "${_LMFILES_}" ]] && [[ ${LOADEDMODULES} != Pmodules/* ]]; then std::die 3 "%s %s: %s -- %s" \ + if [[ -n "${_LMFILES_}" ]] && [[ ${LOADEDMODULES} != Pmodules/* ]]; then + std::die 3 "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ "overlays can NOT be removed as long as modules are loaded!" \ "${overlay}" From ad8a02cdcf95d63454cd88cff3625fde6d634e14 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 01:01:21 +0200 Subject: [PATCH 23/94] modulecmd.bash.in: bug fixed in looping over overlays - the order of overlays is important, we have to use an array instead of a dictionary - PMODULES_OVERLAYS renamed to OverlayList which is now an array and exported in PMODULES_ENV - MapDirsToOverlays renamed to Dir2OverlayMap - dictionary Overlays renamed to OverlayDict --- Pmodules/modulecmd.bash.in | 105 +++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index c632c2d..000bf01 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -57,7 +57,7 @@ unset IFS shopt -s nullglob declare -A GroupDepths='()' -declare -A MapDirsToOverlays='()' +declare -A Dir2OverlayMap='()' declare Shell='' declare -A Subcommands declare -A Options @@ -106,8 +106,8 @@ save_env() { local vars=( GroupDepths UsedReleases UseFlags UsedGroups ) vars+=( PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES ) vars+=( PMODULES_DEFAULT_RELEASES ) - vars+=( PMODULES_OVERLAYS ) - vars+=( Overlays MapDirsToOverlays) + vars+=( OverlayList ) + vars+=( OverlayDict Dir2OverlayMap) local s=$(typeset -p ${vars[@]}) declare -g PMODULES_ENV=$( "${base64}" --wrap=0 <<< "$s" ) @@ -133,8 +133,8 @@ get_overlay_of_moduledir() { # # get release of module # Note: -# - the release of a module outside ${Overlays[@]} is always 'stable' -# - the release of a module inside ${Overlays[@]} without a +# - the release of a module outside ${OverlayDict[@]} is always 'stable' +# - the release of a module inside ${OverlayDict[@]} without a # coresponding release file is always 'unstable' # # Args: @@ -147,7 +147,14 @@ get_release() { local -r moduledir=$2 local -r name=$3 local -r modulefile="$2/$3" - + + local overlay + get_overlay_of_moduledir overlay "${moduledir}" + + if [[ "${overlay}" == 'other' ]]; then + std::upvar $1 'stable' + return + fi # # In an overlay the name of the module-file is something like # dir/modulefiles/name/version @@ -180,14 +187,12 @@ find_overlay () { local "$1" local "$2" local -r path=$3 - local overlay=${MapDirsToOverlays[${path}]} - if [[ -z "${overlay}" ]]; then - for overlay in "${!Overlays[@]}" 'ZZZZZZ'; do - [[ ${path}/ =~ ^${overlay}/ ]] && break - done - [[ "${overlay}" == 'ZZZZZZ' ]] && return 1 - fi + local overlay=${Dir2OverlayMap[${path}]} + get_overlay_of_moduledir overlay "${path}" std::upvar $1 "${overlay}" + + [[ "${overlay}" == 'other' ]] && return 1 + local group="${path#${overlay}/}" group=${group%%/*} std::upvar $2 "${group}" @@ -436,7 +441,7 @@ subcommand_load() { local "$1" local -r group="$2/${PMODULES_MODULEFILES_DIR}" local overlay - for overlay in "${!Overlays[@]}"; do + for overlay in "${OverlayList[@]}"; do if [[ -d "${overlay}/${group}" ]]; then std::upvar $1 "${overlay}" return 0 @@ -548,9 +553,9 @@ subcommand_load() { MODULEPATH="" modulepath=() group+="${PMODULES_MODULEFILES_DIR}" - for overlay in "${!Overlays[@]}"; do - MODULEPATH+=":${overlay}/${group}/" - modulepath+=( ${MODULEPATH} ) + for overlay in "${OverlayList[@]}"; do + MODULEPATH="${overlay}/${group}/:${MODULEPATH}" + modulepath=( "${overlay}/${group}/" "${modulepath[@]}" ) done fi if [[ -n ${release} ]]; then @@ -871,7 +876,7 @@ get_available_modules() { # - new version and not hidden by overlay local name="${mod%/*}" if [[ -z "${modulenames[${name}]}" ]]; then - if [[ "${Overlays[$overlay]}" == 'h' ]]; then + if [[ "${OverlayDict[$overlay]}" == 'h' ]]; then modulenames[${name}]="${overlay}" else modulenames[${name}]='0' @@ -1322,9 +1327,9 @@ subcommand_use() { local overlay std::info '' std::info "Used overlays:" - for overlay in "${!Overlays[@]}"; do + for overlay in "${OverlayList[@]}"; do local hiding='' - [[ "${Overlays[${overlay}]}" != '0' ]] && hiding=' (hiding)' + [[ "${OverlayDict[${overlay}]}" != '0' ]] && hiding=' (hiding)' std::info "\t${overlay}${hiding}" done @@ -1377,7 +1382,7 @@ subcommand_use() { "${CMD}" "${subcommand}" \ "is not an overlay directory" \ "${overlay}" - if [[ -n "${Overlays[${overlay}]}" ]]; then + if [[ -n "${OverlayDict[${overlay}]}" ]]; then std::info "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ "overlay already in use" \ @@ -1394,7 +1399,7 @@ subcommand_use() { dir+="${group}/${PMODULES_MODULEFILES_DIR}" [[ -d "${dir}" ]] || continue # no - for dir in "${!Overlays[@]}"; do + for dir in "${OverlayList[@]}"; do dir+="/${group}/${PMODULES_MODULEFILES_DIR}" std::remove_path MODULEPATH "${dir}" done @@ -1406,28 +1411,28 @@ subcommand_use() { dir+="${group}/${PMODULES_MODULEFILES_DIR}" if [[ -d "${dir}" ]]; then std::prepend_path MODULEPATH "${dir}" - MapDirsToOverlays[${dir}]=${overlay} + Dir2OverlayMap[${dir}]=${overlay} fi done - Overlays[${overlay}]=${modifier} - PMODULES_OVERLAYS+=":${overlay}" - export_env PMODULES_OVERLAYS + OverlayDict[${overlay}]=${modifier} + OverlayList=( "${overlay}" "${OverlayList[@]}" ) + export_env OverlayList g_env_must_be_saved='yes' - scan_groups "${!Overlays[@]}" + scan_groups "${OverlayList[@]}" local group } use_group() { std::append_path UsedGroups "$1" local overlay group - for overlay in "${!Overlays[@]}"; do + for overlay in "${OverlayList[@]}"; do for group in ${UsedGroups//:/ }; do local dir="${overlay}/" dir+="${group}/${PMODULES_MODULEFILES_DIR}" if [[ -d "${dir}" ]]; then std::prepend_path MODULEPATH "${dir}" - MapDirsToOverlays[${dir}]=${overlay} + Dir2OverlayMap[${dir}]=${overlay} fi done done @@ -1486,7 +1491,7 @@ subcommand_use() { local dir="$(cd "${arg}" && pwd)" local overlay - for overlay in "${!Overlays[@]}"; do + for overlay in "${OverlayList[@]}"; do if [[ ${dir}/ =~ ^${overlay}/ ]]; then # dir is in one of our used overlays std::die 3 "%s %s: %s -- %s" \ @@ -1569,7 +1574,7 @@ subcommand_unuse() { "${CMD}" "${subcommand}" \ "cannot remove root overlay" \ "${overlay}" - [[ -z ${Overlays[${overlay}]} ]] && \ + [[ -z ${OverlayDict[${overlay}]} ]] && \ std::die 3 "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ "not an used overlay" \ @@ -1584,17 +1589,20 @@ subcommand_unuse() { dir+="${group}/${PMODULES_MODULEFILES_DIR}" [[ -d "${dir}" ]] || continue # no - for dir in "${!Overlays[@]}"; do + for dir in "${OverlayList[@]}"; do dir+="/${group}/${PMODULES_MODULEFILES_DIR}" std::remove_path MODULEPATH "${dir}" done done fi - unset "Overlays[${overlay}]" - std::remove_path PMODULES_OVERLAYS "${overlay}" + unset "OverlayDict[${overlay}]" + local i + for i in "${!OverlayList[@]}"; do + [[ ${OverlayList[i]} == ${overlay} ]] && unset 'OverlayList[i]' + done g_env_must_be_saved='yes' - export_env PMODULES_OVERLAYS + export_env OverlayList local dir for dir in "${modulepath[@]}"; do if [[ "${dir}" =~ "${overlay}" ]]; then @@ -1613,7 +1621,7 @@ subcommand_unuse() { fi std::remove_path UsedGroups "${arg}" local overlay - for overlay in "${!Overlays[@]}"; do + for overlay in "${OverlayList[@]}"; do local dir="${overlay}/${arg}/${PMODULES_MODULEFILES_DIR}" std::remove_path MODULEPATH "${dir}" done @@ -1662,7 +1670,7 @@ subcommand_unuse() { local dir="$(cd "${arg}" && pwd)" local overlay - for overlay in "${!Overlays[@]}"; do + for overlay in "${OverlayList[@]}"; do if [[ ${dir}/ =~ ^${overlay}/ ]]; then # dir is in one of our used overlays std::die 3 "%s %s: %s -- %s" \ @@ -1764,8 +1772,8 @@ pmodules_init() { declare -gx LOADEDMODULES='' declare -gx _LMFILES_='' - declare -Ag Overlays=([${PMODULES_ROOT}]="0") - declare -gx PMODULES_OVERLAYS="${PMODULES_ROOT}" + declare -Ag OverlayDict=([${PMODULES_ROOT}]="0") + declare -ag OverlayList=( "${PMODULES_ROOT}" ) declare -g UsedGroups='' declare -gx MODULEPATH='' declare -Ag GroupDepths='()' @@ -1817,7 +1825,6 @@ pmodules_init() { reset_used_releases init_manpath export_env \ - PMODULES_OVERLAYS \ LOADEDMODULES \ _LMFILES_ \ MODULEPATH \ @@ -2303,9 +2310,7 @@ subcommand_search() { shift done if [[ -z "${src_prefix}" ]]; then - IFS=':' - local -a src_prefix=(${PMODULES_OVERLAYS}) - IFS=${__IFS} + local -a src_prefix=( "${OverlayList[@]}" ) fi if [[ "${opt_use_releases}" == ":" ]]; then @@ -2636,12 +2641,12 @@ fi _init_overlay_map() { local overlay - for overlay in "${!Overlays[@]}"; do + for overlay in "${!OverlayDict[@]}"; do local group for group in ${UsedGroups//:/ }; do local dir="${overlay}/${group}/${PMODULES_MODULEFILES_DIR}" if [[ -d "${dir}" ]]; then - MapDirsToOverlays[${dir}]=${overlay} + Dir2OverlayMap[${dir}]=${overlay} fi done done @@ -2650,11 +2655,11 @@ _init_overlay_map() { if [[ -n ${PMODULES_ENV} ]]; then eval "$("${base64}" -d <<< "${PMODULES_ENV}" 2>/dev/null)" # if we load a Pmodules version with overlay support, - # PMODULES_OVERLAYS might not be set. Since libmodules.tcl + # OverlayList might not be set. Since libmodules.tcl # reads PMODULES_ENV we have to save the environment. - if [[ -z "${PMODULES_OVERLAYS}" ]]; then - declare -g PMODULES_OVERLAYS="${PMODULES_ROOT}" - declare -Ag Overlays=([${PMODULES_ROOT}]="0") + if [[ -z "${OverlayList}" ]]; then + declare -ag OverlayList=( "${PMODULES_ROOT}" ) + declare -Ag OverlayDict=([${PMODULES_ROOT}]="0") _init_overlay_map save_env fi @@ -2663,7 +2668,7 @@ else fi if (( ${#GroupDepths[@]} == 0 )); then - scan_groups "${!Overlays[@]}" + scan_groups "${!OverlayDict[@]}" fi declare options From aa4140631ce3159f115e331d591e26965dd1f175 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 10:52:12 +0200 Subject: [PATCH 24/94] tcllib added to repo --- Tools/tcllib/build | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 Tools/tcllib/build diff --git a/Tools/tcllib/build b/Tools/tcllib/build new file mode 100755 index 0000000..af189fe --- /dev/null +++ b/Tools/tcllib/build @@ -0,0 +1,5 @@ +#!/usr/bin/env modbuild + +pbuild::set_download_url "https://core.tcl-lang.org/tcllib/uv/$P-$V.tar.xz" +#uild::install_docfiles 'license.terms' 'README.md' + From a0420cc73fe611baaa139646da088e57bb7e2024 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 10:53:07 +0200 Subject: [PATCH 25/94] modulecmd.bash.in: save_env() requires an argument now PMODULES_ENV will be compiles and exported if save_env() is called with $1 != 'no' --- Pmodules/modulecmd.bash.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 000bf01..420cd30 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -102,7 +102,7 @@ export_env() { declare g_env_must_be_saved='no' save_env() { - [[ ${g_env_must_be_saved} == 'no' ]] && return 0 + [[ "$1" == 'no' ]] && return 0 local vars=( GroupDepths UsedReleases UseFlags UsedGroups ) vars+=( PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES ) vars+=( PMODULES_DEFAULT_RELEASES ) @@ -115,7 +115,7 @@ save_env() { unset UsedGroups } -trap 'save_env ' EXIT +trap 'save_env ${g_env_must_be_saved}' EXIT get_overlay_of_moduledir() { local "$1" From 1b43ccbe21228548dd7e5e486c2445a69f074209 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 10:56:00 +0200 Subject: [PATCH 26/94] modulecmd.bash.in: bugfix in initialization of overlays the variables required for overlays were not initialized in a proper way if we switch from a Pmodules version without overlay support --- Pmodules/modulecmd.bash.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 420cd30..c2ac3ee 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -2639,7 +2639,9 @@ if [[ -z "${Subcommands[${subcommand}]}" ]]; then std::die 1 "${CMD}: unknown sub-command -- ${subcommand}" fi -_init_overlay_map() { +_init_overlay_vars() { + declare -ag OverlayList=( "${PMODULES_ROOT}" ) + declare -Ag OverlayDict=([${PMODULES_ROOT}]="0") local overlay for overlay in "${!OverlayDict[@]}"; do local group @@ -2650,6 +2652,7 @@ _init_overlay_map() { fi done done + save_env 'yes' } if [[ -n ${PMODULES_ENV} ]]; then @@ -2658,10 +2661,7 @@ if [[ -n ${PMODULES_ENV} ]]; then # OverlayList might not be set. Since libmodules.tcl # reads PMODULES_ENV we have to save the environment. if [[ -z "${OverlayList}" ]]; then - declare -ag OverlayList=( "${PMODULES_ROOT}" ) - declare -Ag OverlayDict=([${PMODULES_ROOT}]="0") - _init_overlay_map - save_env + _init_overlay_vars fi else pmodules_init From 4ed8961fc17f6fc8e20f4b74bee49bcecab79caa Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 10:58:53 +0200 Subject: [PATCH 27/94] modulecmd.bash.in: bug fixed in purge sub-cmd --- Pmodules/modulecmd.bash.in | 61 ++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index c2ac3ee..af165f3 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1845,6 +1845,13 @@ USAGE: ' subcommand_purge() { + # + # unload all loaded modules + # + # Note: + # If a Pmodule module is loaded, it will *not* be + # unloaded! + # local -r subcommand='purge' local -a args=() while (( $# > 0)); do @@ -1865,13 +1872,55 @@ subcommand_purge() { "${CMD}" "${subcommand}" \ "no arguments allowd" fi - # we cannot unset PMODULES_HOME, otherwise the module function - # would fail. - local saved_home="${PMODULES_HOME}" - "${modulecmd}" "${Shell}" "${subcommand}" + + # is a Pmodule module loaded? + # if yes, save name in variable 'pmodule' + local pmodule='' + IFS=':' + local -a lmfiles=($_LMFILES_) + unset IFS + for f in "${lmfiles[@]}"; do + if [[ $f == */${PMODULES_MODULEFILES_DIR}/Pmodules/* ]]; then + pmodule="${f##*/${PMODULES_MODULEFILES_DIR}/}" + break; + fi + done + + # run module purge + # since we might have to reload a Pmodules module, we cannot + # just run 'modulecmd ${Shell} purge' + local tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ + || std::die 1 "Oops: unable to create tmp file!" + local output=$("${modulecmd}" 'bash' 'purge' 2> "${tmpfile}") + + local error=$( < "${tmpfile}") + if [[ "${error}" =~ ":ERROR:" ]]; then + local s=${error%%$'\n'*} + local error_txt='failed' + std::die 3 "%s %s: %s" \ + "${CMD}" "${subcommand}" \ + "${error_txt}" + fi + if [[ "${Shell}" == "sh" ]]; then + # for sh-like shells just echo + echo "${output}" + else + # re-run with right shell + "${modulecmd}" "${Shell}" 'purge' + fi + eval "${output}" + if [[ -n "${error}" ]]; then + echo "${error}" 1>&2 + fi + reset_modulepath - reset_used_groups - PMODULES_HOME="${saved_home}" + if [[ -n "${pmodule}" ]]; then + # reload a previously loaded Pmodule module + # stderr is redirected to /dev/null, otherwise + # we may get output like + # 'unstable module has been loaded' + subcommand_load "${pmodule}" 2> /dev/null + fi export_env MODULEPATH PMODULES_HOME } From 077cf0c4be45343f4f9c58f3951c26898b4aaeeb Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 11:46:13 +0200 Subject: [PATCH 28/94] modulecmd: bugfix in save_env() Unsetting 'UsedGroups' the way we did doesn't work, revert this change --- Pmodules/modulecmd.bash.in | 1 - 1 file changed, 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index af165f3..dc3700a 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -112,7 +112,6 @@ save_env() { local s=$(typeset -p ${vars[@]}) declare -g PMODULES_ENV=$( "${base64}" --wrap=0 <<< "$s" ) export_env 'PMODULES_ENV' - unset UsedGroups } trap 'save_env ${g_env_must_be_saved}' EXIT From 23cbb4210e8a14751d62181cce7d6f76cfea4b97 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 11:49:45 +0200 Subject: [PATCH 29/94] modulecmd: sub-cmd purge: reset MODUEPATH to used groups The sub-command purge should not remove used groups from MODULEPATH --- Pmodules/modulecmd.bash.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index dc3700a..cb19df5 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1757,7 +1757,7 @@ reset_modulepath() { local group local overlay for overlay in "${!OverlayDict[@]}"; do - for group in ${PMODULES_DEFAULT_GROUPS}; do + for group in ${UsedGroups//:/ }; do local dir="${overlay}/${group}/${PMODULES_MODULEFILES_DIR}" if [[ -d "${dir}" ]]; then std::prepend_path MODULEPATH "${dir}" @@ -1912,7 +1912,6 @@ subcommand_purge() { echo "${error}" 1>&2 fi - reset_modulepath if [[ -n "${pmodule}" ]]; then # reload a previously loaded Pmodule module # stderr is redirected to /dev/null, otherwise @@ -1920,6 +1919,7 @@ subcommand_purge() { # 'unstable module has been loaded' subcommand_load "${pmodule}" 2> /dev/null fi + reset_modulepath export_env MODULEPATH PMODULES_HOME } From c44f393ef26101e5667704ae43b2c039465419cd Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 14:21:16 +0200 Subject: [PATCH 30/94] modulecmd: improved handling of tmp file(s) A tmp file is now created at the very beginning for all subcommands where a tmp file is needed. The file is removed in the _exit() function which is registered via trap. --- Pmodules/modulecmd.bash.in | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index cb19df5..f3e8d88 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -114,7 +114,12 @@ save_env() { export_env 'PMODULES_ENV' } -trap 'save_env ${g_env_must_be_saved}' EXIT +_exit() { + save_env "${g_env_must_be_saved}" + ${rm} -f "${tmpfile}" +} + +trap '_exit' EXIT get_overlay_of_moduledir() { local "$1" @@ -597,8 +602,6 @@ subcommand_load() { test -r "${prefix}/.dependencies" && load_dependencies "$_" fi - local tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ - || std::die 1 "Oops: unable to create tmp file!" local output=$("${modulecmd}" 'bash' ${opts} 'load' \ "${current_modulefile}" 2> "${tmpfile}") @@ -1888,8 +1891,6 @@ subcommand_purge() { # run module purge # since we might have to reload a Pmodules module, we cannot # just run 'modulecmd ${Shell} purge' - local tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ - || std::die 1 "Oops: unable to create tmp file!" local output=$("${modulecmd}" 'bash' 'purge' 2> "${tmpfile}") local error=$( < "${tmpfile}") @@ -2181,8 +2182,6 @@ subcommand_search() { func_print_line='print_line_csv' } - local -r tmpfile=$1 - if [[ "${opt_print_modulefiles}" == 'yes' ]]; then print_modulefiles elif [[ "${opt_print_csv}" == 'yes' ]]; then @@ -2220,8 +2219,6 @@ subcommand_search() { search () { local -r module=$1 # write results to a temporary file for later processing - local -r tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ - || std::die 1 "Oops: unable to create tmp file!" local group # loop over all groups for group in "${!GroupDepths[@]}"; do @@ -2279,8 +2276,7 @@ subcommand_search() { ${deps[@]} >> "${tmpfile}" done done - print_result "${tmpfile}" - ${rm} -f "${tmpfile}" + print_result } while (( $# > 0 )); do @@ -2719,6 +2715,13 @@ if (( ${#GroupDepths[@]} == 0 )); then scan_groups "${!OverlayDict[@]}" fi +case ${subcommand} in + load|purge|search ) + declare -r tmpfile=$( ${mktemp} /tmp/Pmodules.XXXXXX ) \ + || std::die 1 "Oops: unable to create tmp file!" + ;; +esac + declare options options=$( "${getopt}" ${Options[${subcommand}]} -- -- "${opts[@]}" "$@" ) \ || print_help "${subcommand}" From 9e6566636b35316baa7057b3d85320c0bafb19b7 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 18:51:29 +0200 Subject: [PATCH 31/94] modulecmd: bugfix in use/unuse overlays --- Pmodules/modulecmd.bash.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index f3e8d88..5d98ad6 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1353,7 +1353,7 @@ subcommand_use() { use () { use_overlay() { - if [[ -n "${_LMFILES_}" ]] && [[ ${LOADEDMODULES} != Pmodules/* ]]; then + if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then std::die 3 "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ "overlays can be added as long as no modules are loaded!" \ @@ -1558,7 +1558,7 @@ subcommand_unuse() { unset IFS unuse() { unuse_overlay() { - if [[ -n "${_LMFILES_}" ]] && [[ ${LOADEDMODULES} != Pmodules/* ]]; then + if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then std::die 3 "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ "overlays can NOT be removed as long as modules are loaded!" \ From d23fdf930a523796de8562dfb91a76cccd9b6ef1 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 18:52:58 +0200 Subject: [PATCH 32/94] Pmodule modulefile: remove Pmodules bin dir from PATH in some cases it might happen that we have a Pmodules bin directory in PATH. This has to be removed if we load a Pmodule module. --- Pmodules/modulefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Pmodules/modulefile b/Pmodules/modulefile index 65aa4c1..2a9311d 100644 --- a/Pmodules/modulefile +++ b/Pmodules/modulefile @@ -8,3 +8,15 @@ module-maintainer "Achim Gsell " module-help " Pmodules are a hierarchical module environment based on Environment Modules. " + +# +# It might be that '${PMODULES_ROOT}/Tools/Pmodules/VERSION' is in PATH. +# Why? With older version the PATH might have been set without loading +# a module. +# +if { [module-info mode load] } { + set PATH ":$::env(PATH):" + if { [regexp -- {.*:(.*/Pmodules/[^:]*):} $PATH -> str] } { + remove-path PATH $str + } +} From 47b5fae59b0f59f5ae13fb338c678006ea3ce018 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 29 Apr 2021 17:54:25 +0200 Subject: [PATCH 33/94] modbuild: better support for build modules in overlays A new configuration file has been added to map human readable overlay names to the corresponding directory. The overlay can be specified with the --overlay option. The passed string can be either a name or a directory. If a name is passed, this name must map to directory in the configuration file ${PMODULES_ROOT}/config/overlays.conf. The name is also used as to select the variant files 'files/variants.name'. The selection of variant files can be overriden with the --system option. --- Pmodules/libpbuild.bash | 6 ++-- Pmodules/modbuild.in | 62 +++++++++++++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Pmodules/libpbuild.bash b/Pmodules/libpbuild.bash index 526d9c3..944eeab 100644 --- a/Pmodules/libpbuild.bash +++ b/Pmodules/libpbuild.bash @@ -764,12 +764,12 @@ pbuild::make_all() { fi modulefile_dir=$(join_by '/' \ - "${overlay}/${GROUP}/${PMODULES_MODULEFILES_DIR}" \ + "${overlay_dir}/${GROUP}/${PMODULES_MODULEFILES_DIR}" \ "${names[@]}" \ "${module_name}") modulefile_name="${modulefile_dir}/${module_version}" - PREFIX="${overlay}/${GROUP}/${module_name}/${module_version}" + PREFIX="${overlay_dir}/${GROUP}/${module_name}/${module_version}" local -i i=0 for ((i=${#names[@]}-1; i >= 0; i--)); do PREFIX+="/${names[i]}" @@ -1479,7 +1479,7 @@ pbuild.bootstrap() { MODULECMD=$(which true) GROUP='Tools' - PREFIX="${overlay}/${GROUP}/Pmodules/${PMODULES_VERSION}" + PREFIX="${overlay_dir}/${GROUP}/Pmodules/${PMODULES_VERSION}" C_INCLUDE_PATH="${PREFIX}/include" CPLUS_INCLUDE_PATH="${PREFIX}/include" diff --git a/Pmodules/modbuild.in b/Pmodules/modbuild.in index 4827218..a992d9a 100755 --- a/Pmodules/modbuild.in +++ b/Pmodules/modbuild.in @@ -154,7 +154,7 @@ declare opt_verbose='no' # array collecting all modules specified on the command line via '--with=module' declare -a opt_with_modules=() -declare overlay='' +declare opt_overlay_name_or_dir='' parse_args() { @@ -259,10 +259,10 @@ parse_args() { opt_update_modulefiles='yes' ;; --overlay ) - overlay=$2 + opt_overlay_name_or_dir=$2 ;; --overlay=* ) - overlay=${1/*=} + opt_overlay_name_or_dir=${1/*=} ;; -- ) : @@ -366,7 +366,6 @@ build_modules() { fi done - local variants=() local variants_files=() for f in "${files[@]}"; do @@ -408,15 +407,64 @@ build_modules() { done } +declare -r OVERLAY_CONF="${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/overlays.conf" + +get_overlay_name_and_dir() { + local "$1" + local "$2" + if [[ -r "${OVERLAY_CONF}" ]]; then + local toks=() + while read -a toks; do + if [[ ${toks[0]} == $3 ]] || [[ ${toks[1]} == $3 ]]; then + std::upvar $1 "${toks[0]}" + std::upvar $2 "${toks[1]}" + return 0 + fi + done < "${OVERLAY_CONF}" + fi + return 1 +} + #............................................................................. # main parse_args "$@" -if [[ -z "${opt_system}" ]]; then - opt_system=$(std::get_os_release) +# +# --overlay=name +# lookup overlay directory, system name equivalent to overlay name +# --overlay=name --system=sysname +# lookup name, use given system name +# --overlay=dir +# use given overlay dir and default system name +# --system=name +# lookup name, set overlay_dir of found confi +declare overlay_name='' +declare overlay_dir='' +if [[ -n "${opt_overlay_name_or_dir}" ]]; then + if ! get_overlay_name_and_dir overlay_name overlay_dir "${opt_overlay_name_or_dir}"; then + # not found in config + if [[ ${opt_overlay_name_or_dir:0:1} == / ]]; then + overlay_dir="${opt_overlay_name_or_dir}" + else + std::die 1 "Invalid overlay name -- ${opt_overlay_name_or_dir}" + fi + fi + if [[ -z "${opt_system}" ]] && [[ -n "${overlay_name}" ]]; then + opt_system="${overlay_name}" + fi +elif [[ -n "${opt_system}" ]]; then + get_overlay_name_and_dir overlay_name overlay_dir "${opt_system}" || : fi +[[ -z "${overlay_name}" ]] && overlay_name='unknown' +[[ -z "${overlay_dir}" ]] && overlay_dir="${PMODULES_ROOT}" +[[ -z "${opt_system}" ]] && opt_system=$(std::get_os_release) + +echo overlay_name=$overlay_name +echo overlay_dir=$overlay_dir +echo opt_system=$opt_system + pbuild.jobs "${opt_jobs}" pbuild.force_rebuild "${opt_force_rebuild}" pbuild.build_target "${opt_build_target}" @@ -441,8 +489,6 @@ fi source "${opt_build_config}" || \ std::die 3 "Oops: Cannot source configuration file -- '$_'" -[[ -z "${overlay}" ]] && overlay=${PMODULES_ROOT} - # :FIXME: should go dist files to # ${PMODULES_ROOT}/var/distfiles # or From 80728b8a6a557b3157e5b6d0c9690766f2f3f489 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 29 Apr 2021 18:10:55 +0200 Subject: [PATCH 34/94] modulecmd: tag log messages with 'Pmodules' --- Pmodules/modulecmd.bash.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 8501996..ee4e922 100755 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -22,6 +22,10 @@ declare -r sort awk=$(PATH=/bin:/usr/bin /usr/bin/which awk) declare -r awk rm=$(PATH=/bin:/usr/bin /usr/bin/which rm) +declare -r rm +logger=$(PATH=/bin:/usr/bin /usr/bin/which logger) +declare -r logger + if [[ $(uname -s) == 'Darwin' ]]; then declare -r getopt="${libexecdir}/getopt" declare -r find="${libexecdir}/find" @@ -556,7 +560,7 @@ subcommand_load() { [[ ${release} != stable ]]; then std::info "%s" "${msg}" fi - logger "${msg}" + ${logger} -t Pmodules "${msg}" done # fix LOADEDMODULES LOADEDMODULES="${_LMFILES_}" From a970be1cf3b2a91b8ab829fd38983a55c037c8a9 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 29 Apr 2021 18:47:01 +0200 Subject: [PATCH 35/94] modulecmd: don't remove a loaded Pmodules module with module purge Removing a Pmodule module with module purge has some unwanted side-effects. It is not required to have modulecmd in a directory of PATH. If you user explicitly loads a Pmodules module the bin directory of the Pmodule module is added to the PATH. A Pmodules module might be loaded for two reasons. First to change the Pmodules version, second to make the build system available. If we remove a Pmodules module with module purge the build systems is getting unavailable again. This is confusing for the user. --- Pmodules/modulecmd.bash.in | 68 +++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index ee4e922..744d64c 100755 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1320,7 +1320,7 @@ reset_modulepath() { MODULEPATH='' local group local root="${PMODULES_ROOT}" - for group in ${PMODULES_DEFAULT_GROUPS}; do + for group in ${UsedGroups//:/ }; do local dir="${root}/${group}/${PMODULES_MODULEFILES_DIR}" [[ -d "${dir}" ]] && std::prepend_path MODULEPATH "${dir}" done @@ -1395,6 +1395,13 @@ USAGE: ' subcommand_purge() { + # + # unload all loaded modules + # + # Note: + # If a Pmodule module is loaded, it will *not* be + # unloaded! + # local -r subcommand='purge' local -a args=() while (( $# > 0)); do @@ -1411,21 +1418,66 @@ subcommand_purge() { shift done if (( ${#args[@]} > 0 )); then - std::die 3 "%s %s: %s\n" \ + std::die 3 "%s %s: %s" \ "${CMD}" "${subcommand}" \ "no arguments allowd" fi - # we cannot unset PMODULES_HOME, otherwise the module function - # would fail. - local saved_home="${PMODULES_HOME}" - "${modulecmd}" "${Shell}" "${subcommand}" + + # is a Pmodule module loaded? + # if yes, save name in variable 'pmodule' + local pmodule='' + IFS=':' + local -a lmfiles=($_LMFILES_) + unset IFS + for f in "${lmfiles[@]}"; do + if [[ $f == */${PMODULES_MODULEFILES_DIR}/Pmodules/* ]]; then + pmodule="${f##*/${PMODULES_MODULEFILES_DIR}/}" + break; + fi + done + + # run module purge + # since we might have to reload a Pmodules module, we cannot + # just run 'modulecmd ${Shell} purge' + local tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ + || std::die 1 "Oops: unable to create tmp file!\n" + + local output=$("${modulecmd}" 'bash' 'purge' 2> "${tmpfile}") + + local error=$( < "${tmpfile}") + ${rm} "${tmpfile}" + if [[ "${error}" =~ ":ERROR:" ]]; then + local s=${error%%$'\n'*} + local error_txt='failed' + std::die 3 "%s %s: %s" \ + "${CMD}" "${subcommand}" \ + "${error_txt}" + fi + if [[ "${Shell}" == "sh" ]]; then + # for sh-like shells just echo + echo "${output}" + else + # re-run with right shell + "${modulecmd}" "${Shell}" 'purge' + fi + eval "${output}" + if [[ -n "${error}" ]]; then + echo "${error}" 1>&2 + fi + + if [[ -n "${pmodule}" ]]; then + # reload a previously loaded Pmodule module + # stderr is redirected to /dev/null, otherwise + # we may get output like + # 'unstable module has been loaded' + subcommand_load "${pmodule}" 2> /dev/null + fi reset_modulepath - reset_used_groups - PMODULES_HOME="${saved_home}" export_env MODULEPATH PMODULES_HOME } + ############################################################################## # # list [-hlt] From c55404a798237f5599784d64ef16d90b95f3e791 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 29 Apr 2021 19:29:42 +0200 Subject: [PATCH 36/94] modulecmd: better tmp file handling A global tmp file is created if the sub-command is 'load', 'purge' or 'search' and removed in the exit function. --- Pmodules/modulecmd.bash.in | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 744d64c..124c95d 100755 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -102,7 +102,7 @@ export_env() { declare g_env_must_be_saved='no' save_env() { - [[ ${g_env_must_be_saved} == 'no' ]] && return 0 + [[ $1 == 'no' ]] && return 0 local vars=( GroupDepths UsedReleases UseFlags UsedGroups ) vars+=( PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES ) vars+=( PMODULES_DEFAULT_RELEASES ) @@ -112,7 +112,12 @@ save_env() { export_env 'PMODULES_ENV' } -trap 'save_env ' EXIT +_exit() { + save_env "${g_env_must_be_saved}" + ${rm} -f "${tmpfile}" +} + +trap '_exit' EXIT # # get release of module @@ -515,8 +520,6 @@ subcommand_load() { test -r "${prefix}/.info" && cat "$_" 1>&2 test -r "${prefix}/.dependencies" && load_dependencies "$_" fi - local tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ - || std::die 1 "Oops: unable to create tmp file!\n" local output=$("${modulecmd}" 'bash' ${opts} 'load' \ "${current_modulefile}" 2> "${tmpfile}") @@ -1439,9 +1442,6 @@ subcommand_purge() { # run module purge # since we might have to reload a Pmodules module, we cannot # just run 'modulecmd ${Shell} purge' - local tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ - || std::die 1 "Oops: unable to create tmp file!\n" - local output=$("${modulecmd}" 'bash' 'purge' 2> "${tmpfile}") local error=$( < "${tmpfile}") @@ -1774,8 +1774,6 @@ subcommand_search() { search () { local -r module=$1 # write results to a temporary file for later processing - local -r tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \ - || std::die 1 "Oops: unable to create tmp file!" local group # loop over all groups for group in "${!GroupDepths[@]}"; do @@ -2251,6 +2249,13 @@ if (( ${#GroupDepths[@]} == 0 )); then scan_groups "${PMODULES_ROOT}" fi +case ${subcommand} in + load|purge|search ) + declare -r tmpfile=$( ${mktemp} /tmp/Pmodules.XXXXXX ) \ + || std::die 1 "Oops: unable to create tmp file!" + ;; +esac + declare options options=$( "${getopt}" ${Options[${subcommand}]} -- -- "${opts[@]}" "$@" ) \ || print_help "${subcommand}" From 2747861b523b7ca8e9464469f303951a1bb3d876 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 30 Apr 2021 15:23:44 +0200 Subject: [PATCH 37/94] modmanage: shebang fixed --- Pmodules/modmanage.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modmanage.bash.in b/Pmodules/modmanage.bash.in index 9a59809..acf750d 100755 --- a/Pmodules/modmanage.bash.in +++ b/Pmodules/modmanage.bash.in @@ -1,4 +1,4 @@ -#!@PMODULES_HOME@/sbin/bash +#!@BASH@ --noprofile # we have to unset CDPATH, otherwise 'cd' prints the directoy! unset CDPATH From 291039084b55d981e3a7122a70c58723989fa23c Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 30 Apr 2021 15:24:13 +0200 Subject: [PATCH 38/94] modmanage: hardcode CMD --- Pmodules/modmanage.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modmanage.bash.in b/Pmodules/modmanage.bash.in index acf750d..1f74361 100755 --- a/Pmodules/modmanage.bash.in +++ b/Pmodules/modmanage.bash.in @@ -4,7 +4,7 @@ unset CDPATH # used for some output only -declare -r CMD=$(basename "$0") +declare -r CMD='modmanage' declare -r mydir=$(cd $(dirname "$0") && pwd) declare -r prefix=$(dirname "${mydir}") From 8c4d911fa5bda535c3a6aaf461ff4566de3303db Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 30 Apr 2021 15:27:46 +0200 Subject: [PATCH 39/94] modmanage: don't use PATH to find commands --- Pmodules/modmanage.bash.in | 66 ++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/Pmodules/modmanage.bash.in b/Pmodules/modmanage.bash.in index 1f74361..62727e3 100755 --- a/Pmodules/modmanage.bash.in +++ b/Pmodules/modmanage.bash.in @@ -6,17 +6,37 @@ unset CDPATH # used for some output only declare -r CMD='modmanage' -declare -r mydir=$(cd $(dirname "$0") && pwd) -declare -r prefix=$(dirname "${mydir}") +dirname=$(PATH=/bin:/usr/bin which dirname) +declare -r dirname +uname=$(PATH=/bin:/usr/bin which uname) +declare -r uname +mkdir=$(PATH=/bin:/usr/bin which mkdir) +declare -r mkdir +rsync=$(PATH=/bin:/usr/bin which rsync) +declare -r rsync +rm=$(PATH=/bin:/usr/bin /usr/bin/which rm) +declare -r rm + +if [[ $(${uname} -s) == 'Darwin' ]]; then + declare -r getopt="${libexecdir}/getopt" + declare -r find="${libexecdir}/find" +else + getopt=$(PATH=/bin:/usr/bin /usr/bin/which getopt) + declare -r getopt + find=$(PATH=/bin:/usr/bin /usr/bin/which find) + declare -r find +fi + + +declare -r mydir=$(cd $(${dirname} "$0") && pwd) +declare -r prefix=$(${dirname} "${mydir}") declare -r bindir="${prefix}/bin" -declare -r sbindir="${prefix}/sbin" declare -r libdir="${prefix}/lib" declare -r libexecdir="${prefix}/libexec" -source "${libdir}/libstd.bash" -source "${libdir}/libpmodules.bash" -PATH="${sbindir}:${bindir}:${PATH}" +source "${libdir}/libstd.bash" + _exit () { std::die 1 "Interrupted..." @@ -205,7 +225,7 @@ get_module_prefix() { # $1: relative module file path # get_releasefile_name() { - echo "$(dirname "$1")/.release-$(basename "$1")" + echo "$(${dirname} "$1")/.release-$(basename "$1")" } ############################################################################## @@ -234,8 +254,8 @@ sync_module() { # install/update module if [[ ! -d "${target_prefix}/${rel_module_prefix}" ]] || [[ "${force}" == 'yes' ]]; then - $DRY mkdir -p "${target_prefix}/${rel_module_prefix}" || return $? - $DRY rsync --links --perms --recursive --delete \ + $DRY ${mkdir} -p "${target_prefix}/${rel_module_prefix}" || return $? + $DRY ${rsync} --links --perms --recursive --delete \ "${src_prefix}/${rel_module_prefix}/" \ "${target_prefix}/${rel_module_prefix}/" || exit $? fi @@ -246,8 +266,8 @@ sync_module() { # create target directory for module- and release-file if [[ -e "${src_modulefile}" ]] || [[ -e "${src_releasefile}" ]]; then - local dir=$( dirname "${target_modulefile}" ) - $DRY mkdir -p "${dir}" || return $? + local dir=$( ${dirname} "${target_modulefile}" ) + $DRY ${mkdir} -p "${dir}" || return $? fi # copy modulefile template @@ -260,20 +280,20 @@ sync_module() { local -r src_template="${src_prefix}/${template}" local -r target_template="${target_prefix}/${template}" if [[ -e "${src_template}" ]]; then - $DRY mkdir -p "${target_template}" - $DRY rsync --links --perms --recursive \ + $DRY ${mkdir} -p "${target_template}" + $DRY ${rsync} --links --perms --recursive \ "${src_template}" "${target_template}" || exit $? fi # copy modulefile if [[ -e "${src_modulefile}" ]]; then - $DRY rsync --links --perms --recursive \ + $DRY ${rsync} --links --perms --recursive \ "${src_modulefile}" "${target_modulefile}" || exit $? fi # copy release-file if [[ -e "${src_releasefile}" ]]; then - $DRY rsync --links --perms --recursive \ + $DRY ${rsync} --links --perms --recursive \ "${src_releasefile}" "${target_releasefile}" || exit $? fi @@ -290,9 +310,8 @@ sync_module() { sync_config() { src="$1/${PMODULES_CONFIG_DIR}/" dst="$2/${PMODULES_CONFIG_DIR}/" - $DRY rsync --recursive --links --perms --delete \ + $DRY ${rsync} --recursive --links --perms --delete \ "${src}" "${dst}" 2>/dev/null || return $? - sed -i.bak "s/PMODULES_VERSION=\(.*\)/PMODULES_VERSION=${PMODULES_VERSION}/" "${dst}/environment.bash" echo } @@ -416,7 +435,7 @@ environment at '${PMODULES_ROOT}' fi force='yes' echo "Creating target directory '${target_prefix}'..." - $DRY mkdir -p "${target_prefix}" || \ + $DRY ${mkdir} -p "${target_prefix}" || \ std::die 1 "Error: make directory failed!" echo @@ -430,13 +449,12 @@ environment at '${PMODULES_ROOT}' "${src_prefix}" \ "${target_prefix}" || \ std::die 1 "Error: sync Pmodules failed!" - mkdir -p "${target_prefix}/Tools/${PMODULES_MODULEFILES_DIR}" - echo dst="${target_prefix}/${PMODULES_CONFIG_DIR}/environment.bash" echo "Adding installation source '${src_prefix}' to '${dst}'..." sed -i.bak '/PMODULES_INSTALL_SOURCE/d' "${dst}" echo "declare -x PMODULES_INSTALL_SOURCE=\"${src_prefix}\"" >> "${dst}" + ${mkdir} -p "${target_prefix}/Tools/${PMODULES_MODULEFILES_DIR}" echo if [[ -n "${user}" ]]; then @@ -505,7 +523,7 @@ get_group_depths () { cd "${root}" local group for group in "${Groups[@]}"; do - local fname=$(find "${group}/${modulefiles_dir}" \ + local fname=$(${find} "${group}/${modulefiles_dir}" \ -depth \( -type f -o -type l \) -print -quit) [[ -n ${fname} ]] || continue local -a tmp @@ -591,7 +609,7 @@ subcommand_install() { [[ -z ${dep} ]] && continue # search for module with current modulepath and remember - local modulename=$(find "${modulepath[@]}" -path "*/${dep}" \ + local modulename=$(${find} "${modulepath[@]}" -path "*/${dep}" \ 2>/dev/null | head -n 1 ) [[ -n ${modulename} ]] || \ std::die 3 "Oops: required module '${dep}' not found!" @@ -606,7 +624,7 @@ subcommand_install() { modulepath+=( "${path}" ) fi done < "${tmpfile}" - rm "${tmpfile}" + ${rm} "${tmpfile}" } #...................................................................... @@ -729,7 +747,7 @@ subcommand_install() { map_to_family[$_key]=${_family} fi done < <({ cd "${src_prefix}" && \ - find */"${PMODULES_MODULEFILES_DIR}" \ + ${find} */"${PMODULES_MODULEFILES_DIR}" \ \( -type l -o -type f \) \! -name ".*"; } 2>/dev/null ) # From 47bccd5fa8f8062eaea33ea7d7b80b0720e1eee6 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 30 Apr 2021 15:30:17 +0200 Subject: [PATCH 40/94] modmange: functions from libpmodules.bash added --- Pmodules/modmanage.bash.in | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Pmodules/modmanage.bash.in b/Pmodules/modmanage.bash.in index 62727e3..6e11be2 100755 --- a/Pmodules/modmanage.bash.in +++ b/Pmodules/modmanage.bash.in @@ -345,11 +345,26 @@ delete_module() { # Initialize a new module environment in this directory- # subcommand_init() { + check_env() { + [[ -n "${PMODULES_ROOT}" ]] && + [[ -d "${PMODULES_ROOT}" ]] && + [[ -n "${PMODULES_HOME}" ]] && + [[ -n "${PMODULES_VERSION}" ]] || \ + std::die 1 " +Error: the module environment you are going to use as so urce has not been +initialized properly!" + + [[ -d "${src_prefix}/${PMODULES_CONFIG_DIR}" ]] && + [[ -d "${src_prefix}/Tools/Pmodules/${PMODULES_VERSION}" ]] || \ + std::die 1 " +Error: the module environment '${src_prefix}' has not been initialized properly!" + } + local src='' local target_prefixes=() local user='' local opts='' - opts=$(pmodules::get_options -o h -l src: -l user: -l help -l version: -- "$@") + opts=$(${getopt} -o h -l src: -l user: -l help -l version: -- "$@") if [[ $? != 0 ]]; then subcommand_help_init exit 1 @@ -407,7 +422,7 @@ subcommand_init() { std::die 1 "Error: --user option is only allowed if running as root!" fi - pmodules::check_env || \ + check_env || \ std::die 1 "Giving up..." echo " @@ -449,11 +464,6 @@ environment at '${PMODULES_ROOT}' "${src_prefix}" \ "${target_prefix}" || \ std::die 1 "Error: sync Pmodules failed!" - - dst="${target_prefix}/${PMODULES_CONFIG_DIR}/environment.bash" - echo "Adding installation source '${src_prefix}' to '${dst}'..." - sed -i.bak '/PMODULES_INSTALL_SOURCE/d' "${dst}" - echo "declare -x PMODULES_INSTALL_SOURCE=\"${src_prefix}\"" >> "${dst}" ${mkdir} -p "${target_prefix}/Tools/${PMODULES_MODULEFILES_DIR}" echo @@ -667,7 +677,7 @@ subcommand_install() { std::info "" } - opts=$(pmodules::get_options -o hf -l dry-run -l force -l with: -l release: -l help -l src: -- "$@") + opts=$(${getopt} -o hf -l dry-run -l force -l with: -l release: -l help -l src: -- "$@") if [[ $? != 0 ]]; then subcommand_help_install exit 1 From 415a94293121a35a066d717d4143242aea71bb27 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 09:11:44 +0200 Subject: [PATCH 41/94] libmodules.tcl: bugfixes in module-addgroup() handling overlays replacing(global) overlays were not handle properly --- Pmodules/libmodules.tcl | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/Pmodules/libmodules.tcl b/Pmodules/libmodules.tcl index d886a90..756f5c1 100644 --- a/Pmodules/libmodules.tcl +++ b/Pmodules/libmodules.tcl @@ -26,6 +26,7 @@ debug "loading libmodules" package require base64 set ::MODULEFILES_DIR "modulefiles" +set ::ol_replacing "r" proc _pmodules_parse_pmodules_env { } { debug "enter" @@ -65,33 +66,29 @@ proc module-addgroup { group } { set ::${group} $name set ::${group}_version $version - debug "mode=[module-info mode]" if { [module-info mode load] } { - array set overlayed_groups {} - foreach overlay [lreverse_n $::OverlayList 1] { + set overlays_to_add {} + foreach overlay $::OverlayList { + lappend overlays_to_add $overlay + debug $overlay + if { [string compare $::OverlayDict($overlay) $ol_replacing=] == 0 } { + break + } + } + foreach overlay [lreverse_n $overlays_to_add 1] { debug "overlay=$overlay" - if {![info exists overlayed_groups($group)]} { - debug "group=$group" - debug "::variant=$::variant" - set dir [file join \ - $overlay \ - $group \ - $::MODULEFILES_DIR \ - {*}$::variant] - if { [file isdirectory $dir] } { - debug "prepend $dir to MODULEPATH " - prepend-path MODULEPATH $dir - } + debug "group=$group" + debug "::variant=$::variant" + set dir [file join \ + $overlay \ + $group \ + $::MODULEFILES_DIR \ + {*}$::variant] + if { [file isdirectory $dir] } { + debug "prepend $dir to MODULEPATH " + prepend-path MODULEPATH $dir } - # don't add if overlayed - if { [string compare $::OverlayDict($overlay) "g"] == 0 } { - # get groups in this overlay - set dirs [glob -directory $overlay -type d {[A-Z]*}] - foreach dir $dirs { - set overlayed_groups([lindex [file split $dir] end]) 1 - } - } - } + } debug "end foreach" prepend-path UsedGroups $group } elseif { [module-info mode remove] } { @@ -120,6 +117,7 @@ proc module-addgroup { group } { $group \ $::MODULEFILES_DIR \ {*}$::variant] + debug "remove $dir" remove-path MODULEPATH $dir } remove-path UsedGroups $group From 325551eecdfc691c59bbb16bd4d9267b86b57343 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 09:19:46 +0200 Subject: [PATCH 42/94] modulecmd: fixes in adding/removing overlays bugfix in the code to prevent adding an overlay if modules are already loaded, same for removing more clear error message if an overlay cannot be added/removed use constants for overlay modifiers --- Pmodules/modulecmd.bash.in | 45 ++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 5d98ad6..5502845 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -49,6 +49,9 @@ else declare -r modulecmd="${libexecdir}/modulecmd.bin" fi +declare -r ol_hiding='h' +declare -r ol_replacing='r' + declare verbosity_lvl=${PMODULES_VERBOSITY:-'verbose'} # use default IFS @@ -878,7 +881,7 @@ get_available_modules() { # - new version and not hidden by overlay local name="${mod%/*}" if [[ -z "${modulenames[${name}]}" ]]; then - if [[ "${OverlayDict[$overlay]}" == 'h' ]]; then + if [[ "${OverlayDict[$overlay]}" == "${ol_hiding}" ]]; then modulenames[${name}]="${overlay}" else modulenames[${name}]='0' @@ -1353,11 +1356,16 @@ subcommand_use() { use () { use_overlay() { - if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then - std::die 3 "%s %s: %s -- %s" \ - "${CMD}" "${subcommand}" \ - "overlays can be added as long as no modules are loaded!" \ - "${overlay}" + if [[ -n ${LOADEDMODULES} ]]; then + if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then + std::error "%s %s: %s" \ + "${CMD}" "${subcommand}" \ + "overlay cannot be added since some modules are already loaded!" + std::die 3 "%s %s: %s -- %s" \ + "${CMD}" "${subcommand}" \ + "overlay failed" \ + "${overlay}" + fi fi local overlay='' local modifier='0' @@ -1365,7 +1373,7 @@ subcommand_use() { modifier=${1##*:} overlay=${1%:*} case ${modifier} in - g | h ) + ${ol_replacing} | ${ol_hiding} ) : ;; * ) @@ -1392,9 +1400,9 @@ subcommand_use() { return 0 fi - if [[ "${modifier}" == "g" ]]; then - # if this overlay hides groups, we have to remove - # the modules made available by other overlays + if [[ "${modifier}" == "${ol_replacing}" ]]; then + # if this overlay replaces groups, we have to remove + # the modules made available by other overlays in these groups for group in ${UsedGroups//:/ }; do # first test whether this group is in the to be added overlay local dir="${overlay}/" @@ -1558,11 +1566,16 @@ subcommand_unuse() { unset IFS unuse() { unuse_overlay() { - if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then - std::die 3 "%s %s: %s -- %s" \ - "${CMD}" "${subcommand}" \ - "overlays can NOT be removed as long as modules are loaded!" \ - "${overlay}" + if [[ -n ${LOADEDMODULES} ]]; then + if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then + std::error "%s %s: %s" \ + "${CMD}" "${subcommand}" \ + "overlay cannot be removed since some modules are still loaded!" + std::die 3 "%s %s: %s -- %s" \ + "${CMD}" "${subcommand}" \ + "overlay failed" \ + "${overlay}" + fi fi overlay=${overlay%:*} # ignore any modifier overlay=${overlay%/} # remove trailing '/' if there is one @@ -1582,7 +1595,7 @@ subcommand_unuse() { "not an used overlay" \ "${overlay}" - if [[ "${modifier}" == 'g' ]]; then + if [[ "${modifier}" == "${ol_replacing}" ]]; then # if this overlay hides groups, we have to re-add # the modules made available by other overlays for group in ${UsedGroups//:/ }; do From 9a0d55ed85b3ce769eef0315dc82dd74d63a8fa0 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 09:25:26 +0200 Subject: [PATCH 43/94] modulecmd: save environment after unloading a module --- Pmodules/modulecmd.bash.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 5502845..d593fc0 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -729,6 +729,7 @@ subcommand_unload() { PMODULES_HOME=${saved_home} export_env 'PMODULES_HOME' fi + g_env_must_be_saved='yes' } ############################################################################## From d25663a32e7d9f3453be59fb94bd971d72ea2b61 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 09:27:28 +0200 Subject: [PATCH 44/94] modulefile: bugfix in modifying PATH --- Pmodules/modulefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Pmodules/modulefile b/Pmodules/modulefile index 2a9311d..1893fdb 100644 --- a/Pmodules/modulefile +++ b/Pmodules/modulefile @@ -17,6 +17,8 @@ Pmodules are a hierarchical module environment based on Environment Modules. if { [module-info mode load] } { set PATH ":$::env(PATH):" if { [regexp -- {.*:(.*/Pmodules/[^:]*):} $PATH -> str] } { - remove-path PATH $str + if { [string compare $str $PREFIX/bin] != 0 } { + remove-path PATH $str + } } } From fcf37f8b44a0ca964b07a091749cd698d6e71569 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 28 Apr 2021 16:52:58 +0000 Subject: [PATCH 45/94] Pmodule modulefile: remove Pmodules bin dir from PATH in some cases it might happen that we have a Pmodules bin directory in PATH. This has to be removed if we load a Pmodule module. (cherry picked from commit d23fdf930a523796de8562dfb91a76cccd9b6ef1) --- Pmodules/modulefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Pmodules/modulefile b/Pmodules/modulefile index 65aa4c1..2a9311d 100644 --- a/Pmodules/modulefile +++ b/Pmodules/modulefile @@ -8,3 +8,15 @@ module-maintainer "Achim Gsell " module-help " Pmodules are a hierarchical module environment based on Environment Modules. " + +# +# It might be that '${PMODULES_ROOT}/Tools/Pmodules/VERSION' is in PATH. +# Why? With older version the PATH might have been set without loading +# a module. +# +if { [module-info mode load] } { + set PATH ":$::env(PATH):" + if { [regexp -- {.*:(.*/Pmodules/[^:]*):} $PATH -> str] } { + remove-path PATH $str + } +} From 2faf42a4e046250b936f9ac2dcd9f664b5df5a17 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 07:27:28 +0000 Subject: [PATCH 46/94] modulefile: bugfix in modifying PATH (cherry picked from commit d25663a32e7d9f3453be59fb94bd971d72ea2b61) --- Pmodules/modulefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Pmodules/modulefile b/Pmodules/modulefile index 2a9311d..1893fdb 100644 --- a/Pmodules/modulefile +++ b/Pmodules/modulefile @@ -17,6 +17,8 @@ Pmodules are a hierarchical module environment based on Environment Modules. if { [module-info mode load] } { set PATH ":$::env(PATH):" if { [regexp -- {.*:(.*/Pmodules/[^:]*):} $PATH -> str] } { - remove-path PATH $str + if { [string compare $str $PREFIX/bin] != 0 } { + remove-path PATH $str + } } } From daead01197aec7ef060b076edd75af765abfbbfd Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 07:25:26 +0000 Subject: [PATCH 47/94] modulecmd: save environment after unloading a module (cherry picked from commit 9a0d55ed85b3ce769eef0315dc82dd74d63a8fa0) --- Pmodules/modulecmd.bash.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 124c95d..f630ddf 100755 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -642,6 +642,7 @@ subcommand_unload() { PMODULES_HOME=${saved_home} export_env 'PMODULES_HOME' fi + g_env_must_be_saved='yes' } ############################################################################## From dc1ad90c70a16a6e2c4bebf0564140359ed100e6 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 11:28:10 +0200 Subject: [PATCH 48/94] modulecmd: align columns in sub-cmd avail --- Pmodules/modulecmd.bash.in | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) mode change 100755 => 100644 Pmodules/modulecmd.bash.in diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in old mode 100755 new mode 100644 index f630ddf..a49cdb9 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -875,14 +875,15 @@ subcommand_avail() { human_readable_output() { output_header - local -i column=$cols - local -i colsize=16 - for ((i=0; i<${#mods[@]}; i+=3 )); do + local -a available_modules=() + local mod='' + local -i max_length=1 + for ((i=0; i<${#mods[@]}; i+=3)); do if [[ ${verbosity_lvl} == 'verbose' ]]; then local release=${mods[i+1]} case ${mods[i+1]} in stable ) - mod=${mods[i]} + mod="${mods[i]}" ;; * ) mod="${mods[i]}(${release:0:1})" @@ -891,9 +892,17 @@ subcommand_avail() { else mod=${mods[i]} fi + local -i n=${#mod} + (( n > max_length )) && (( max_length=n )) + available_modules+=("${mod}") + done + IFS=$'\n' available_modules=($(sort <<<"${available_modules[*]}")) + unset IFS + local -i span=$(( max_length / 16 + 1 )) # compute column size + local -i colsize=$(( span * 16 )) # as multiple of 16 + local -i column=$cols # force a line-break + for mod in "${available_modules[@]}"; do local -i len=${#mod} - local -i span=$(( len / 16 + 1 )) - local -i colsize=$(( span * 16 )) if (( column+len >= cols )); then printf -- "\n" 1>&2 column=0 From e3299a1afa236804bb57352710a4c09270fce8d4 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 14:22:30 +0200 Subject: [PATCH 49/94] modulecmd: sub-cmd avail: pass group as argument to output function --- Pmodules/modulecmd.bash.in | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index a49cdb9..2534bab 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -818,9 +818,7 @@ subcommand_avail() { cols=$(tput cols) output_header() { - local caption=${dir/${PMODULES_ROOT}\/} - local caption=${caption/\/${PMODULES_MODULEFILES_DIR}/: } - local caption=${caption/: \//: } + local caption="$1" let i=($cols-${#caption})/2-2 printf -- "%0.s-" $(seq 1 $i) 1>&2 printf -- " %s " "${caption}" 1>&2 @@ -829,7 +827,7 @@ subcommand_avail() { } terse_output() { - output_header + output_header "$1" for (( i=0; i<${#mods[@]}; i+=3 )); do local mod=${mods[i]} local release=${mods[i+1]} @@ -855,7 +853,7 @@ subcommand_avail() { # # :FIXME: for the time being, this is the same as terse_output! long_output() { - output_header + output_header "$1" for (( i=0; i<${#mods[@]}; i+=3 )); do local mod=${mods[i]} local release=${mods[i+1]} @@ -873,7 +871,7 @@ subcommand_avail() { } human_readable_output() { - output_header + output_header "$1" local -a available_modules=() local mod='' @@ -968,7 +966,7 @@ subcommand_avail() { "${opt_use_releases}" \ "${dir}" [[ ${#mods[@]} == 0 ]] && continue - ${output_function} + ${output_function} "${group}" done done } From 6318a0a59186c3a7e0a9f69a9caa66ab3fb0161b Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 14:23:55 +0200 Subject: [PATCH 50/94] modulecmd: sub-cmd avail: group argument added It's now possible to list available modules in certain groups only. --- Pmodules/modulecmd.bash.in | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 2534bab..fa4cf9b 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -917,18 +917,15 @@ subcommand_avail() { } local pattern=() local output_function='human_readable_output' - local opt_all_groups='no' local opt_use_releases="${UsedReleases}" + local -A opt_groups=() + local val='' while (($# > 0)); do case $1 in - -H | --help ) + -H | --help | -\? ) print_help "${subcommand}" ;; - -a | --all ) - opt_all_groups='yes' - opt_use_releases="${PMODULES_DEFINED_RELEASES}" - ;; - --all-releases ) + -a | --all | --all-releases ) opt_use_releases="${PMODULES_DEFINED_RELEASES}" ;; -h | --human ) @@ -943,6 +940,15 @@ subcommand_avail() { -m | --machine ) output_function='machine_output' ;; + -g | --group | --group=* ) + if [[ $1 == --group=* ]]; then + val="${1/--group=}" + else + val="$2" + shift + fi + opt_groups[${val}]=1 + ;; -- | '' ) ;; * ) @@ -960,6 +966,11 @@ subcommand_avail() { local string for string in "${pattern[@]}"; do for dir in "${modulepath[@]}"; do + local group="${dir/${PMODULES_ROOT}\/}" + group="${group%%/*}" + if (( ${#opt_groups[@]} > 0 )) && [[ ! -v opt_groups[${group}] ]]; then + continue + fi get_available_modules \ mods \ "${string}" \ From f5351f025edcb7cc4f06d8aa1bd107a4918b796a Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 14:40:12 +0200 Subject: [PATCH 51/94] modulecmd: use default IFS --- Pmodules/modulecmd.bash.in | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index fa4cf9b..ddf0701 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -51,9 +51,8 @@ fi declare verbosity_lvl=${PMODULES_VERBOSITY:-'verbose'} -# we use newline as internal field separator -IFS=$' \t\n' -declare -r __IFS=${IFS} # used to restore IFS +# use default IFS +unset IFS shopt -s nullglob @@ -290,7 +289,7 @@ subcommand_load() { IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${__IFS} + unset IFS # # Test whether a given module is available. @@ -433,7 +432,7 @@ subcommand_load() { IFS=':' local -a toks=($m) - IFS=${__IFS} + unset IFS local group='' local release='' if is_group "${toks[0]}"; then @@ -962,7 +961,7 @@ subcommand_avail() { fi IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${__IFS} + unset IFS local string for string in "${pattern[@]}"; do for dir in "${modulepath[@]}"; do @@ -1052,7 +1051,7 @@ subcommand_use() { local -r subcommand='use' IFS=':' local -a modulepath=(${MODULEPATH}) - IFS=${__IFS} + unset IFS local add2path_func='std::append_path' group_is_used() { @@ -1843,7 +1842,7 @@ subcommand_search() { for ((j = -depth-2; j < -2; j += 2)); do deps+=( "${toks[*]: $j:2}" ); done - IFS=${__IFS} + unset IFS fi echo ${name} ${release} ${group} ${modulefile} \ From a3835d3f0b6bda05418bcc1fbe34dcd85a2fea90 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 18:12:44 +0200 Subject: [PATCH 52/94] libmodules.tcl: bugfix in module-addgroup{} --- Pmodules/libmodules.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/libmodules.tcl b/Pmodules/libmodules.tcl index 756f5c1..58e266d 100644 --- a/Pmodules/libmodules.tcl +++ b/Pmodules/libmodules.tcl @@ -71,7 +71,7 @@ proc module-addgroup { group } { foreach overlay $::OverlayList { lappend overlays_to_add $overlay debug $overlay - if { [string compare $::OverlayDict($overlay) $ol_replacing=] == 0 } { + if { [string compare $::OverlayDict($overlay) $::ol_replacing] == 0 } { break } } From ab1f6c263dade381017f486c19aa97eea3117eaa Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 18:14:07 +0200 Subject: [PATCH 53/94] modulecmd: fixed in sub-cmd avail - bugfix in loop collecting per group directories in MODULEPATH - use UsedGroups to loop over the groups, this defines a clear oder - in pmodules_init(): prepend groups to UseGroups instead of appending. This fixes an issue in the order the groups were listed. --- Pmodules/modulecmd.bash.in | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index ef24187..ba2e66b 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1185,27 +1185,26 @@ subcommand_avail() { IFS=':' local -a modulepath=(${MODULEPATH}) unset IFS - local overlay='' + local dir local group='' - local -a groups=() + local overlay='' for dir in "${modulepath[@]}"; do group='other' find_overlay overlay group "${dir}" - if [[ -v modulepath_${group} ]]; then - path+=("${dir}") - else - typeset -a modulepath_${group}="${dir}" - typeset -n path=modulepath_${group} - groups+=("${group}") + if [[ ! -v modulepath_${group} ]]; then + typeset -a modulepath_${group} fi + typeset -n path=modulepath_${group} + path+=("${dir}") done local p for p in "${pattern[@]}"; do - for group in "${groups[@]}"; do + for group in ${UsedGroups//:/ } other; do if (( ${#opt_groups[@]} > 0 )) && [[ ! -v opt_groups[${group}] ]]; then continue fi - declare -n path=modulepath_${group} + [[ -v modulepath_${group} ]] || continue + typeset -n path=modulepath_${group} get_available_modules \ mods \ "${p}" \ @@ -1807,7 +1806,7 @@ pmodules_init() { UsedGroups='' local group for group in ${PMODULES_DEFAULT_GROUPS}; do - std::append_path UsedGroups "${group}" + std::prepend_path UsedGroups "${group}" done g_env_must_be_saved='yes' } From 0ea9e54cc47bf128cf66dd88d6ea0061182976b0 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 6 May 2021 19:04:27 +0200 Subject: [PATCH 54/94] modulecmd: reinitialize Pmodules if Pmodules version changed --- Pmodules/modulecmd.bash.in | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index ddf0701..84b586e 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -102,7 +102,7 @@ declare g_env_must_be_saved='no' save_env() { [[ $1 == 'no' ]] && return 0 - local vars=( GroupDepths UsedReleases UseFlags UsedGroups ) + local vars=( Version GroupDepths UsedReleases UseFlags UsedGroups ) vars+=( PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES ) vars+=( PMODULES_DEFAULT_RELEASES ) @@ -1345,6 +1345,7 @@ reset_modulepath() { local dir="${root}/${group}/${PMODULES_MODULEFILES_DIR}" [[ -d "${dir}" ]] && std::prepend_path MODULEPATH "${dir}" done + g_env_must_be_saved='yes' } reset_used_groups() { @@ -1364,7 +1365,6 @@ reset_used_releases() { g_env_must_be_saved='yes' } - init_manpath() { std::replace_path MANPATH "${PMODULES_HOME%/*}/.*" @@ -1391,7 +1391,9 @@ pmodules_init() { declare -gx MODULEPATH='' declare -Ag GroupDepths='()' + unset UseFlags declare -Ag UseFlags=() + declare -g Version="${PMODULES_VERSION}" reset_modulepath reset_used_groups reset_used_releases @@ -2259,6 +2261,9 @@ fi if [[ -n ${PMODULES_ENV} ]]; then eval "$("${base64}" -d <<< "${PMODULES_ENV}" 2>/dev/null)" + if [[ -z ${Version} ]] || [[ ${Version} != ${PMODULES_VERSION} ]]; then + pmodules_init + fi else pmodules_init fi From 183e7f40a260ef6e09745183ce768986bab29daf Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 7 May 2021 15:51:28 +0200 Subject: [PATCH 55/94] libstd.bash: function to check Bash variable type added --- Pmodules/libstd.bash | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Pmodules/libstd.bash b/Pmodules/libstd.bash index eb8525d..e5a2f46 100644 --- a/Pmodules/libstd.bash +++ b/Pmodules/libstd.bash @@ -244,6 +244,33 @@ std::get_os_release() { ${func_map[${OS}]} } +std::get_type() { + local -a signature=$(typeset -p "$1") + case ${signature[1]} in + -Ai* ) + echo 'int dict' + ;; + -A* ) + echo 'dict' + ;; + -ai* ) + echo 'int array' + ;; + -a* ) + echo 'array' + ;; + -i* ) + echo 'integer' + ;; + -- ) + echo 'string' + ;; + * ) + echo 'none' + return 1 + esac +} + # Local Variables: # mode: sh # sh-basic-offset: 8 From bff9055b20cb0fa2cd4eb5b111218e57e4ce4aeb Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 7 May 2021 16:40:08 +0200 Subject: [PATCH 56/94] modulecmd: bugfix in tmp file setup/cleanup --- Pmodules/modulecmd.bash.in | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 84b586e..6937055 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1465,7 +1465,6 @@ subcommand_purge() { local output=$("${modulecmd}" 'bash' 'purge' 2> "${tmpfile}") local error=$( < "${tmpfile}") - ${rm} "${tmpfile}" if [[ "${error}" =~ ":ERROR:" ]]; then local s=${error%%$'\n'*} local error_txt='failed' @@ -1755,8 +1754,6 @@ subcommand_search() { func_print_line='print_line_csv' } - local -r tmpfile=$1 - if [[ "${opt_print_modulefiles}" == 'yes' ]]; then print_modulefiles elif [[ "${opt_print_csv}" == 'yes' ]]; then @@ -1852,7 +1849,6 @@ subcommand_search() { done done print_result "${tmpfile}" - ${rm} -f "${tmpfile}" } while (( $# > 0 )); do @@ -2277,6 +2273,9 @@ case ${subcommand} in declare -r tmpfile=$( ${mktemp} /tmp/Pmodules.XXXXXX ) \ || std::die 1 "Oops: unable to create tmp file!" ;; + * ) + declare -r tmpfile='' + ;; esac declare options From d32f04ea832c5043435e8aacad0d2ec9c31f7193 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 7 May 2021 16:41:00 +0200 Subject: [PATCH 57/94] modulecmd: bugfix in basic initialization --- Pmodules/modulecmd.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 6937055..e497fb2 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1394,8 +1394,8 @@ pmodules_init() { unset UseFlags declare -Ag UseFlags=() declare -g Version="${PMODULES_VERSION}" - reset_modulepath reset_used_groups + reset_modulepath reset_used_releases init_manpath export_env \ From ca4c530a5e27af157d4dd2bb21fb6a51fb520d59 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 10 May 2021 15:53:06 +0200 Subject: [PATCH 58/94] modulecmd: prevent loading Pmodules module if other modules are loaded --- Pmodules/modulecmd.bash.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index e497fb2..5599f5e 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -508,8 +508,20 @@ subcommand_load() { fi if [[ ${current_modulefile} =~ ${PMODULES_ROOT} ]] \ && [[ ! ${m} =~ / ]]; then + # the module is in our hierarchy but no version + # has been specified. We take the version from + # current_modulefile and append it m+="/${current_modulefile##*/}" fi + if [[ ${m} == Pmodules/* ]] && [[ -n ${LOADEDMODULES} ]]; then + std::error "%s %s: %s" \ + "${CMD}" "${subcommand}" \ + "cannot load a Pmodules module because other modules are already load!" + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "failed" \ + "${m}" + fi if [[ ":${LOADEDMODULES}:" =~ ":${m}:" ]]; then continue fi From fcec9f77c205095bdfc94e3a1252fda30985c3fa Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 10 May 2021 15:55:19 +0200 Subject: [PATCH 59/94] modulecmd: restore some env.vars after loading Pmodules module --- Pmodules/modulecmd.bash.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 5599f5e..871caf0 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -2270,7 +2270,16 @@ fi if [[ -n ${PMODULES_ENV} ]]; then eval "$("${base64}" -d <<< "${PMODULES_ENV}" 2>/dev/null)" if [[ -z ${Version} ]] || [[ ${Version} != ${PMODULES_VERSION} ]]; then + # the Pmodules version changed! + # we save _LMFILES_ and LOADEDMODULES and restore them + # later. Otherwise the Pmodules module would not be listed + # by module list + declare saved_LMFILES_="${_LMFILES_}" + declare saved_LOADEDMODULES="${LOADEDMODULES}" pmodules_init + _LMFILES_="${saved_LMFILES_}" + LOADEDMODULES="${saved_LOADEDMODULES}" + export_env _LMFILES_ LOADEDMODULES fi else pmodules_init From e0950bcd250d68946821041cf218a5fce1b2f004 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 11 May 2021 12:05:00 +0200 Subject: [PATCH 60/94] modulecmd: fix initialisation after loading a Pmodule module --- Pmodules/modulecmd.bash.in | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 871caf0..e449b61 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -2271,15 +2271,8 @@ if [[ -n ${PMODULES_ENV} ]]; then eval "$("${base64}" -d <<< "${PMODULES_ENV}" 2>/dev/null)" if [[ -z ${Version} ]] || [[ ${Version} != ${PMODULES_VERSION} ]]; then # the Pmodules version changed! - # we save _LMFILES_ and LOADEDMODULES and restore them - # later. Otherwise the Pmodules module would not be listed - # by module list - declare saved_LMFILES_="${_LMFILES_}" - declare saved_LOADEDMODULES="${LOADEDMODULES}" - pmodules_init - _LMFILES_="${saved_LMFILES_}" - LOADEDMODULES="${saved_LOADEDMODULES}" - export_env _LMFILES_ LOADEDMODULES + declare -g Version="${PMODULES_VERSION}" + g_env_must_be_saved='yes' fi else pmodules_init From 69bcb98a07c38706c5057f7b370d6c093459b203 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 11 May 2021 14:05:19 +0200 Subject: [PATCH 61/94] modulecmd: create a tmpdile for sub-cmd switch --- Pmodules/modulecmd.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index e449b61..799ee94 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -2283,7 +2283,7 @@ if (( ${#GroupDepths[@]} == 0 )); then fi case ${subcommand} in - load|purge|search ) + load|purge|search|switch ) declare -r tmpfile=$( ${mktemp} /tmp/Pmodules.XXXXXX ) \ || std::die 1 "Oops: unable to create tmp file!" ;; From fd21f982542835a93843f8ba120dc5f3c4584dc3 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 11 May 2021 15:09:20 +0200 Subject: [PATCH 62/94] modulecmd: optional overlay configuration in config file added --- Pmodules/modulecmd.bash.in | 47 +++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index f3400a0..f29f89f 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -49,6 +49,7 @@ else declare -r modulecmd="${libexecdir}/modulecmd.bin" fi +declare -r ol_normal='n' declare -r ol_hiding='h' declare -r ol_replacing='r' @@ -1374,7 +1375,8 @@ subcommand_use() { use () { use_overlay() { if [[ -n ${LOADEDMODULES} ]]; then - if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then + if [[ $LOADEDMODULES == *:* ]] \ + || [[ $LOADEDMODULES != Pmodules/* ]]; then std::error "%s %s: %s" \ "${CMD}" "${subcommand}" \ "overlay cannot be added since some modules are already loaded!" @@ -1385,24 +1387,29 @@ subcommand_use() { fi fi local overlay='' - local modifier='0' + local type="${ol_normal}" if [[ $1 == *:* ]]; then - modifier=${1##*:} + type=${1##*:} overlay=${1%:*} - case ${modifier} in - ${ol_replacing} | ${ol_hiding} ) - : - ;; - * ) - std::die 3 "%s %s: %s -- %s" \ - "${CMD}" "${subcommand}" \ - "invalid modifier '${modifier}!" \ - "${overlay}" - ;; - esac + elif [[ -d $1 ]] && [[ -r $1/config/overlay.conf ]]; then + overlay=$1 + source "${overlay}/config/overlay.conf" else overlay=$1 fi + + case ${type} in + ${ol_normal} | ${ol_replacing} | ${ol_hiding} ) + : + ;; + * ) + std::die 3 "%s %s: %s -- %s" \ + "${CMD}" "${subcommand}" \ + "invalid type '${type}!" \ + "${overlay}" + ;; + esac + overlay=${overlay%/} # remove trailing '/' if there is one [[ -d "${overlay}" ]] || \ std::die 3 "%s %s: %s -- %s" \ @@ -1417,7 +1424,7 @@ subcommand_use() { return 0 fi - if [[ "${modifier}" == "${ol_replacing}" ]]; then + if [[ "${type}" == "${ol_replacing}" ]]; then # if this overlay replaces groups, we have to remove # the modules made available by other overlays in these groups for group in ${UsedGroups//:/ }; do @@ -1442,7 +1449,7 @@ subcommand_use() { fi done - OverlayDict[${overlay}]=${modifier} + OverlayDict[${overlay}]=${type} OverlayList=( "${overlay}" "${OverlayList[@]}" ) export_env OverlayList g_env_must_be_saved='yes' @@ -1517,6 +1524,10 @@ subcommand_use() { fi local dir="$(cd "${arg}" && pwd)" + if [[ -r ${dir}/config/overlay.conf ]]; then + use_overlay "${dir}" + return + fi local overlay for overlay in "${OverlayList[@]}"; do if [[ ${dir}/ =~ ^${overlay}/ ]]; then @@ -1594,7 +1605,7 @@ subcommand_unuse() { "${overlay}" fi fi - overlay=${overlay%:*} # ignore any modifier + overlay=${overlay%:*} # ignore any type overlay=${overlay%/} # remove trailing '/' if there is one [[ -d "${overlay}" ]] || \ std::die 3 "%s %s: %s -- %s" \ @@ -1612,7 +1623,7 @@ subcommand_unuse() { "not an used overlay" \ "${overlay}" - if [[ "${modifier}" == "${ol_replacing}" ]]; then + if [[ "${OverlayDict[${overlay}]}" == "${ol_replacing}" ]]; then # if this overlay hides groups, we have to re-add # the modules made available by other overlays for group in ${UsedGroups//:/ }; do From f31dc385133cf45ae52cf17a59ed7ed180eae72a Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 20 May 2021 14:41:19 +0200 Subject: [PATCH 63/94] modulecmd: some unnecessary return statements removed after std::die --- Pmodules/modulecmd.bash.in | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index f29f89f..43b0633 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1512,7 +1512,6 @@ subcommand_use() { "${CMD}" "${subcommand}" \ "illegal group" \ "${arg}" - return fi # arg must be a directory! if [[ ! -d ${arg} ]]; then @@ -1520,7 +1519,6 @@ subcommand_use() { "${CMD}" "${subcommand}" \ "illegal argument" \ "${arg}" - return fi local dir="$(cd "${arg}" && pwd)" @@ -1700,7 +1698,6 @@ subcommand_unuse() { "${CMD}" "${subcommand}" \ "illegal group" \ "${arg}" - return fi # user wants to append a directory to MODULEPATH if [[ ! -d ${arg} ]]; then @@ -1708,21 +1705,14 @@ subcommand_unuse() { "${CMD}" "${subcommand}" \ "illegal argument" \ "${arg}" - return fi local dir="$(cd "${arg}" && pwd)" - local overlay - for overlay in "${OverlayList[@]}"; do - if [[ ${dir}/ =~ ^${overlay}/ ]]; then - # dir is in one of our used overlays - std::die 3 "%s %s: %s -- %s" \ - "${CMD}" "${subcommand}" \ - "illegal argument" \ - "${arg}" - return - fi - done + if [[ -r ${dir}/config/overlay.conf ]] || [[ -v OverlayDict[${dir}] ]]; then + unuse_overlay "${dir}" + return + fi + # argument is a modulepath std::remove_path MODULEPATH "${dir}" From 5941ded0d4828c9464271cad6711ff6b9208e19f Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 20 May 2021 14:52:46 +0200 Subject: [PATCH 64/94] modulecmd: more descriptive error message in sub-cmd use --- Pmodules/modulecmd.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 43b0633..3898101 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1517,7 +1517,7 @@ subcommand_use() { if [[ ! -d ${arg} ]]; then std::die 3 "%s %s: %s -- %s" \ "${CMD}" "${subcommand}" \ - "illegal argument" \ + "illegal argument: is neither a valid keyword, group nor directory" \ "${arg}" fi From 5c393560dfa495dec8f0a82b18658c2755a1f857 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 20 May 2021 14:54:03 +0200 Subject: [PATCH 65/94] modulecmd: re-using overlay check improved/simplified --- Pmodules/modulecmd.bash.in | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 3898101..2d79e3f 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1526,17 +1526,16 @@ subcommand_use() { use_overlay "${dir}" return fi - local overlay - for overlay in "${OverlayList[@]}"; do - if [[ ${dir}/ =~ ^${overlay}/ ]]; then - # dir is in one of our used overlays - std::die 3 "%s %s: %s -- %s" \ - "${CMD}" "${subcommand}" \ - "illegal argument" \ - "${arg}" - return - fi - done + # Is ${dir} a used overlay? + # Note: the config.file 'overlay.conf is *not* required + # in an overlay!' + if [[ -v OverlayDict[${dir}] ]]; then + std::die 3 "%s %s: %s -- %s" \ + "${CMD}" "${subcommand}" \ + "illegal argument: is already loaded as overlay" \ + "${dir}" + fi + # argument is a modulepath ${add2path_func} MODULEPATH "${dir}" } From 0b87dc8ac4e92a3911b1a29b43a6d06b5ba4b3ad Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 20 May 2021 14:57:37 +0200 Subject: [PATCH 66/94] modulecmd: bugfix in unuse an overlay - local declaration of overlay was missing --- Pmodules/modulecmd.bash.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 2d79e3f..d6b5d56 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1591,6 +1591,7 @@ subcommand_unuse() { unset IFS unuse() { unuse_overlay() { + local overlay="$1" if [[ -n ${LOADEDMODULES} ]]; then if [[ $LOADEDMODULES == *:* ]] || [[ $LOADEDMODULES != Pmodules/* ]]; then std::error "%s %s: %s" \ From 4f6b8c89b5684713977bd6ae335de0adbbb69347 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 20 May 2021 16:40:43 +0200 Subject: [PATCH 67/94] set version to 1.0.0rc10 --- config/versions.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/versions.conf b/config/versions.conf index 442193e..66ce460 100644 --- a/config/versions.conf +++ b/config/versions.conf @@ -4,5 +4,5 @@ findutils 4.7.0 getopt 1.1.6 gettext 0.21 modules 3.2.10.1 -Pmodules 1.0.0rc9 +Pmodules 1.0.0rc10 Tcl 8.6.10 From 4e2572211807d9a9def02df854976d58024aa03e Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 20 May 2021 16:41:30 +0200 Subject: [PATCH 68/94] set version to 1.1.2 --- config/versions.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/versions.conf b/config/versions.conf index f106cbc..15a3cf2 100644 --- a/config/versions.conf +++ b/config/versions.conf @@ -4,6 +4,6 @@ findutils 4.7.0 getopt 1.1.6 gettext 0.21 modules 3.2.10.1 -Pmodules 1.1.1 +Pmodules 1.1.2 Tcl 8.6.10 tcllib 1.20 From 8ba396930a7eb66dfd6d9ad1e21f56e9b089b4ee Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 25 May 2021 13:59:30 +0200 Subject: [PATCH 69/94] refactor variable PMODULES_DEFINED_RELEASES - new name is ReleaseStages - new name is ReleaseStages --- Pmodules/libpbuild.bash | 2 +- Pmodules/modulecmd.bash.in | 12 ++++++------ Pmodules/profile.bash.in | 2 +- Pmodules/profile.csh.in | 2 +- Pmodules/profile.zsh.in | 2 +- Pmodules/zsh | 4 ++-- config/modbuild.conf.in | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Pmodules/libpbuild.bash b/Pmodules/libpbuild.bash index 3404b63..50f5687 100644 --- a/Pmodules/libpbuild.bash +++ b/Pmodules/libpbuild.bash @@ -1302,7 +1302,7 @@ pbuild.build_module() { build_dependency() { local -r m=$1 std::debug "${m}: module not available" - local rels=( ${PMODULES_DEFINED_RELEASES//:/ } ) + local rels=( ${ReleaseStages//:/ } ) [[ ${dry_run} == yes ]] && \ std::die 1 \ "%s " \ diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 799ee94..71031c0 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -38,7 +38,7 @@ fi source "${libdir}/libstd.bash" -: ${PMODULES_DEFINED_RELEASES:=':unstable:stable:deprecated:'} +: ${ReleaseStages:=':unstable:stable:deprecated:'} declare -r version='@PMODULES_VERSION@' @@ -103,7 +103,7 @@ declare g_env_must_be_saved='no' save_env() { [[ $1 == 'no' ]] && return 0 local vars=( Version GroupDepths UsedReleases UseFlags UsedGroups ) - vars+=( PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES ) + vars+=( PMODULES_DEFAULT_GROUPS ReleaseStages ) vars+=( PMODULES_DEFAULT_RELEASES ) local s=$(typeset -p ${vars[@]}) @@ -151,7 +151,7 @@ get_release() { } is_release() { - [[ ${PMODULES_DEFINED_RELEASES} =~ :$1: ]] + [[ ${ReleaseStages} =~ :$1: ]] } # @@ -937,7 +937,7 @@ subcommand_avail() { print_help "${subcommand}" ;; -a | --all | --all-releases ) - opt_use_releases="${PMODULES_DEFINED_RELEASES}" + opt_use_releases="${ReleaseStages}" ;; -h | --human ) output_function='human_readable_output' @@ -1095,7 +1095,7 @@ subcommand_use() { std::info "\t${r}" done std::info "\nUnused releases:" - for r in ${PMODULES_DEFINED_RELEASES//:/ }; do + for r in ${ReleaseStages//:/ }; do if ! release_is_used $r; then std::info "\t${r}" fi @@ -1916,7 +1916,7 @@ subcommand_search() { done ;; -a | --all-releases ) - opt_use_releases="${PMODULES_DEFINED_RELEASES}" + opt_use_releases="${ReleaseStages}" ;; --src ) # :FIXME: do we have to add some sanity checks here? diff --git a/Pmodules/profile.bash.in b/Pmodules/profile.bash.in index 3cc380c..aec73c1 100644 --- a/Pmodules/profile.bash.in +++ b/Pmodules/profile.bash.in @@ -27,7 +27,7 @@ export PMODULES_DEFAULT_RELEASES export PMODULES_VERSION declare -x PMODULES_MODULEFILES_DIR='modulefiles' -declare -x PMODULES_DEFINED_RELEASES=':unstable:stable:deprecated:' +declare -x ReleaseStages=':unstable:stable:deprecated:' declare -x PMODULES_ROOT=$(cd $(dirname "${BASH_SOURCE}")/.. && pwd) declare -x PMODULES_CONFIG_DIR=$(basename $(cd $(dirname "${BASH_SOURCE}") && pwd)) diff --git a/Pmodules/profile.csh.in b/Pmodules/profile.csh.in index 0047bdb..b5b5843 100755 --- a/Pmodules/profile.csh.in +++ b/Pmodules/profile.csh.in @@ -14,7 +14,7 @@ endif ############################################################################# setenv PMODULES_MODULEFILES_DIR 'modulefiles' -setenv PMODULES_DEFINED_RELEASES ':unstable:stable:deprecated:' +setenv ReleaseStages ':unstable:stable:deprecated:' setenv PMODULES_ROOT "@PMODULES_ROOT@" setenv PMODULES_CONFIG_DIR 'config' diff --git a/Pmodules/profile.zsh.in b/Pmodules/profile.zsh.in index 83a2ac9..04b184e 100644 --- a/Pmodules/profile.zsh.in +++ b/Pmodules/profile.zsh.in @@ -20,7 +20,7 @@ declare -x PMODULES_VERSION ############################################################################# declare -x PMODULES_MODULEFILES_DIR='modulefiles' -declare -x PMODULES_DEFINED_RELEASES=':unstable:stable:deprecated:' +declare -x ReleaseStages=':unstable:stable:deprecated:' declare -x PMODULES_ROOT=$(cd $(dirname "${(%):-%N}")/.. && pwd) declare -x PMODULES_CONFIG_DIR=$(basename $(cd $(dirname "${(%):-%N}") && pwd)) diff --git a/Pmodules/zsh b/Pmodules/zsh index 80dc338..1ef378c 100644 --- a/Pmodules/zsh +++ b/Pmodules/zsh @@ -82,12 +82,12 @@ for r in ${PMODULES_DEFAULT_RELEASES[@]}; do usedreleases=( "${r}" ${(m)usedreleases:#${r}} ) done -eval $(save_env UsedReleases PMODULES_DEFAULT_RELEASES PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES) +eval $(save_env UsedReleases PMODULES_DEFAULT_RELEASES PMODULES_DEFAULT_GROUPS ReleaseStages) unset UsedReleases unset PMODULES_DEFAULT_RELEASES unset PMODULES_DEFAULT_GROUPS -unset PMODULES_DEFINED_RELEASES +unset ReleaseStages # initialize MANPATH with output of `man --path` if not set [[ -z "${MANPATH}" ]] && manpath=$( man --path ) diff --git a/config/modbuild.conf.in b/config/modbuild.conf.in index 60d33c3..e943e79 100644 --- a/config/modbuild.conf.in +++ b/config/modbuild.conf.in @@ -13,6 +13,6 @@ declare -x PMODULES_MODULEFILES_DIR='modulefiles' declare -x PMODULES_HOME="${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION}" declare -x PMODULES_DEFAULT_GROUPS='Tools Programming' -declare -x PMODULES_DEFINED_RELEASES=':unstable:stable:deprecated:' +declare ReleaseStages=':unstable:stable:deprecated:' declare -x PMODULES_DEFAULT_RELEASES='stable' From edd3fc40098c3a98a443da7d4dac03713b9ed0b8 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 25 May 2021 14:35:59 +0200 Subject: [PATCH 70/94] refactor variable PMODULES_DEFAULT_RELEASES - new name is DefaultUsedReleaseStages --- Pmodules/modulecmd.bash.in | 4 ++-- Pmodules/profile.bash.in | 4 ++-- Pmodules/profile.csh.in | 2 +- Pmodules/profile.zsh.in | 4 ++-- Pmodules/zsh | 6 +++--- config/modbuild.conf.in | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 71031c0..37dc83e 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -104,7 +104,7 @@ save_env() { [[ $1 == 'no' ]] && return 0 local vars=( Version GroupDepths UsedReleases UseFlags UsedGroups ) vars+=( PMODULES_DEFAULT_GROUPS ReleaseStages ) - vars+=( PMODULES_DEFAULT_RELEASES ) + vars+=( DefaultUsedReleaseStages ) local s=$(typeset -p ${vars[@]}) declare -g PMODULES_ENV=$( "${base64}" --wrap=0 <<< "$s" ) @@ -1371,7 +1371,7 @@ reset_used_groups() { reset_used_releases() { declare -g UsedReleases='' - for r in ${PMODULES_DEFAULT_RELEASES//:/ }; do + for r in ${DefaultUsedReleaseStages//:/ }; do std::append_path UsedReleases "${r}" done g_env_must_be_saved='yes' diff --git a/Pmodules/profile.bash.in b/Pmodules/profile.bash.in index aec73c1..851d5b8 100644 --- a/Pmodules/profile.bash.in +++ b/Pmodules/profile.bash.in @@ -7,7 +7,7 @@ : ${PMODULES_DEFAULT_GROUPS:='Tools Programming'} # set releases which should be available after initialization -: ${PMODULES_DEFAULT_RELEASES:='stable'} +: ${DefaultUsedReleaseStages:='stable'} # set default version : ${PMODULES_VERSION:=@PMODULES_VERSION@} @@ -23,7 +23,7 @@ # export PMODULES_DEFAULT_GROUPS -export PMODULES_DEFAULT_RELEASES +export DefaultUsedReleaseStages export PMODULES_VERSION declare -x PMODULES_MODULEFILES_DIR='modulefiles' diff --git a/Pmodules/profile.csh.in b/Pmodules/profile.csh.in index b5b5843..5baa5c4 100755 --- a/Pmodules/profile.csh.in +++ b/Pmodules/profile.csh.in @@ -1,7 +1,7 @@ #!/bin/tcsh setenv PMODULES_DEFAULT_GROUPS 'Tools Programming' -setenv PMODULES_DEFAULT_RELEASES 'stable' +setenv DefaultUsedReleaseStages 'stable' if ( ! $?PMODULES_VERSION ) then setenv PMODULES_VERSION "@PMODULES_VERSION@" endif diff --git a/Pmodules/profile.zsh.in b/Pmodules/profile.zsh.in index 04b184e..b8bb938 100644 --- a/Pmodules/profile.zsh.in +++ b/Pmodules/profile.zsh.in @@ -8,11 +8,11 @@ # declare -xa PMODULES_DEFAULT_GROUPS -declare -xa PMODULES_DEFAULT_RELEASES +declare -xa DefaultUsedReleaseStages declare -x PMODULES_VERSION : ${PMODULES_DEFAULT_GROUPS:=(Tools Programming)} -: ${PMODULES_DEFAULT_RELEASES:=(stable)} +: ${DefaultUsedReleaseStages:=(stable)} : ${PMODULES_VERSION:=@PMODULES_VERSION@} ############################################################################# diff --git a/Pmodules/zsh b/Pmodules/zsh index 1ef378c..2fda058 100644 --- a/Pmodules/zsh +++ b/Pmodules/zsh @@ -78,14 +78,14 @@ done # build initial list of used releases declare -x UsedReleases='' typeset -T UsedReleases usedreleases -for r in ${PMODULES_DEFAULT_RELEASES[@]}; do +for r in ${DefaultUsedReleaseStages[@]}; do usedreleases=( "${r}" ${(m)usedreleases:#${r}} ) done -eval $(save_env UsedReleases PMODULES_DEFAULT_RELEASES PMODULES_DEFAULT_GROUPS ReleaseStages) +eval $(save_env UsedReleases DefaultUsedReleaseStages PMODULES_DEFAULT_GROUPS ReleaseStages) unset UsedReleases -unset PMODULES_DEFAULT_RELEASES +unset DefaultUsedReleaseStages unset PMODULES_DEFAULT_GROUPS unset ReleaseStages diff --git a/config/modbuild.conf.in b/config/modbuild.conf.in index e943e79..5c28cd9 100644 --- a/config/modbuild.conf.in +++ b/config/modbuild.conf.in @@ -14,5 +14,5 @@ declare -x PMODULES_HOME="${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION}" declare -x PMODULES_DEFAULT_GROUPS='Tools Programming' declare ReleaseStages=':unstable:stable:deprecated:' -declare -x PMODULES_DEFAULT_RELEASES='stable' +declare DefaultUsedReleaseStages='stable' From 25129b57f776942fd18d6b5551f85c5a61fb25cf Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 25 May 2021 15:37:09 +0200 Subject: [PATCH 71/94] refactored PMODULES_DEFAULT_GROUPS to DefaultGroups --- Pmodules/csh | 2 +- Pmodules/modulecmd.bash.in | 4 ++-- Pmodules/profile.bash.in | 4 ++-- Pmodules/profile.csh.in | 2 +- Pmodules/profile.zsh.in | 4 ++-- Pmodules/zsh | 6 +++--- config/modbuild.conf.in | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Pmodules/csh b/Pmodules/csh index 854152a..5fb9926 100644 --- a/Pmodules/csh +++ b/Pmodules/csh @@ -35,7 +35,7 @@ unset prefix unset postfix setenv MODULEPATH -foreach group ( ${PMODULES_DEFAULT_GROUPS} ) +foreach group ( ${DefaultGroups} ) if ( "${MODULEPATH}" == "" ) then setenv MODULEPATH "${PMODULES_ROOT}/${group}/${PMODULES_MODULEFILES_DIR}" else diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 37dc83e..8ab7be5 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -103,7 +103,7 @@ declare g_env_must_be_saved='no' save_env() { [[ $1 == 'no' ]] && return 0 local vars=( Version GroupDepths UsedReleases UseFlags UsedGroups ) - vars+=( PMODULES_DEFAULT_GROUPS ReleaseStages ) + vars+=( DefaultGroups ReleaseStages ) vars+=( DefaultUsedReleaseStages ) local s=$(typeset -p ${vars[@]}) @@ -1363,7 +1363,7 @@ reset_modulepath() { reset_used_groups() { UsedGroups='' local group - for group in ${PMODULES_DEFAULT_GROUPS}; do + for group in ${DefaultGroups}; do std::append_path UsedGroups "${group}" done g_env_must_be_saved='yes' diff --git a/Pmodules/profile.bash.in b/Pmodules/profile.bash.in index 851d5b8..959c245 100644 --- a/Pmodules/profile.bash.in +++ b/Pmodules/profile.bash.in @@ -4,7 +4,7 @@ # in a system wide profile or in a user's profile. # set groups which should be available after initialization -: ${PMODULES_DEFAULT_GROUPS:='Tools Programming'} +: ${DefaultGroups:='Tools Programming'} # set releases which should be available after initialization : ${DefaultUsedReleaseStages:='stable'} @@ -22,7 +22,7 @@ # ${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION} # -export PMODULES_DEFAULT_GROUPS +export DefaultGroups export DefaultUsedReleaseStages export PMODULES_VERSION diff --git a/Pmodules/profile.csh.in b/Pmodules/profile.csh.in index 5baa5c4..79f20e7 100755 --- a/Pmodules/profile.csh.in +++ b/Pmodules/profile.csh.in @@ -1,6 +1,6 @@ #!/bin/tcsh -setenv PMODULES_DEFAULT_GROUPS 'Tools Programming' +setenv DefaultGroups 'Tools Programming' setenv DefaultUsedReleaseStages 'stable' if ( ! $?PMODULES_VERSION ) then setenv PMODULES_VERSION "@PMODULES_VERSION@" diff --git a/Pmodules/profile.zsh.in b/Pmodules/profile.zsh.in index b8bb938..4d36775 100644 --- a/Pmodules/profile.zsh.in +++ b/Pmodules/profile.zsh.in @@ -7,11 +7,11 @@ # ${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION} # -declare -xa PMODULES_DEFAULT_GROUPS +declare -xa DefaultGroups declare -xa DefaultUsedReleaseStages declare -x PMODULES_VERSION -: ${PMODULES_DEFAULT_GROUPS:=(Tools Programming)} +: ${DefaultGroups:=(Tools Programming)} : ${DefaultUsedReleaseStages:=(stable)} : ${PMODULES_VERSION:=@PMODULES_VERSION@} diff --git a/Pmodules/zsh b/Pmodules/zsh index 2fda058..e59c6f8 100644 --- a/Pmodules/zsh +++ b/Pmodules/zsh @@ -70,7 +70,7 @@ declare -x _LMFILES_='' # build initial MODULEPATH declare -x MODULEPATH='' typeset -T MODULEPATH modulepath -for group in ${PMODULES_DEFAULT_GROUPS[@]}; do +for group in ${DefaultGroups[@]}; do dir="${PMODULES_ROOT}/${group}/${PMODULES_MODULEFILES_DIR}" modulepath=( "${dir}" ${(m)modulepath:#${dir}} ) done @@ -82,11 +82,11 @@ for r in ${DefaultUsedReleaseStages[@]}; do usedreleases=( "${r}" ${(m)usedreleases:#${r}} ) done -eval $(save_env UsedReleases DefaultUsedReleaseStages PMODULES_DEFAULT_GROUPS ReleaseStages) +eval $(save_env UsedReleases DefaultUsedReleaseStages DefaultGroups ReleaseStages) unset UsedReleases unset DefaultUsedReleaseStages -unset PMODULES_DEFAULT_GROUPS +unset DefaultGroups unset ReleaseStages # initialize MANPATH with output of `man --path` if not set diff --git a/config/modbuild.conf.in b/config/modbuild.conf.in index 5c28cd9..bbf1032 100644 --- a/config/modbuild.conf.in +++ b/config/modbuild.conf.in @@ -12,7 +12,7 @@ declare -x PMODULES_MODULEFILES_DIR='modulefiles' declare -x PMODULES_HOME="${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION}" -declare -x PMODULES_DEFAULT_GROUPS='Tools Programming' +declare -x DefaultGroups='Tools Programming' declare ReleaseStages=':unstable:stable:deprecated:' declare DefaultUsedReleaseStages='stable' From 9b33e1723aff5aa0ed8eecd763f5423dc304228e Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 26 May 2021 16:42:50 +0200 Subject: [PATCH 72/94] build: tcllib added --- build | 7 +++++++ config/versions.conf | 1 + 2 files changed, 8 insertions(+) diff --git a/build b/build index 5e7febf..481d566 100755 --- a/build +++ b/build @@ -358,6 +358,10 @@ pmodules::compile() { build Tcl fi + if [[ ! -e "${PMODULES_HOME}/lib/tcllib1.20" ]] || [[ ${opt_force} == 'yes' ]]; then + build tcllib + fi + if [[ ! -e "${PMODULES_HOME}/libexec/modulecmd.bin" ]] || [[ ${opt_force} == 'yes' ]]; then build modules fi @@ -493,6 +497,9 @@ pmodules::install() { sed "${sed_cmd}" "${SRC_DIR}/modmanage.bash.in" > "${PMODULES_HOME}/libexec/modmanage.bash" chmod 0755 "${PMODULES_HOME}/libexec/modmanage.bash" + test -e "${PMODULES_ROOT}/${CONFIG_DIR}/Pmodules.conf" || \ + install -m 0644 "${SRC_DIR}/Pmodules.conf" "${PMODULES_ROOT}/${CONFIG_DIR}" + install -m 0644 "${SRC_DIR}/bash" "${PMODULES_HOME}/init" install -m 0644 "${SRC_DIR}/bash_completion" "${PMODULES_HOME}/init" install -m 0644 "${SRC_DIR}/csh" "${PMODULES_HOME}/init" diff --git a/config/versions.conf b/config/versions.conf index 66ce460..670deb3 100644 --- a/config/versions.conf +++ b/config/versions.conf @@ -6,3 +6,4 @@ gettext 0.21 modules 3.2.10.1 Pmodules 1.0.0rc10 Tcl 8.6.10 +tcllib 1.20 From 85c89df9f5ddd12ccfc68eeeb061db2741b65f1b Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 26 May 2021 16:43:38 +0200 Subject: [PATCH 73/94] initialization of Pmodules environment reviewed - introduce new configuration file ${PMODULES_ROOT}/config/Pmodules.conf - move as much as possible from profile.bash and init/bash to modulecmd - expose less environment variables to the user --- Pmodules/bash | 5 ++ Pmodules/libmodules.tcl | 16 ++++++ Pmodules/modulecmd.bash.in | 104 ++++++++++++++++++++++--------------- Pmodules/profile.bash.in | 25 --------- 4 files changed, 83 insertions(+), 67 deletions(-) diff --git a/Pmodules/bash b/Pmodules/bash index c7e9bf5..5afa1be 100644 --- a/Pmodules/bash +++ b/Pmodules/bash @@ -35,6 +35,11 @@ unset MODULE_VERSION_STACK unset MODULESHOME unset PMODULES_ENV +declare -x PMODULES_MODULEFILES_DIR='modulefiles' +declare -x PMODULES_CONFIG_DIR='config' +declare -x PMODULES_DIR="${PMODULES_HOME}" + + ############################################################################# # implement module comand as shell function # diff --git a/Pmodules/libmodules.tcl b/Pmodules/libmodules.tcl index e94b022..e8776a3 100644 --- a/Pmodules/libmodules.tcl +++ b/Pmodules/libmodules.tcl @@ -22,6 +22,22 @@ if {[info exists env(PMODULES_DEBUG)] && $env(PMODULES_DEBUG)} { debug "loading libmodules" +package require base64 + +proc _pmodules_parse_pmodules_env { } { + debug "enter" + foreach line [split [base64::decode $::env(PMODULES_ENV)] "\n"] { + if { ![regexp -- {.* -[aAx]* (.*)=\((.*)\)} $line -> name value] } { + continue + } + switch $name { + UsedGroups { + set ::UsedGroups $value + } + } + } +} + proc module-addgroup { group } { global env global name diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 8ab7be5..446da1d 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -38,10 +38,6 @@ fi source "${libdir}/libstd.bash" -: ${ReleaseStages:=':unstable:stable:deprecated:'} - -declare -r version='@PMODULES_VERSION@' - if [[ ${PMODULES_PURETCL} == yes ]]; then declare -r modulecmd="${libexecdir}/modulecmd.tcl" else @@ -62,8 +58,10 @@ declare -A Subcommands declare -A Options declare -A Help +declare -r pmodules_config_file="${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/Pmodules.conf" + Help['version']=" -Pmodules ${version} using Tcl Environment Modules @MODULES_VERSION@ +Pmodules @PMODULES_VERSION@ using Tcl Environment Modules @MODULES_VERSION@ Copyright GNU GPL v2 " @@ -89,6 +87,18 @@ export_env() { printf "${fmt}" "$1" "${!1}" shift done + # :FIXME: UsedGroups can be modified in libmodule.tcl using + # append-path/remove-path! But we keep the state in PMODULES_ENV + # so we don't have to export it. + # + case "${Shell}" in + sh | bash | zsh ) + echo "unset UsedGroups; " + ;; + csh | tcsh ) + echo "unsetenv UsedGroups; " + ;; + esac } # @@ -154,6 +164,42 @@ is_release() { [[ ${ReleaseStages} =~ :$1: ]] } +# +# compute depth of modulefile directory. +# +# Args: +# $1: absolute path of a modulefile directory +# +compute_group_depth () { + local -r dir=$1 + test -d "${dir}" || return 1 + local group=${dir%/*} + local group=${group##*/} + [[ -n "${GroupDepths[${group}]}" ]] && return 0 + local -i depth=$(${find} "${dir}" -depth \( -type f -o -type l \) \ + -printf "%d" -quit 2>/dev/null) + (( depth-=2 )) + # if a group doesn't contain a modulefile, depth is negativ + # :FIXME: better solution? + (( depth < 0 )) && (( depth = 0 )) + GroupDepths[$group]=${depth} + g_env_must_be_saved='yes' +} + +# +# (Re-)Scan available groups in given root and compute group depth's +# +# Args: +# $1: root of modulefile hierarchy +# +scan_groups () { + local -r root="$1" + local moduledir + for moduledir in ${root}/*/${PMODULES_MODULEFILES_DIR}; do + compute_group_depth "${moduledir}" + done +} + # # Check whether argument is a group # @@ -993,42 +1039,6 @@ subcommand_avail() { done } -# -# compute depth of modulefile directory. -# -# Args: -# $1: absolute path of a modulefile directory -# -compute_group_depth () { - local -r dir=$1 - test -d "${dir}" || return 1 - local group=${dir%/*} - local group=${group##*/} - [[ -n "${GroupDepths[${group}]}" ]] && return 0 - local -i depth=$(${find} "${dir}" -depth \( -type f -o -type l \) \ - -printf "%d" -quit 2>/dev/null) - (( depth-=2 )) - # if a group doesn't contain a modulefile, depth is negativ - # :FIXME: better solution? - (( depth < 0 )) && (( depth = 0 )) - GroupDepths[$group]=${depth} - g_env_must_be_saved='yes' -} - -# -# (Re-)Scan available groups in given root and compute group depth's -# -# Args: -# $1: root of modulefile hierarchy -# -scan_groups () { - local -r root="$1" - local moduledir - for moduledir in ${root}/*/${PMODULES_MODULEFILES_DIR}; do - compute_group_depth "${moduledir}" - done -} - ############################################################################## # # use [-a|--append|-p|--prepend] [directory|group|release...] @@ -1397,15 +1407,19 @@ init_manpath() { } pmodules_init() { + source "${pmodules_config_file}" || \ + std::die 3 "Oops: cannot parse config file -- %s\n" \ + "${pmodules_config_file}" + declare -gx LOADEDMODULES='' declare -gx _LMFILES_='' declare -gx UsedGroups='' declare -gx MODULEPATH='' - declare -Ag GroupDepths='()' unset UseFlags declare -Ag UseFlags=() declare -g Version="${PMODULES_VERSION}" + reset_used_groups reset_modulepath reset_used_releases @@ -2274,6 +2288,12 @@ if [[ -n ${PMODULES_ENV} ]]; then declare -g Version="${PMODULES_VERSION}" g_env_must_be_saved='yes' fi + if [[ -v DefaultGroups ]] || [[ -v DefaultUsedReleaseStages ]] || [[ -v ReleaseStages ]]; then + source "${pmodules_config_file}" || \ + std::die 3 "Oops: cannot parse config file -- %s\n" \ + "${pmodules_config_file}" + + fi else pmodules_init fi diff --git a/Pmodules/profile.bash.in b/Pmodules/profile.bash.in index 959c245..f25eee8 100644 --- a/Pmodules/profile.bash.in +++ b/Pmodules/profile.bash.in @@ -3,36 +3,11 @@ # The following settings are system defaults. They can be (re-)defined # in a system wide profile or in a user's profile. -# set groups which should be available after initialization -: ${DefaultGroups:='Tools Programming'} - -# set releases which should be available after initialization -: ${DefaultUsedReleaseStages:='stable'} - # set default version : ${PMODULES_VERSION:=@PMODULES_VERSION@} -############################################################################# -# N O C H A N G E S B E L O W T H I S L I N E ! # -# -# Notes: -# - PMODULES_ROOT is derived from the location of this file. -# - Some for PMODULES_CONFIG_DIR. -# - The Pmodules software must be installed in -# ${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION} -# - -export DefaultGroups -export DefaultUsedReleaseStages -export PMODULES_VERSION - -declare -x PMODULES_MODULEFILES_DIR='modulefiles' -declare -x ReleaseStages=':unstable:stable:deprecated:' - declare -x PMODULES_ROOT=$(cd $(dirname "${BASH_SOURCE}")/.. && pwd) -declare -x PMODULES_CONFIG_DIR=$(basename $(cd $(dirname "${BASH_SOURCE}") && pwd)) declare -x PMODULES_HOME="${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION}" -declare -x PMODULES_DIR="${PMODULES_HOME}" test -r "${PMODULES_HOME}/init/bash" && source "$_" From dfb133cae73e60836a4f440a3ecb140fadcc8ecb Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 26 May 2021 16:50:10 +0200 Subject: [PATCH 74/94] config/Pmodules.conf added --- Pmodules/Pmodules.conf | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Pmodules/Pmodules.conf diff --git a/Pmodules/Pmodules.conf b/Pmodules/Pmodules.conf new file mode 100644 index 0000000..5f9230c --- /dev/null +++ b/Pmodules/Pmodules.conf @@ -0,0 +1,8 @@ +# set groups which should be available after initialization +DefaultGroups='Tools Programming' + +# define available release stages +ReleaseStages=':unstable:stable:deprecated:' + +# set releases which should be available after initialization +DefaultUsedReleaseStages='stable' From fd6708352c3b847b1b4bffb7410095c2d23ec6ae Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 26 May 2021 16:50:41 +0200 Subject: [PATCH 75/94] tcllib added --- Tools/tcllib/build | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Tools/tcllib/build diff --git a/Tools/tcllib/build b/Tools/tcllib/build new file mode 100644 index 0000000..ea151ba --- /dev/null +++ b/Tools/tcllib/build @@ -0,0 +1,5 @@ +#!/usr/bin/env modbuild + +pbuild::set_download_url "https://core.tcl-lang.org/tcllib/uv/$P-$V.tar.xz" + + From b40297d1a42f38b8669d106ec709e329e748fc2c Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 26 May 2021 17:47:26 +0200 Subject: [PATCH 76/94] variable DefaultUsedReleaseStages renamed to DefaultReleaseStages --- Pmodules/Pmodules.conf | 2 +- Pmodules/modulecmd.bash.in | 6 +++--- Pmodules/profile.csh.in | 2 +- Pmodules/profile.zsh.in | 4 ++-- Pmodules/zsh | 6 +++--- config/modbuild.conf.in | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Pmodules/Pmodules.conf b/Pmodules/Pmodules.conf index 5f9230c..fffe8a3 100644 --- a/Pmodules/Pmodules.conf +++ b/Pmodules/Pmodules.conf @@ -5,4 +5,4 @@ DefaultGroups='Tools Programming' ReleaseStages=':unstable:stable:deprecated:' # set releases which should be available after initialization -DefaultUsedReleaseStages='stable' +DefaultReleaseStages='stable' diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 446da1d..713b786 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -114,7 +114,7 @@ save_env() { [[ $1 == 'no' ]] && return 0 local vars=( Version GroupDepths UsedReleases UseFlags UsedGroups ) vars+=( DefaultGroups ReleaseStages ) - vars+=( DefaultUsedReleaseStages ) + vars+=( DefaultReleaseStages ) local s=$(typeset -p ${vars[@]}) declare -g PMODULES_ENV=$( "${base64}" --wrap=0 <<< "$s" ) @@ -1381,7 +1381,7 @@ reset_used_groups() { reset_used_releases() { declare -g UsedReleases='' - for r in ${DefaultUsedReleaseStages//:/ }; do + for r in ${DefaultReleaseStages//:/ }; do std::append_path UsedReleases "${r}" done g_env_must_be_saved='yes' @@ -2288,7 +2288,7 @@ if [[ -n ${PMODULES_ENV} ]]; then declare -g Version="${PMODULES_VERSION}" g_env_must_be_saved='yes' fi - if [[ -v DefaultGroups ]] || [[ -v DefaultUsedReleaseStages ]] || [[ -v ReleaseStages ]]; then + if [[ -v DefaultGroups ]] || [[ -v DefaultReleaseStages ]] || [[ -v ReleaseStages ]]; then source "${pmodules_config_file}" || \ std::die 3 "Oops: cannot parse config file -- %s\n" \ "${pmodules_config_file}" diff --git a/Pmodules/profile.csh.in b/Pmodules/profile.csh.in index 79f20e7..b00013e 100755 --- a/Pmodules/profile.csh.in +++ b/Pmodules/profile.csh.in @@ -1,7 +1,7 @@ #!/bin/tcsh setenv DefaultGroups 'Tools Programming' -setenv DefaultUsedReleaseStages 'stable' +setenv DefaultReleaseStages 'stable' if ( ! $?PMODULES_VERSION ) then setenv PMODULES_VERSION "@PMODULES_VERSION@" endif diff --git a/Pmodules/profile.zsh.in b/Pmodules/profile.zsh.in index 4d36775..8077e79 100644 --- a/Pmodules/profile.zsh.in +++ b/Pmodules/profile.zsh.in @@ -8,11 +8,11 @@ # declare -xa DefaultGroups -declare -xa DefaultUsedReleaseStages +declare -xa DefaultReleaseStages declare -x PMODULES_VERSION : ${DefaultGroups:=(Tools Programming)} -: ${DefaultUsedReleaseStages:=(stable)} +: ${DefaultReleaseStages:=(stable)} : ${PMODULES_VERSION:=@PMODULES_VERSION@} ############################################################################# diff --git a/Pmodules/zsh b/Pmodules/zsh index e59c6f8..f1a0a4c 100644 --- a/Pmodules/zsh +++ b/Pmodules/zsh @@ -78,14 +78,14 @@ done # build initial list of used releases declare -x UsedReleases='' typeset -T UsedReleases usedreleases -for r in ${DefaultUsedReleaseStages[@]}; do +for r in ${DefaultReleaseStages[@]}; do usedreleases=( "${r}" ${(m)usedreleases:#${r}} ) done -eval $(save_env UsedReleases DefaultUsedReleaseStages DefaultGroups ReleaseStages) +eval $(save_env UsedReleases DefaultReleaseStages DefaultGroups ReleaseStages) unset UsedReleases -unset DefaultUsedReleaseStages +unset DefaultReleaseStages unset DefaultGroups unset ReleaseStages diff --git a/config/modbuild.conf.in b/config/modbuild.conf.in index bbf1032..cfce2aa 100644 --- a/config/modbuild.conf.in +++ b/config/modbuild.conf.in @@ -14,5 +14,5 @@ declare -x PMODULES_HOME="${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION}" declare -x DefaultGroups='Tools Programming' declare ReleaseStages=':unstable:stable:deprecated:' -declare DefaultUsedReleaseStages='stable' +declare DefaultReleaseStages='stable' From d5925192522dcdeb4761696903fe22384e320a63 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 2 Jun 2021 13:56:28 +0200 Subject: [PATCH 77/94] use term release stage instead of release - refactor variables and function names - internal: refactor UseFlags -> UsedFlags and change type to normal array --- Pmodules/modulecmd.bash.in | 259 ++++++++++++++++++------------------- 1 file changed, 129 insertions(+), 130 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 713b786..a7274da 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -112,9 +112,11 @@ declare g_env_must_be_saved='no' save_env() { [[ $1 == 'no' ]] && return 0 - local vars=( Version GroupDepths UsedReleases UseFlags UsedGroups ) - vars+=( DefaultGroups ReleaseStages ) - vars+=( DefaultReleaseStages ) + local vars=( Version ) + vars+=( UsedReleaseStages UsedFlags UsedGroups ) + vars+=( DefaultGroups DefaultReleaseStages ) + vars+=( ReleaseStages ) + vars+=( GroupDepths ) local s=$(typeset -p ${vars[@]}) declare -g PMODULES_ENV=$( "${base64}" --wrap=0 <<< "$s" ) @@ -129,16 +131,16 @@ _exit() { trap '_exit' EXIT # -# get release of module +# get release stage of module # Note: -# - the release of a modulefile outside ${PMODULES_ROOT} is 'stable' -# - the release of a modulefile inside ${PMODULES_ROOT} without a -# coresponding release file is 'unstable' +# - the release stage of a modulefile outside ${PMODULES_ROOT} is 'stable' +# - the release stage of a modulefile inside ${PMODULES_ROOT} without a +# coresponding file is 'unstable' # # Args: # $1: absolute modulefile name # -get_release() { +get_release_stage() { local "$1" local -r modulefile="$2" @@ -149,10 +151,10 @@ get_release() { fi # we are inside ${PMODULES_ROOT} - local -r releasefile="${modulefile%/*}/.release-${modulefile##*/}" - if [[ -r ${releasefile} ]]; then - # read releasefile, remove empty lines, spaces etc - local -r data=$( < "${releasefile}" ) + local -r rel_stage_file="${modulefile%/*}/.release-${modulefile##*/}" + if [[ -r ${rel_stage_file} ]]; then + # read file, remove empty lines, spaces etc + local -r data=$( < "${rel_stage_file}" ) std::upvar $1 "${data}" else std::upvar $1 'unstable' @@ -160,7 +162,7 @@ get_release() { return 0 } -is_release() { +is_release_stage() { [[ ${ReleaseStages} =~ :$1: ]] } @@ -328,7 +330,7 @@ USAGE: subcommand_load() { local -r subcommand='load' - local release='undef' + local rel_stage='undef' local current_modulefile='' local prefix='' local m='' @@ -361,12 +363,12 @@ subcommand_load() { # # possible return values: # 0: module is loadable - # 1: either not a modulefile or unsused release + # 1: either not a modulefile or unsused release stage # # The following variables in the enclosing function are set: # current_modulefile # prefix - # release + # rel_stage # is_available() { local m=$1 @@ -387,7 +389,7 @@ subcommand_load() { current_modulefile="${array[0]}" prefix="${array[1]}" test -n "${current_modulefile}" || return 1 - get_release release "${current_modulefile}" "${UsedReleases}" + get_release_stage rel_stage "${current_modulefile}" "${UsedReleaseStages}" } # @@ -401,11 +403,11 @@ subcommand_load() { # none output_load_hints() { local output='' - local release='' + local rel_stage='' while read -a line; do - release=${line[1]} - if [[ ! ":${UsedReleases}:" =~ "${release}" ]]; then - output+="module use ${release}; " + rel_stage=${line[1]} + if [[ ! ":${UsedReleaseStages}:" =~ "${rel_stage}" ]]; then + output+="module use ${rel_stage}; " fi local group=${line[2]} if [[ ! ":${UsedGroups}:" =~ ":${group}:" ]] && \ @@ -471,22 +473,22 @@ subcommand_load() { # extendet module name is either # - group:name or - # - group:name:release or - # - release:name or - # - release:group:name or - # - name:release + # - group:name:rel_stage or + # - rel_stage:name or + # - rel_stage:group:name or + # - name:rel_stage IFS=':' local -a toks=($m) unset IFS local group='' - local release='' + local rel_stage='' if is_group "${toks[0]}"; then group=${toks[0]} m=${toks[1]} - release=${toks[2]} - elif is_release "${toks[0]}"; then - release=${toks[0]} + rel_stage=${toks[2]} + elif is_release_stage "${toks[0]}"; then + rel_stage=${toks[0]} if is_group "${toks[1]}"; then group=${toks[1]} m=${toks[2]} @@ -498,9 +500,9 @@ subcommand_load() { m=${toks[0]} if is_group "${toks[1]}"; then group=${toks[1]} - release=${toks[2]} + rel_stage=${toks[2]} else - release=${toks[1]} + rel_stage=${toks[1]} group=${toks[2]} fi fi @@ -520,32 +522,26 @@ subcommand_load() { MODULEPATH+="${PMODULES_MODULEFILES_DIR}" modulepath=( ${MODULEPATH} ) fi - if [[ -n ${release} ]]; then - is_release "${release}" || \ + if [[ -n ${rel_stage} ]]; then + is_release_stage "${rel_stage}" || \ std::die 3 "%s %s: %s -- %s\n" \ "${CMD}" "${subcommand}" \ - "illegal release name" - "${release}" - std::append_path UsedReleases "${release}" + "illegal release stage" + "${rel_stage}" + std::append_path UsedReleaseStages "${rel_stage}" g_env_must_be_saved='yes' fi fi local found='' - for flag in "${!UseFlags[@]}"; do + for flag in "${UsedFlags[@]/#/_}" ''; do # :FIXME: this doesn't work if ${m} is a # modulename without version - if is_available "${m}_${flag}"; then - m+="_${flag}" + if is_available "${m}"; then + m+="${flag}" found=':' break fi done - if [[ ! "${found}" ]]; then - # no use-flags set - if is_available "${m}"; then - found=':' - fi - fi if [[ ! "${found}" ]]; then std::info "%s %s: module unavailable -- %s" \ "${CMD}" 'load' "${m}" @@ -614,10 +610,10 @@ subcommand_load() { local msg=$(printf "%s %s: %s -- %s" \ "${CMD}" 'load' \ - "${release} module has been loaded" \ + "${rel_stage} module has been loaded" \ "${m}") if [[ ${verbosity_lvl} != silent ]] && \ - [[ ${release} != stable ]]; then + [[ ${rel_stage} != stable ]]; then std::info "%s" "${msg}" fi ${logger} -t Pmodules "${msg}" @@ -803,27 +799,27 @@ subcommand_show() { # # get all available modules in given directory. # return list like -# modulename1 release1 modulename2 release2 ... +# modulename_1 rel_stage_1 modulefile_1 modulename_2 rel_stage_2 modulefile_1 ... # get_available_modules() { local var="$1" local -r module="$2" - local -r use_releases="${3:-${UsedReleases}}" + local -r used_rel_stages="${3:-${UsedReleaseStages}}" shift 3 # in the for loop below we use $@ to loop over the directories local -a mods=() - local release - local dir='' + local rel_stage='' + local dir='' for dir in "$@"; do test -d "${dir}" || continue { cd "${dir}" while read mod; do - get_release release "${dir}/${mod}" + get_release_stage rel_stage "${dir}/${mod}" - if [[ :${use_releases}: =~ :${release}: ]]; then - mods+=( "${mod}" ${release} "${dir}/${mod}") + if [[ :${used_rel_stages}: =~ :${rel_stage}: ]]; then + mods+=( "${mod}" ${rel_stage} "${dir}/${mod}") fi done < <(${find} -L * \( -type f -o -type l \) -not -name ".*" -ipath "${module}*") } @@ -836,7 +832,7 @@ get_available_modules() { # avail [-hlt] [...] # Subcommands[avail]='avail' -Options[avail]='-l help -o Hahlmt -l all -l all-releases -l human -l long -l machine -l terse' +Options[avail]='-l help -o Hahlmt -l all -l all-release-stages -l human -l long -l machine -l terse' Help[avail]=" USAGE: module avail [switches] string @@ -850,8 +846,8 @@ USAGE: e.g. a compiler, or with the sub-command 'use'. SWITCHES: - -a|--all||--all-releases - List all available modules independend of the release. + -a|--all||--all-release-stages + List all available modules independend of the release stage. -t|--terse Output in short format. @@ -885,15 +881,16 @@ subcommand_avail() { terse_output() { output_header "$1" - for (( i=0; i<${#mods[@]}; i+=3 )); do + local -i i=0 + for i in ${!mods[@]}; do local mod=${mods[i]} - local release=${mods[i+1]} - case $release in + local rel_stage=${mods[i+1]} + case ${rel_stage} in stable ) out='' ;; * ) - out="${release}" + out="${rel_stage}" ;; esac printf "%-20s\t%s\n" "${mod}" "${out}" 1>&2 @@ -913,13 +910,13 @@ subcommand_avail() { output_header "$1" for (( i=0; i<${#mods[@]}; i+=3 )); do local mod=${mods[i]} - local release=${mods[i+1]} - case $release in + local rel_stage=${mods[i+1]} + case ${rel_stage} in stable ) out='' ;; * ) - out=${release} + out=${rel_stage} ;; esac printf "%-20s\t%s\n" "${mod}" "${out}" 1>&2 @@ -935,13 +932,13 @@ subcommand_avail() { local -i max_length=1 for ((i=0; i<${#mods[@]}; i+=3)); do if [[ ${verbosity_lvl} == 'verbose' ]]; then - local release=${mods[i+1]} - case ${mods[i+1]} in + local rel_stage=${mods[i+1]} + case ${rel_stage} in stable ) mod="${mods[i]}" ;; * ) - mod="${mods[i]}(${release:0:1})" + mod="${mods[i]}(${rel_stage:0:1})" ;; esac else @@ -974,7 +971,7 @@ subcommand_avail() { } local pattern=() local output_function='human_readable_output' - local opt_use_releases="${UsedReleases}" + local opt_use_rel_stages="${UsedReleaseStages}" local -A opt_groups=() local val='' while (($# > 0)); do @@ -982,8 +979,8 @@ subcommand_avail() { -H | --help | -\? ) print_help "${subcommand}" ;; - -a | --all | --all-releases ) - opt_use_releases="${ReleaseStages}" + -a | --all | --all-release-stages ) + opt_use_rel_stages="${ReleaseStages}" ;; -h | --human ) output_function='human_readable_output' @@ -1031,7 +1028,7 @@ subcommand_avail() { get_available_modules \ mods \ "${string}" \ - "${opt_use_releases}" \ + "${opt_use_rel_stages}" \ "${dir}" [[ ${#mods[@]} == 0 ]] && continue ${output_function} "${group}" @@ -1041,17 +1038,17 @@ subcommand_avail() { ############################################################################## # -# use [-a|--append|-p|--prepend] [directory|group|release...] +# use [-a|--append|-p|--prepend] [directory|group|release_stage...] # Subcommands[use]='use' Options[use]='-l help -o Hap -l append -l prepend' Help[use]=" USAGE: - module use [-a|--append|-p|--prepend] [directory|group|release...] + module use [-a|--append|-p|--prepend] [directory|group|release_stage|...] Without arguments this sub-command displays information about - the module search path, used families and releases. You can - use this sub-command to get a list of available families and - releases. + the module search path, used groups and release stages. You can + use this sub-command to get a list of available groups and + releases stages. With a directory as argument, this directory will either be prepended or appended to the module search path. The default @@ -1080,10 +1077,6 @@ subcommand_use() { [[ :${UsedGroups}: =~ :$1: ]] } - release_is_used() { - [[ ":${UsedReleases}:" =~ :$1: ]] - } - print_info() { local f local r @@ -1100,19 +1093,17 @@ subcommand_use() { fi done - std::info "\nUsed releases:" - for r in ${UsedReleases//:/ }; do + std::info "\nUsed releases stages:" + for r in ${UsedReleaseStages//:/ }; do std::info "\t${r}" done - std::info "\nUnused releases:" + std::info "\nUnused release stages:" for r in ${ReleaseStages//:/ }; do - if ! release_is_used $r; then - std::info "\t${r}" - fi + [[ ":${UsedReleaseStages}:" =~ :$r: ]] && std::info "\t${r}" done std::info "\nUsed flags:" - for flag in "${!UseFlags[@]}"; do + for flag in "${UsedFlags[@]}"; do std::info "\t${flag}" done @@ -1133,14 +1124,14 @@ subcommand_use() { use () { local arg=$1 - if is_release "${arg}"; then - # argument is release - std::append_path UsedReleases "${arg}" + if is_release_stage "${arg}"; then + # argument is release stage + std::append_path UsedReleaseStages "${arg}" return fi if [[ "${arg}" =~ "flag=" ]]; then # argument is flag - UseFlags["${arg/flag=}"]=1 + UsedFlags+=( "${arg/flag=}" ) return fi if [[ -z ${GroupDepths[${arg}]} ]] && [[ -d "${PMODULES_ROOT}/${arg}" ]]; then @@ -1221,14 +1212,14 @@ subcommand_use() { ############################################################################## # -# unuse directory|group|release... +# unuse directory|group|release_stage|... # Subcommands[unuse]='unuse' Options[unuse]='-o H -l help' Help[unuse]=' unuse directory|group|release... - Remove the given directory, group or release from the search - path. + Remove the given modulefiles directory, group, release stage, + flag or overlay from the search path. ' subcommand_unuse() { @@ -1236,14 +1227,18 @@ subcommand_unuse() { unuse() { local arg=$1 - if is_release "${arg}"; then - # argument is release - std::remove_path UsedReleases "${arg}" + if is_release_stage "${arg}"; then + # argument is release stage + std::remove_path UsedReleaseStages "${arg}" return fi if [[ "${arg}" =~ "flag=" ]]; then # argument is flag - unset UseFlags["${arg/flag=}"] + local flag="${arg/flag=}" + local i + for i in ${!UsedFlags[@]}; do + [[ ${UsedFlags[i]} == ${flag} ]] && unset UsedFlags[i] + done return fi if [[ -n ${GroupDepths[${arg}]} ]] && @@ -1380,9 +1375,9 @@ reset_used_groups() { } reset_used_releases() { - declare -g UsedReleases='' + declare -g UsedReleaseStages='' for r in ${DefaultReleaseStages//:/ }; do - std::append_path UsedReleases "${r}" + std::append_path UsedReleaseStages "${r}" done g_env_must_be_saved='yes' } @@ -1411,14 +1406,13 @@ pmodules_init() { std::die 3 "Oops: cannot parse config file -- %s\n" \ "${pmodules_config_file}" - declare -gx LOADEDMODULES='' - declare -gx _LMFILES_='' - declare -gx UsedGroups='' - declare -gx MODULEPATH='' - declare -Ag GroupDepths='()' - unset UseFlags - declare -Ag UseFlags=() - declare -g Version="${PMODULES_VERSION}" + declare -gx LOADEDMODULES='' + declare -gx _LMFILES_='' + declare -gx UsedGroups='' + declare -gx MODULEPATH='' + declare -Ag GroupDepths='()' + declare -ag UsedFlags=() + declare -g Version="${PMODULES_VERSION}" reset_used_groups reset_modulepath @@ -1615,7 +1609,7 @@ subcommand_clear() { # Subcommands[search]='search' Options[search]='-o aH -l help -l no-header -l print-modulefiles ' -Options[search]+='-l release: -l with: -l all-releases -l src: -l print-csv ' +Options[search]+='-l release-stage: -l with: -l all-release-stages -l src: -l print-csv ' Options[search]+='-l verbose ' Options[search]+='-l all-deps -l wrap' Help[search]=' @@ -1625,7 +1619,7 @@ USAGE: for modules whose name match the argument. SWITCHES: - -a|--all-releases + -a|--all-release-stages Search within all releases. --all-deps @@ -1634,10 +1628,10 @@ SWITCHES: --no-header Suppress output of a header. - --release=RELEASE - Search for modules within this release. You can specify this - switch multiple times. Without this switch, the used releases - will be searched. + --release-stage=RELEASE_STAGE + Search for modules within this release stage. You can specify + this switch multiple times. Without this switch, the release + stages in use will be searched. --verbose vebose output @@ -1697,7 +1691,7 @@ subcommand_search() { print_header_default() { std::info '' - std::info "${fmt}" "Module" "Release" "Group" "Requires" + std::info "${fmt}" "Module" "Rel.stage" "Group" "Requires" std::info '-%.0s' $(seq 1 ${cols}) } @@ -1736,7 +1730,7 @@ subcommand_search() { print_header_verbose() { std::info '' - std::info "${fmt}" "Module" "Release" "Group" "Dependencies/Modulefile" + std::info "${fmt}" "Module" "Rel.stage" "Group" "Dependencies/Modulefile" std::info '-%.0s' $(seq 1 ${cols}) } @@ -1830,19 +1824,18 @@ subcommand_search() { local modulepath=( ${src_prefix[@]/%//${group}/modulefiles$s} ) # get and print all available modules in $mpath - # with respect to the requested releases - # tmpfile: module/version release group group- - # dependencies... + # with respect to the requested release stage + # tmpfile: module/version rel_stage group dependencies... local mods get_available_modules \ mods \ "${module}" \ - "${opt_use_releases}" \ + "${opt_use_rel_stages}" \ "${modulepath[@]}" \ for (( i=0; i<${#mods[@]}; i+=3 )); do local name=${mods[i]} - local release=${mods[i+1]} + local rel_stage=${mods[i+1]} local modulefile=${mods[i+2]} if (( ${#name} > max_len_modulename)); then @@ -1870,7 +1863,7 @@ subcommand_search() { unset IFS fi - echo ${name} ${release} ${group} ${modulefile} \ + echo ${name} ${rel_stage} ${group} ${modulefile} \ ${deps[@]} >> "${tmpfile}" done done @@ -1896,19 +1889,19 @@ subcommand_search() { opt_print_csv='yes' opt_print_header='no' ;; - --release | --release=* ) + --release-stage | --release-stage=* ) if [[ "$1" == "--release" ]]; then local arg=$2 shift else local arg=${1/--release=} fi - is_release "${arg}" || \ + is_release_stage "${arg}" || \ std::die 1 "%s %s: %s -- %s" \ "${CMD}" 'search' \ - "illegal release name" \ + "illegal release stage" \ "${arg}" - opt_use_releases+="${arg}:" + opt_use_rel_stages+="${arg}:" ;; --with | --with=* ) if [[ "$1" == --with ]]; then @@ -1930,7 +1923,7 @@ subcommand_search() { done ;; -a | --all-releases ) - opt_use_releases="${ReleaseStages}" + opt_use_rel_stages+="${ReleaseStages}" ;; --src ) # :FIXME: do we have to add some sanity checks here? @@ -1955,8 +1948,8 @@ subcommand_search() { src_prefix="${PMODULES_ROOT}" fi - if [[ "${opt_use_releases}" == ":" ]]; then - opt_use_releases=":${UsedReleases}:" + if [[ "${opt_use_rel_stages}" == ":" ]]; then + opt_use_rel_stages=":${UsedReleaseStages}:" fi if [[ ${#modules[@]} == 0 ]]; then @@ -2042,7 +2035,7 @@ subcommand_help() { print_help "${arg}" else # :FIXME: print help of newest *available* module - # (respecting UsedReleases) + # (respecting UsedReleaseStages) "${modulecmd}" "${Shell}" "${subcommand}" "${arg}" fi done @@ -2286,6 +2279,12 @@ if [[ -n ${PMODULES_ENV} ]]; then if [[ -z ${Version} ]] || [[ ${Version} != ${PMODULES_VERSION} ]]; then # the Pmodules version changed! declare -g Version="${PMODULES_VERSION}" + # renamed in version 1.0.0rc10 and type changed from + # associative array to normal array + if [[ -v UseFlags ]]; then + declare -a UsedFlags=( "${!UseFlags[@]}" ) + unset UseFlags + fi g_env_must_be_saved='yes' fi if [[ -v DefaultGroups ]] || [[ -v DefaultReleaseStages ]] || [[ -v ReleaseStages ]]; then From d908a4041c1329c02b4c46b1b44050f82367a2b8 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 2 Jun 2021 18:21:53 +0200 Subject: [PATCH 78/94] modulecmd: bugfix in listing unused release stages --- Pmodules/modulecmd.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index a7274da..cf18a35 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1099,7 +1099,7 @@ subcommand_use() { done std::info "\nUnused release stages:" for r in ${ReleaseStages//:/ }; do - [[ ":${UsedReleaseStages}:" =~ :$r: ]] && std::info "\t${r}" + [[ ! ":${UsedReleaseStages}:" =~ :$r: ]] && std::info "\t${r}" done std::info "\nUsed flags:" From b3a6adf9f830657776d809ec60f6f18f7b34c93a Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 2 Jun 2021 18:23:04 +0200 Subject: [PATCH 79/94] modulecmd: handle changes in PMODULES_ENV for old versions --- Pmodules/modulecmd.bash.in | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index cf18a35..4bf884a 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -2285,6 +2285,25 @@ if [[ -n ${PMODULES_ENV} ]]; then declare -a UsedFlags=( "${!UseFlags[@]}" ) unset UseFlags fi + if [[ ! -v UsedFlags ]]; then + declare -a UsedFlags=() + fi + if [[ -v UsedReleases ]]; then + declare -- UsedReleaseStages="${UsedReleases}" + unset UsedReleases + fi + if [[ -v PMODULES_DEFAULT_GROUPS ]]; then + declare -- DefaultGroups="${PMODULES_DEFAULT_GROUPS}" + unset PMODULES_DEFAULT_GROUPS + fi + if [[ -v PMODULES_DEFINED_RELEASES ]]; then + declare -- ReleaseStages="${PMODULES_DEFINED_RELEASES}" + unset PMODULES_DEFINED_RELEASES + fi + if [[ -v PMODULES_DEFAULT_RELEASES ]]; then + declare -- DefaultReleaseStages="${PMODULES_DEFAULT_RELEASES}" + unset PMODULES_DEFAULT_RELEASES + fi g_env_must_be_saved='yes' fi if [[ -v DefaultGroups ]] || [[ -v DefaultReleaseStages ]] || [[ -v ReleaseStages ]]; then From 129d6ff5400d47d2978068558b5d9a1c22d133b6 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 7 Jun 2021 14:14:57 +0200 Subject: [PATCH 80/94] bugfix in terse output of sub-cmd avail --- Pmodules/modulecmd.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 4bf884a..e0a20b3 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -882,7 +882,7 @@ subcommand_avail() { terse_output() { output_header "$1" local -i i=0 - for i in ${!mods[@]}; do + for (( i=0; i<${#mods[@]}; i+=3 )); do local mod=${mods[i]} local rel_stage=${mods[i+1]} case ${rel_stage} in From 5edcec45446ffd0ea7e905bdffdddd3fab38a2c3 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 7 Jun 2021 15:27:08 +0200 Subject: [PATCH 81/94] modulecmd: sort module names version aware - call sort with option --version-sort in getting available modules and search cmd --- Pmodules/modulecmd.bash.in | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index e0a20b3..57bd58e 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -821,7 +821,10 @@ get_available_modules() { if [[ :${used_rel_stages}: =~ :${rel_stage}: ]]; then mods+=( "${mod}" ${rel_stage} "${dir}/${mod}") fi - done < <(${find} -L * \( -type f -o -type l \) -not -name ".*" -ipath "${module}*") + done < <(${find} -L * \ + \( -type f -o -type l \) -not -name ".*" \ + -ipath "${module}*" \ + | ${sort} --version-sort) } done std::upvar ${var} "${mods[@]}" @@ -948,8 +951,6 @@ subcommand_avail() { (( n > max_length )) && (( max_length=n )) available_modules+=("${mod}") done - IFS=$'\n' available_modules=($(sort <<<"${available_modules[*]}")) - unset IFS local -i span=$(( max_length / 16 + 1 )) # compute column size local -i colsize=$(( span * 16 )) # as multiple of 16 local -i column=$cols # force a line-break @@ -1787,7 +1788,7 @@ subcommand_search() { ${func_print_header} while read -a toks; do ${func_print_line} "${toks[@]}" - done < <("${sort}" -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | \ + done < <("${sort}" --version-sort -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | \ ${awk} "${with_modules}") } From 586493f69fff33a483897784678276f9364353b5 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 8 Jun 2021 10:01:14 +0200 Subject: [PATCH 82/94] libmodules.tcl: missing curly bracket fixed --- Pmodules/libmodules.tcl | 1 + 1 file changed, 1 insertion(+) diff --git a/Pmodules/libmodules.tcl b/Pmodules/libmodules.tcl index 7bba9db..b287f88 100644 --- a/Pmodules/libmodules.tcl +++ b/Pmodules/libmodules.tcl @@ -45,6 +45,7 @@ proc _pmodules_parse_pmodules_env { } { foreach k $l { lappend ::OverlayList $tmp($k) } + } UsedGroups { set ::UsedGroups $value } From 20a2c0376e959ec4e10fd77f488ec2beb1a9adf9 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 8 Jun 2021 10:02:34 +0200 Subject: [PATCH 83/94] modulecmd: fixed refactored function name --- Pmodules/modulecmd.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 172c14b..a9dcc15 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1043,7 +1043,7 @@ find_module() { for flag in "${UseFlags[@]/#/_}" ""; do [[ ${mod} == ${module}/*${flag} ]] || continue std::upvar $1 "${dir}/${mod}" - get_release \ + get_release_stage \ rel_stage \ "${dir}" \ "${mod}" From 49aa32f4dfb5f8ef52b50418d47ab6e4de3f5da3 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 9 Jun 2021 09:58:47 +0200 Subject: [PATCH 84/94] modulecmd: set defaults for DefaultGroups, etc - defaults are set for DefaultsGroups, DefaultReleaseStages and ReleaseStages --- Pmodules/modulecmd.bash.in | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index 57bd58e..e5c9f2e 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -60,11 +60,29 @@ declare -A Help declare -r pmodules_config_file="${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/Pmodules.conf" +# the following settings are used if the Pmodules.conf is not available + +# set groups which should be available after initialization +declare -- DefaultGroups='Tools Programming' + +# define available release stages +declare -- ReleaseStages=':unstable:stable:deprecated:' + +# set releases which should be available after initialization +declare -- DefaultReleaseStages='stable' + +# In the dictionary Help we store the help text of each single command +# and for displaying the version. + +# initialize help text of 'module --version' Help['version']=" Pmodules @PMODULES_VERSION@ using Tcl Environment Modules @MODULES_VERSION@ Copyright GNU GPL v2 " +# +# display help text for command given in $1 +# print_help() { echo -e "${Help[$1]}" 1>&2 std::die 1 From 12a5fcd8728cb457e9ca0f3ec89940aad259125c Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 9 Jun 2021 10:00:34 +0200 Subject: [PATCH 85/94] modulecmd: fix in 'unuse' help text --- Pmodules/modulecmd.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index e5c9f2e..fd74b0c 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1238,7 +1238,7 @@ Options[unuse]='-o H -l help' Help[unuse]=' unuse directory|group|release... Remove the given modulefiles directory, group, release stage, - flag or overlay from the search path. + flag from the search path. ' subcommand_unuse() { From 4ef135c6ab9c626fc9d714e441518de869bd5de7 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 9 Jun 2021 10:01:13 +0200 Subject: [PATCH 86/94] modulecmd: soure Pmodules.conf only if exist and readable --- Pmodules/modulecmd.bash.in | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index fd74b0c..c6d822b 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -1421,10 +1421,11 @@ init_manpath() { } pmodules_init() { - source "${pmodules_config_file}" || \ - std::die 3 "Oops: cannot parse config file -- %s\n" \ - "${pmodules_config_file}" - + if [[ -r "${pmodules_config_file}" ]]; then + source "${pmodules_config_file}" || \ + std::die 3 "Oops: cannot parse config file -- %s\n" \ + "${pmodules_config_file}" + fi declare -gx LOADEDMODULES='' declare -gx _LMFILES_='' declare -gx UsedGroups='' From d4132018d1175358895f34bae6a9e80186b13418 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 9 Jun 2021 10:01:47 +0200 Subject: [PATCH 87/94] modulecmd: do not source Pmodules.conf if PMODULES_ENV exist - if PMODULES_ENV is set but DefaultGroups, DefaultReleaseStages or ReleaseStages is not set in PMODULES_ENV, the the default defined in modulecmd is used --- Pmodules/modulecmd.bash.in | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index c6d822b..dde1dd8 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -2326,12 +2326,6 @@ if [[ -n ${PMODULES_ENV} ]]; then fi g_env_must_be_saved='yes' fi - if [[ -v DefaultGroups ]] || [[ -v DefaultReleaseStages ]] || [[ -v ReleaseStages ]]; then - source "${pmodules_config_file}" || \ - std::die 3 "Oops: cannot parse config file -- %s\n" \ - "${pmodules_config_file}" - - fi else pmodules_init fi From 7a721b859bbf61825974ef42aa7871156da9229b Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Wed, 23 Jun 2021 09:33:12 +0200 Subject: [PATCH 88/94] libpbuild.bash: bugfix in version cmp --- Pmodules/libpbuild.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pmodules/libpbuild.bash b/Pmodules/libpbuild.bash index 8272a93..20732b8 100644 --- a/Pmodules/libpbuild.bash +++ b/Pmodules/libpbuild.bash @@ -90,7 +90,7 @@ pbuild::version_lt() { pbuild::version_le() { pbuild::version_compare "$1" "$2" local -i exit_code=$? - (( exit_code == 0 || exit_code = 2 )) + (( exit_code == 0 || exit_code == 2 )) } @@ -98,7 +98,7 @@ pbuild::version_gt() { pbuild::version_compare "$1" "$2" (( $? == 1 )) local -i exit_code=$? - (( exit_code == 0 || exit_code = 1 )) + (( exit_code == 0 || exit_code == 1 )) } pbuild::version_eq() { From 2d12850de0c6af3d547d4c746321ba878fc6f7ec Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 20 Jul 2021 15:44:46 +0200 Subject: [PATCH 89/94] libpbuild.bash: bugfix in version compare functions --- Pmodules/libpbuild.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pmodules/libpbuild.bash b/Pmodules/libpbuild.bash index 50f5687..35ce306 100644 --- a/Pmodules/libpbuild.bash +++ b/Pmodules/libpbuild.bash @@ -90,7 +90,7 @@ pbuild::version_lt() { pbuild::version_le() { pbuild::version_compare "$1" "$2" local -i exit_code=$? - (( exit_code == 0 || exit_code = 2 )) + (( exit_code == 0 || exit_code == 2 )) } @@ -98,7 +98,7 @@ pbuild::version_gt() { pbuild::version_compare "$1" "$2" (( $? == 1 )) local -i exit_code=$? - (( exit_code == 0 || exit_code = 1 )) + (( exit_code == 0 || exit_code == 1 )) } pbuild::version_eq() { From 4f625ed86b5435eeb942a2367ace9dcd979164e9 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 20 Jul 2021 15:54:21 +0200 Subject: [PATCH 90/94] libstd.bash: fix in std.get_os_release_linux() for current CentOS --- Pmodules/libstd.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pmodules/libstd.bash b/Pmodules/libstd.bash index e5a2f46..fedd0c4 100644 --- a/Pmodules/libstd.bash +++ b/Pmodules/libstd.bash @@ -220,8 +220,8 @@ std.get_os_release_linux() { fi case "${ID}" in - RedHatEnterpriseServer | RedHatEnterprise | Scientific | rhel | centos | fedora ) - echo "rhel${VERSION_ID%.*}" + RedHatEnterpriseServer | RedHatEnterprise | Scientific | rhel | centos | CentOS | fedora ) + echo "rhel${VERSION_ID%%.*}" ;; Ubuntu ) echo "Ubuntu${VERSION_ID%.*}" From 6ceb76e8fb538d0cfa5e7bad02ef35af99d428f6 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 12 Aug 2021 18:12:13 +0200 Subject: [PATCH 91/94] bash_completion: sub-commands dependencies and sync removed --- Pmodules/bash_completion | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pmodules/bash_completion b/Pmodules/bash_completion index 76c789a..ed47153 100644 --- a/Pmodules/bash_completion +++ b/Pmodules/bash_completion @@ -39,9 +39,9 @@ _module() { COMPREPLY=() - cmds="add apropos avail clear dependencies display help\ + cmds="add apropos avail clear display help\ initadd initclear initlist initprepend initrm initswitch\ - keyword list load purge refresh rm search show swap switch sync\ + keyword list load purge refresh rm search show swap switch \ unload unuse update use whatis" opts="-c -f -h -i -l -s -t -u -v -H -V\ From 02d1939c81eb7c4f9236f451b6059569b52d53da Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 12 Aug 2021 18:14:37 +0200 Subject: [PATCH 92/94] modulecmd: module sub-command --help bugs fixed --- Pmodules/modulecmd.bash.in | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index dde1dd8..f620f21 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -262,6 +262,7 @@ subcommand_generic0() { args+=( "$1" ) ;; esac + shift 1 done if (( ${#args[@]} > 0 )); then std::die 3 "%s %s: %s\n" \ @@ -459,7 +460,7 @@ subcommand_load() { while (($# > 0)); do case $1 in -H | --help ) - print_help "${subcommand_load}" + print_help "${subcommand}" ;; -f | --force ) opts+=(' -f') @@ -2294,6 +2295,24 @@ if [[ -z "${Subcommands[${subcommand}]}" ]]; then std::die 1 "${CMD}: unknown sub-command -- ${subcommand}\n" fi +case ${subcommand} in + add ) + subcommand='load' + ;; + display ) + subcommand='show' + ;; + keyword ) + subcommand='apropos' + ;; + rm ) + subcommand='unload' + ;; + switch ) + subcommand='swap' + ;; +esac + if [[ -n ${PMODULES_ENV} ]]; then eval "$("${base64}" -d <<< "${PMODULES_ENV}" 2>/dev/null)" if [[ -z ${Version} ]] || [[ ${Version} != ${PMODULES_VERSION} ]]; then @@ -2335,7 +2354,7 @@ if (( ${#GroupDepths[@]} == 0 )); then fi case ${subcommand} in - load|purge|search|switch ) + load|purge|search|swap ) declare -r tmpfile=$( ${mktemp} /tmp/Pmodules.XXXXXX ) \ || std::die 1 "Oops: unable to create tmp file!" ;; From e3d8ee97809fcdfc66dd461b7add91e9411442ff Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 12 Aug 2021 18:27:01 +0200 Subject: [PATCH 93/94] modulecmd: bugfix in removing tmp file in _exit --- Pmodules/modulecmd.bash.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index f620f21..fc51ad6 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -143,7 +143,9 @@ save_env() { _exit() { save_env "${g_env_must_be_saved}" - ${rm} -f "${tmpfile}" + if [[ -n "${tmpfile}" ]] && [[ -e "${tmpfile}" ]]; then + ${rm} -f "${tmpfile}" || : + fi } trap '_exit' EXIT From 6093d858ef6da8c3b034f68c94aaf72c62d3fb53 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 23 Aug 2021 14:46:48 +0200 Subject: [PATCH 94/94] modbuild: some comments added/modified --- Pmodules/modbuild.in | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Pmodules/modbuild.in b/Pmodules/modbuild.in index a992d9a..a9dd620 100755 --- a/Pmodules/modbuild.in +++ b/Pmodules/modbuild.in @@ -409,9 +409,13 @@ build_modules() { declare -r OVERLAY_CONF="${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/overlays.conf" +# +# Return overlay name *and* directory for an overlay given +# by name *or* directory. Search in the config file ${OVERLAY_CONF}. +# get_overlay_name_and_dir() { - local "$1" - local "$2" + local "$1" # upvar for overlay name + local "$2" # upvar for overlay directory if [[ -r "${OVERLAY_CONF}" ]]; then local toks=() while read -a toks; do @@ -430,6 +434,8 @@ get_overlay_name_and_dir() { parse_args "$@" +# +# set overlay_name, overlay_dir and opt_system # # --overlay=name # lookup overlay directory, system name equivalent to overlay name @@ -438,7 +444,7 @@ parse_args "$@" # --overlay=dir # use given overlay dir and default system name # --system=name -# lookup name, set overlay_dir of found confi +# lookup name, set overlay_dir of found config declare overlay_name='' declare overlay_dir='' if [[ -n "${opt_overlay_name_or_dir}" ]]; then