diff --git a/Pmodules/modulecmd.bash.in b/Pmodules/modulecmd.bash.in index ca4c143..276c584 100644 --- a/Pmodules/modulecmd.bash.in +++ b/Pmodules/modulecmd.bash.in @@ -128,7 +128,7 @@ get_release() { # read releasefile, remove empty lines, spaces etc local -r data=$( < "${releasefile}" ) std::upvar $1 "${data}" - else + else std::upvar $1 'unstable' fi [[ :${releases}: =~ ${release} ]] @@ -291,7 +291,7 @@ subcommand_generic1plus() { ############################################################################## # # load [-fsvw] -# +# # $1: module to load # Subcommands[add]='load' @@ -302,7 +302,7 @@ USAGE: module add modulefile... module load modulefile... Load modulefile(s) into the shell environment. Loading a - 'group-head' will extend the MODULEPATH. E.g.: loading a + 'group-head' will extend the MODULEPATH. E.g.: loading a compiler makes additional modules like openmpi and libraries compiled with this compiler available. ' @@ -314,7 +314,7 @@ subcommand_load() { local prefix='' local m='' - local saved_IFS="${IFS}"; + local saved_IFS="${IFS}"; IFS=':' local -a modulepath=(${MODULEPATH}) IFS=${saved_IFS} @@ -356,8 +356,8 @@ subcommand_load() { # prefix of the module to ${array[1]}. # # The trick with the first line matching "_PREFIX" is not - # 100% reliable: One of the Pmodules extensions must be - # called before something like + # 100% reliable: One of the Pmodules extensions must be + # called before something like # setenv FOO_PREFIX bar # can be used. # @@ -541,7 +541,7 @@ subcommand_load() { # :FIXME: Not sure whether this is now correct! # The idea is to supress the error messages from the Tcl modulecmd, but not # the output to stderr coded in a modulefile. - + local error=$( < "${tmpfile}") if [[ "${error}" =~ ":ERROR:" ]]; then local s=${error%%$'\n'*} @@ -760,14 +760,14 @@ USAGE: is searched for modulefiles whose pathname match the argument. This command does *not* display all installed modules on the - system. Only *loadable* modules are listed. The list of + system. Only *loadable* modules are listed. The list of available modules may change either by loading other modules, e.g. a compiler, or with the sub-command 'use'. SWITCHES: -a|--all||--all-releases List all available modules independend of the release. - + -t|--terse Output in short format. @@ -785,7 +785,7 @@ subcommand_avail() { # use this variable in the output functions local -a mods=() local dir='' - + # get number of columns of terminal cols=$(tput cols) @@ -997,7 +997,7 @@ get_group_depths () { # re-scan available groups. # # Note: -# Removing groups is not supported for the time being. Be aware, that +# Removing groups is not supported for the time being. Be aware, that # a user might have a module loaded from this group. This cannot be checked. # # $1: root of modulefile hierarchy @@ -1036,7 +1036,7 @@ USAGE: prepended or appended to the module search path. The default is to prepend the directory. - With a group as argument, the modules in this group will + With a group as argument, the modules in this group will be made available. With a release as argument, this modules with this release @@ -1050,7 +1050,7 @@ SWITCHES: subcommand_use() { local -r subcommand='use' - local saved_IFS=${IFS}; + local saved_IFS=${IFS}; IFS=':' local -a modulepath=(${MODULEPATH}) IFS=${saved_IFS} @@ -1071,7 +1071,7 @@ subcommand_use() { std::info "\t${_group}\n" fi done - + std::info "\nUsed releases:\n" for r in ${UsedReleases//:/ }; do std::info "\t${r}\n" @@ -1110,12 +1110,8 @@ subcommand_use() { } use () { - declare -g UsedGroups - declare -g MODULEPATH - - local dirs_to_add=() while (( $# > 0)); do - arg="$1" + local arg="$1" # if is release # ... # elif is group @@ -1130,35 +1126,38 @@ subcommand_use() { if is_release "${arg}"; then # releases are always *appended* std::append_path UsedReleases "${arg}" - g_env_must_be_saved='yes' + elif [[ "${arg}" =~ "flag=" ]]; then std::append_path UseFlags "${arg/flag=}" - g_env_must_be_saved='yes' + elif [[ "${arg}" =~ "overlay=" ]]; then local overlay="${arg/overlay=}" [[ -d "${overlay}" ]] || \ - std:die 3 "%s %s: is not a directory -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${overlay}" + std:die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "is not a directory" \ + "${overlay}" if [[ ! ${Overlays[${overlay}]} ]]; then Overlays[${overlay}]=1 PMODULES_OVERLAYS+=:${overlay} get_group_depths "${!Overlays[@]}" for group in ${UsedGroups//:/ }; do - local dir="${overlay}/${group}/${PMODULES_MODULEFILES_DIR}" + local dir="${overlay}/" + dir+="${group}/${PMODULES_MODULEFILES_DIR}" if [[ -d "${dir}" ]]; then std::prepend_path MODULEPATH "${dir}" fi done - g_env_must_be_saved='yes' fi elif [[ ! ${arg} =~ */* ]] && is_group "${arg}"; then if (( ${GroupDepths[$arg]} != 0 )); then - std::die 3 "%s %s: cannot add group to module path -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${arg}" + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "cannot add group to module path" \ + "${arg}" fi std::append_path UsedGroups "${arg}" - g_env_must_be_saved='yes' for overlay in "${!Overlays[@]}"; do for group in ${UsedGroups//:/ }; do local dir="${overlay}/" @@ -1168,19 +1167,26 @@ subcommand_use() { fi done done + elif [[ ${arg} =~ ^${PMODULES_ROOT} ]]; then - std::die 3 "%s %s: illegal directory -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${arg}" + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "illegal directory" \ + "${arg}" + elif [[ -d ${arg} ]]; then ${add2path_func} MODULEPATH "$(cd "${arg}" && pwd)" + else - std::die 3 "%s %s: neither a directory, release or group -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${arg}" + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "neither a directory, release or group" \ + "${arg}" fi shift done - - export_env ${g_shell} MODULEPATH + g_env_must_be_saved='yes' + export_env ${g_shell} 'MODULEPATH' } local -a args=() @@ -1225,7 +1231,89 @@ unuse directory|group|release... subcommand_unuse() { local -r subcommand='unuse' - local dirs_to_remove=() + unuse() { + while (( $# > 0 )); do + local arg=$1 + local modulefiles_dir="${PMODULES_ROOT}/${arg}/${PMODULES_MODULEFILES_DIR}" + if is_release "${arg}"; then + # argument is release + std::remove_path UsedReleases "${arg}" + + elif [[ "${arg}" =~ "flag=" ]]; then + # argument is flag + std::remove_path UseFlags "${arg/flag=}" + + elif [[ "${arg}" =~ "overlay=" ]]; then + local overlay="${arg/overlay=}" + [[ -d "${overlay}" ]] || \ + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "is not a directory" \ + "${overlay}" + [[ "${overlay}" == "${PMODULES_ROOT}" ]] && \ + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "cannot remove root overlay" \ + "${overlay}" + if [[ ${Overlays[${overlay}]} ]]; then + [[ "${_LMFILES_}" =~ "${overlay}" ]] && \ + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "cannot remove overlay" \ + "${overlay}" + unset Overlays[${overlay}] + std::remove_path PMODULES_OVERLAYS "${overlay}" + for dir in "${modulepath[@]}"; do + if [[ "${dir}" =~ "${overlay}" ]]; then + std::remove_path MODULEPATH "${dir}" + fi + done + fi + + elif [[ ! ${arg} =~ */* ]] && [[ -d ${modulefiles_dir} ]]; then + # argument is group + if (( ${GroupDepths[$arg]} != 0 )); then + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "cannot remove group" \ + "${arg}" + fi + local var="PMODULES_LOADED_${arg^^}" + if [[ -n "${!var}" ]]; then + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "cannot remove group due to loaded modules" \ + "${arg}" + fi + std::remove_path UsedGroups "${arg}" + std::remove_path MODULEPATH "${modulefiles_dir}" + + elif [[ -d ${arg} ]]; then + # argument is a modulepath + local normalized_dir=$(cd "${arg}" && pwd) + std::remove_path MODULEPATH "${normalized_dir}" + + elif [[ ${arg} =~ ^${PMODULES_ROOT} ]]; then + # argument looks like a group in our root + std::die 3 "%s %s: %s -- %s\n." \ + "${CMD}" "${subcommand}" \ + "illegal directory" \ + "${arg}" + + else + # oops + std::die 3 "%s %s: %s -- %s\n" \ + "${CMD}" "${subcommand}" \ + "not a valid argument" \ + "${arg}" + + fi + shift + done + g_env_must_be_saved='yes' + export_env "${g_shell}" 'MODULEPATH' + } + local -a args=() while (( $# > 0)); do case "$1" in @@ -1241,76 +1329,11 @@ subcommand_unuse() { shift done if (( ${#args[@]} == 0 )); then - std::die 3 "%s %s: missing argument\n" \ - "${CMD}" "${subcommand}" + std::die 3 "%s %s: %s\n" \ + "${CMD}" "${subcommand}" \ + 'missing argument' fi - - local arg - for arg in "${args[@]}"; do - # if is release - # ... - # elif is group - # ... - # elif matches modulepath root - # ... - # elif is directory - # ... - local modulefiles_dir="${PMODULES_ROOT}/${arg}/${PMODULES_MODULEFILES_DIR}" - if is_release "${arg}"; then - std::remove_path UsedReleases "${arg}" - - elif [[ "${arg}" =~ "flag=" ]]; then - std::remove_path UseFlags "${arg/flag=}" - g_env_must_be_saved='yes' - - elif [[ "${arg}" =~ "overlay=" ]]; then - local overlay="${arg/overlay=}" - [[ -d "${overlay}" ]] || \ - std::die 3 "%s %s: is not a directory -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${overlay}" - [[ "${overlay}" == "${PMODULES_ROOT}" ]] && \ - std::die 3 "%s %s: cannot remove root overlay -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${overlay}" - if [[ ${Overlays[${overlay}]} ]]; then - [[ "${_LMFILES_}" =~ "${overlay}" ]] && \ - std::die 3 "%s %s: cannot remove overlay -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${overlay}" - unset Overlays[${overlay}] - std::remove_path PMODULES_OVERLAYS "${overlay}" - for dir in "${modulepath[@]}"; do - if [[ "${dir}" =~ "${overlay}" ]]; then - std::remove_path MODULEPATH "${dir}" - fi - done - g_env_must_be_saved='yes' - fi - - elif [[ ! ${arg} =~ */* ]] && [[ -d ${modulefiles_dir} ]]; then - if (( ${GroupDepths[$arg]} != 0 )); then - std::die 3 "%s %s: %s" \ - "${CMD}" "${FUNCNAME[0]##*_}" \ - "cannot remove group from module path -- %s\n" \ - "${arg}" - fi - std::remove_path UsedGroups "${arg}" - g_env_must_be_saved='yes' - std::remove_path MODULEPATH "${modulefiles_dir}" - - elif [[ -d ${arg} ]]; then - local normalized_dir=$(cd "${arg}" && pwd) - std::remove_path MODULEPATH "${normalized_dir}" - - elif [[ ${arg} =~ ^${PMODULES_ROOT} ]]; then - std::die 3 "%s %s: illegal directory -- %s\n." \ - "${CMD}" "${FUNCNAME[0]##*_}" "${arg}" - - else - std::die 3 "%s %s: not a directory -- %s\n" \ - "${CMD}" "${FUNCNAME[0]##*_}" "${arg}" - fi - shift - done - export_env "${g_shell}" 'MODULEPATH' + unuse "${args[@]}" } ############################################################################## @@ -1561,7 +1584,7 @@ USAGE: Search installed modules. If an argument is given, search for modules whose name match the argument. -SWITCHES: +SWITCHES: --no-header Suppress output of a header. @@ -1572,7 +1595,7 @@ SWITCHES: -a|--all-releases Search within all releases. - + --with=STRING Search for modules compiled with modules matching string. The command @@ -1693,7 +1716,7 @@ subcommand_search() { print_result "${tmpfile}" rm -f "${tmpfile}" } - + while (( $# > 0 )); do case $1 in -H | --help ) @@ -1758,11 +1781,11 @@ subcommand_search() { if [[ -z "${src_prefix}" ]]; then src_prefix=( "${!Overlays[@]}" ) fi - + if [[ "${opt_use_releases}" == ":" ]]; then opt_use_releases=":${UsedReleases}:" fi - + if [[ ${#modules[@]} == 0 ]]; then modules+=( '' ) fi @@ -1915,7 +1938,7 @@ USAGE: .zlogin(.ext) If a 'module load' line is found in any of these files, the - modulefile(s) is(are) appended to any existing list of + modulefile(s) is(are) appended to any existing list of modulefiles. The 'module load' line must be located in at least one of the files listed above for any of the 'init' sub-commands to work properly. If the 'module load' line