From 8867f5bbaf6a943b3388cb28beeb6b6d74d0ee7a Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sat, 13 Jun 2026 09:59:43 +0200 Subject: [PATCH 1/7] doc: add linked-envvars design doc Signed-off-by: Xavier Delaruelle --- .hunspell.en.dic | 1 + NEWS.rst | 1 + doc/source/design/linked-envvars.rst | 77 ++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 doc/source/design/linked-envvars.rst diff --git a/.hunspell.en.dic b/.hunspell.en.dic index 3c24d93a4..9865fb336 100644 --- a/.hunspell.en.dic +++ b/.hunspell.en.dic @@ -1338,3 +1338,4 @@ ts OSX BAWT HTTPS +mirrorEnvVarChange diff --git a/NEWS.rst b/NEWS.rst index ddfd8d93f..fbed8db13 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -90,6 +90,7 @@ Modules 5.7.0 (not yet released) command are not affected by this mechanism. When :mconfig:`info_extension` is changed with :subcmd:`config` sub-command, it sets the :envvar:`MODULES_INFO_EXTENSION` environment variable. (fix issue #585) +* Doc: add :ref:`linked-envvars` design notes. .. _5.6 release notes: diff --git a/doc/source/design/linked-envvars.rst b/doc/source/design/linked-envvars.rst new file mode 100644 index 000000000..7b2ed9c96 --- /dev/null +++ b/doc/source/design/linked-envvars.rst @@ -0,0 +1,77 @@ +.. _linked-envvars: + +Linked environment variables +============================ + +This document describes the mechanism to link one environment variables onto +others and apply the same value changes. + +The goal is to link environment variables together and apply all changes to +both once linked. + +Design choices: + +* When link is being established, variable value is not synced +* Link is not reflexive: if A is linked to B, all changes made to A are + applied to B, but direct changes to B are not applied to A unless if this + link is also configured +* A ``module display`` shows the environment changes applying to linked + environment variables + +This mechanism applies to all environment variable management modulefile +commands and module sub-commands: + +* :mfcmd:`append-path` +* :mfcmd:`prepend-path` +* :mfcmd:`pushenv` +* :mfcmd:`remove-path` +* :mfcmd:`setenv` +* :mfcmd:`unsetenv` + +.. note:: Link is not effective when a value is set to the environment + variable through the ``::env`` Tcl global array. + +``linked_envvars`` configuration option +--------------------------------------- + +New configuration option :mconfig:`linked_envvars` is made to configure these +links between environment variables. + +* Items are separated by colon character +* One variable can be linked to several ones, either through: + + - one item with several variables: ``A&B&C`` + - several items: ``A&B:A&C`` + +Implementation +-------------- + +* Define an internal state (``current_envvar``) to indicate the name of the + environment variable currently modified +* Set a ``trace`` to execute ``mirrorEnvVarChange`` procedure at the end of + the execution of environment variable management commands +* No trace setup if :mconfig:`linked_envvars` is empty +* ``mirrorEnvVarChange`` procedure: + + - get currently modified environment variable name through + ``current_envvar`` state + - get environment variable change command to execute through + ``command-string`` trace argument + - replace ``current_envvar`` in this command string by linked environment + variable name + - execute resulting command string in currently active interpreter + - do this for each linked environment variable, including recursively linked + ones: trace is triggered one and handle all environment variables to avoid + cycle loop + +.. note:: No other environment variable change can occur between the + definition of the ``current_envvar`` state and the execution of the + ``mirrorEnvVarChange`` trace procedure. The link mechanism cannot apply to + Modules internal environment variables like ``__MODULES_SHARE_*``. + +.. note:: Environment variable name argument is always positioned before any + value, thus replacing the first occurrence found of this name will + accurately change the name argument on all environment variable change + commands. + +.. vim:set tabstop=2 shiftwidth=2 expandtab autoindent: From 64300a066dea8ddcc66ff7e40abfe17a92b9c920 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sat, 13 Jun 2026 10:00:06 +0200 Subject: [PATCH 2/7] Introduce "linked_envvars" configuration option Add "linked_envvars" configuration option that defines environment variables linked to others that should get the same value modification applied to them. When configuration is modified it sets the MODULES_LINKED_ENVVARS environment variable. Closes #609 Signed-off-by: Xavier Delaruelle --- tcl/envmngt.tcl.in | 46 ++++++++++++++++++++++++++++++++++++++++++++++ tcl/init.tcl.in | 23 +++++++++++++++++++++++ tcl/interp.tcl.in | 15 ++++++++++++--- tcl/mfcmd.tcl | 30 ++++++++++++++++++++++++++++++ tcl/modscan.tcl | 12 ++++++++++++ tcl/subcmd.tcl.in | 5 +++++ tcl/util.tcl | 9 +++++++++ 7 files changed, 137 insertions(+), 3 deletions(-) diff --git a/tcl/envmngt.tcl.in b/tcl/envmngt.tcl.in index 43b6cee41..9683f78f3 100644 --- a/tcl/envmngt.tcl.in +++ b/tcl/envmngt.tcl.in @@ -1642,6 +1642,9 @@ proc unload-path {cmd mode dflbhv args} { allow_dup idx_val ign_refcount val_set_is_delim glob_match bhv var\ path_list + # indicate env var name to configured traces + setState current_envvar $var + switch -- $bhv { noop { return [list $bhv $var] @@ -1792,6 +1795,9 @@ proc add-path {cmd mode dflbhv args} { path_list } + # indicate env var name to configured traces + setState current_envvar $var + # clean any previously defined pushenv stack unset-env [getPushenvVarName $var] 1 @@ -2062,6 +2068,46 @@ proc getModulesEnvVarGlobList {{loaded_ctx 0}} { return $envvar_glob_list } +# trace procedure to apply same env change procedure to linked env vars +proc mirrorEnvVarChange {cmd_str code result op} { + # skip mirror processing if initial command failed + if {$code} { + return + } + set envvar [getState current_envvar] + if {[info exists ::g_linkedEnvvars($envvar)]} { + # collect all direct and indirect linked env vars, avoiding cycle loop + set linked_envvar_list $::g_linkedEnvvars($envvar) + for {set i 0} {$i < [llength $linked_envvar_list]} {incr i} { + set linked_envvar [lindex $linked_envvar_list $i] + if {[info exists ::g_linkedEnvvars($linked_envvar)]} { + lappendNoDup linked_envvar_list\ + {*}$::g_linkedEnvvars($linked_envvar) + } + } + + if {![isTopEvaluation]} { + set interp_eval_cmd [list interp eval [getCurrentModfileInterpName]] + } + + # apply same env var change command on linked env vars + # no other trace hook will be triggered as we are processing this one + foreach linked_envvar $linked_envvar_list { + if {$linked_envvar eq $envvar} { + continue + } + set linked_cmd_str [replaceFirstInStr $cmd_str $envvar\ + $linked_envvar] + # adapt execution if called from modulefile interp + if {[info exists interp_eval_cmd]} { + set linked_cmd_str [list {*}$interp_eval_cmd $linked_cmd_str] + } + # execute in same context than initial command + uplevel 1 $linked_cmd_str + } + } +} + # ;;; Local Variables: # ;;; Mode: tcl-mode # ;;; tcl-indent-level: 3 diff --git a/tcl/init.tcl.in b/tcl/init.tcl.in index c276223d3..f6d35153b 100644 --- a/tcl/init.tcl.in +++ b/tcl/init.tcl.in @@ -107,6 +107,8 @@ array set g_config_defs [list\ implicit_requirement {MODULES_IMPLICIT_REQUIREMENT @implicitrequirement@ 0\ b {0 1}}\ info_extension {MODULES_INFO_EXTENSION 0 0 b {0 1}}\ + linked_envvars {MODULES_LINKED_ENVVARS {} 0 l {} {}\ + initConfLinkedEnvvars}\ list_output {MODULES_LIST_OUTPUT {@listoutput@} 0 l {header idx variant\ alias indesym sym tag hidden key} {} {} eltlist}\ list_terse_output {MODULES_LIST_TERSE_OUTPUT {@listterseoutput@} 0 l\ @@ -811,6 +813,27 @@ proc initConfTagColorName {envvar value validvallist intvallist} { return $value } +# Initialize env variable link array +proc initConfLinkedEnvvars {envvar value validvallist intvallist} { + # overridden value coming from environment + if {[isEnvVarDefined $envvar]} { + set value $::env($envvar) + } + + # set array to get full value for one env var if set through multiple args + foreach link_arg [split $value :] { + set linked_envvar_list [lassign [split $link_arg &] src_envvar] + if {![string length $src_envvar] || ![llength $linked_envvar_list] ||\ + {} in $linked_envvar_list || $src_envvar in $linked_envvar_list} { + reportWarning "Ignore invalid link defined in $envvar ($link_arg)" + } else { + lappendNoDup ::g_linkedEnvvars($src_envvar) {*}$linked_envvar_list + } + } + + return [array get ::g_linkedEnvvars] +} + # Initialize interactive editor command proc initConfEditor {envvar value validvallist intvallist} { # overridden value coming from environment via Modules-specific variable diff --git a/tcl/interp.tcl.in b/tcl/interp.tcl.in index 96c45fddc..bb438f2bd 100644 --- a/tcl/interp.tcl.in +++ b/tcl/interp.tcl.in @@ -64,6 +64,9 @@ proc initModfileModeAliases {mode auto aliasesVN aliasesPassArgVN\ if {[getConf source_cache]} { lappend ::g_modfileBaseAliases source sourceModfileCmd } + if {[llength [getConf linked_envvars]]} { + lappend ::g_modfileBaseAliases mirrorEnvVarChange mirrorEnvVarChange + } # list of alias commands whose target procedure is adapted according to # the evaluation mode @@ -154,7 +157,12 @@ x-resource {x-resource x-resource reportCmd nop nop # in display mode (except for source-sh and unique-name-conflict) } elseif {$mode eq {display} && $alias ni {source-sh\ unique-name-conflict}} { - set traces($alias) reportCmdTrace + lappend traces($alias) reportCmdTrace + } + # mirror environment variable changes if some links are defined + if {[llength [getConf linked_envvars]] && $alias in {append-path\ + prepend-path pushenv remove-path setenv unsetenv}} { + lappend traces($alias) mirrorEnvVarChange } } } @@ -761,8 +769,9 @@ proc initInterpCommands {itrp fresh aliasesVN aliasesPassArgVN tracesVN\ } foreach alias [array names traces] { - interp eval $itrp [list trace add execution $alias leave\ - $traces($alias)] + foreach trace_proc $traces($alias) { + interp eval $itrp [list trace add execution $alias leave $trace_proc] + } } } diff --git a/tcl/mfcmd.tcl b/tcl/mfcmd.tcl index 223a29e1b..5821b31ca 100644 --- a/tcl/mfcmd.tcl +++ b/tcl/mfcmd.tcl @@ -578,6 +578,9 @@ proc parseSetenvCommandArgs {mode dflbhv args} { proc setenv {args} { lassign [parseSetenvCommandArgs load set {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + if {$bhv eq {set}} { # clean any previously defined reference counter array unset-env [getModshareVarName $var] 1 @@ -596,6 +599,9 @@ proc setenv {args} { proc setenv-un {args} { lassign [parseSetenvCommandArgs unload unset {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + # clean any existing reference counter array unset-env [getModshareVarName $var] 1 @@ -616,6 +622,9 @@ proc setenv-un {args} { proc setenv-wh {args} { lassign [parseSetenvCommandArgs load set {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + setEnvVarIfUndefined $var {} return {} } @@ -728,6 +737,9 @@ proc parseUnsetenvCommandArgs {mode dflbhv args} { proc unsetenv {args} { lassign [parseUnsetenvCommandArgs load unset {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + # clean any existing reference counter array unset-env [getModshareVarName $var] 1 @@ -744,6 +756,9 @@ proc unsetenv {args} { proc unsetenv-un {args} { lassign [parseUnsetenvCommandArgs unload noop {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + switch -- $bhv { set { # apply value specified for set on unload @@ -769,6 +784,9 @@ proc unsetenv-un {args} { proc unsetenv-wh {args} { lassign [parseUnsetenvCommandArgs load noop {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + setEnvVarIfUndefined $var {} return {} } @@ -944,6 +962,9 @@ proc edit-path-wh {cmd args} { lassign [parsePathCommandArgs $cmd load noop {*}$args] separator allow_dup\ idx_val ign_refcount val_set_is_delim glob_match bhv var path_list + # indicate env var name to configured traces + setState current_envvar $var + setEnvVarIfUndefined $var {} return {} @@ -2202,6 +2223,9 @@ proc pushenv {var val} { # know what element to remove from stack when unloading prepend-path $pushvar [currentState modulename]&$val + # indicate env var name to configured traces + setState current_envvar $var + return {} } @@ -2246,11 +2270,17 @@ proc pushenv-un {var val} { unset-env $var 0 $val } + # indicate env var name to configured traces + setState current_envvar $var + return {} } # optimized pushenv for whatis mode (same approach than setenv-wh) proc pushenv-wh {var val} { + # indicate env var name to configured traces + setState current_envvar $var + setEnvVarIfUndefined $var {} return {} } diff --git a/tcl/modscan.tcl b/tcl/modscan.tcl index 3ed35a11b..5ff55d1ad 100644 --- a/tcl/modscan.tcl +++ b/tcl/modscan.tcl @@ -47,6 +47,9 @@ proc variant-sc {itrp args} { proc setenv-sc {args} { lassign [parseSetenvCommandArgs load set {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + recordScanModuleElt $var setenv envvar setEnvVarIfUndefined $var {} @@ -57,6 +60,9 @@ proc edit-path-sc {cmd args} { lassign [parsePathCommandArgs $cmd load noop {*}$args] separator allow_dup\ idx_val ign_refcount val_set_is_delim glob_match bhv var path_list + # indicate env var name to configured traces + setState current_envvar $var + recordScanModuleElt $var $cmd envvar # record MODULEPATH edition as "module use" command @@ -71,6 +77,9 @@ proc edit-path-sc {cmd args} { proc pushenv-sc {var val} { recordScanModuleElt $var pushenv envvar + # indicate env var name to configured traces + setState current_envvar $var + setEnvVarIfUndefined $var {} return {} } @@ -78,6 +87,9 @@ proc pushenv-sc {var val} { proc unsetenv-sc {args} { lassign [parseUnsetenvCommandArgs load noop {*}$args] bhv var val + # indicate env var name to configured traces + setState current_envvar $var + recordScanModuleElt $var unsetenv envvar setEnvVarIfUndefined $var {} diff --git a/tcl/subcmd.tcl.in b/tcl/subcmd.tcl.in index 9a1c7c99e..f5ce8a423 100644 --- a/tcl/subcmd.tcl.in +++ b/tcl/subcmd.tcl.in @@ -2314,6 +2314,11 @@ proc cmdModuleResurface {cmd args} { # already defined. remove-path: to ensure paths are removed whatever # their reference counter value lappend optlist --ignore-refcount + + # sync environment variable changes if some links are defined + if {[llength [getConf linked_envvars]]} { + trace add execution $cmd leave mirrorEnvVarChange + } } } diff --git a/tcl/util.tcl b/tcl/util.tcl index 2e409caa6..b636506f6 100644 --- a/tcl/util.tcl +++ b/tcl/util.tcl @@ -403,6 +403,15 @@ proc getCallingProcName {} { } } +proc replaceFirstInStr {str old new} { + set start_idx [string first $old $str] + if {$start_idx == -1} { + return $str + } + set end_idx [expr {$start_idx + [string length $old] - 1}] + return [string replace $str $start_idx $end_idx $new] +} + # ;;; Local Variables: # ;;; Mode: tcl-mode # ;;; tcl-indent-level: 3 From 48dad305c1087338f0d41ded51a4e863418e30eb Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sat, 13 Jun 2026 10:08:39 +0200 Subject: [PATCH 3/7] init: add linked_envvars config to completion script Signed-off-by: Xavier Delaruelle --- init/Makefile | 2 +- init/fish_completion | 2 +- init/zsh-functions/_module.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/init/Makefile b/init/Makefile index 1ff1b2c75..6a4f36f0c 100644 --- a/init/Makefile +++ b/init/Makefile @@ -136,7 +136,7 @@ comp_lint_opts := -a -i --all --icase comp_modtosh_opts := --auto --no-auto --force -f --icase -i comp_path_opts := -d --delim --duplicates comp_rm_path_opts := -d --delim --index -comp_config_opts := --dump-state --reset abort_on_error advanced_version_spec auto_handling avail_indepth avail_output avail_terse_output cache_buffer_bytes cache_expiry_secs collection_pin_version collection_pin_tag collection_target color colors conflict_unload contact editor extended_default extra_siteconfig hide_auto_loaded home icase ignore_cache ignore_user_rc implicit_default implicit_requirement info_extension list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days non_exportable_tags pager paginate path_entry_reorder protected_envvars quarantine_support rcfile redirect_output require_via reset_target_state run_quarantine search_match set_shell_startup shells_with_ksh_fpath silent_shell_debug source_cache spider_indepth spider_output spider_terse_output sticky_purge tag_abbrev tag_color_name tcl_linter term_background term_width unique_name_loaded unload_match_order variant_shortcut verbosity wa_277 +comp_config_opts := --dump-state --reset abort_on_error advanced_version_spec auto_handling avail_indepth avail_output avail_terse_output cache_buffer_bytes cache_expiry_secs collection_pin_version collection_pin_tag collection_target color colors conflict_unload contact editor extended_default extra_siteconfig hide_auto_loaded home icase ignore_cache ignore_user_rc implicit_default implicit_requirement info_extension linked_envvars list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days non_exportable_tags pager paginate path_entry_reorder protected_envvars quarantine_support rcfile redirect_output require_via reset_target_state run_quarantine search_match set_shell_startup shells_with_ksh_fpath silent_shell_debug source_cache spider_indepth spider_output spider_terse_output sticky_purge tag_abbrev tag_color_name tcl_linter term_background term_width unique_name_loaded unload_match_order variant_shortcut verbosity wa_277 define translate-in-script $(ECHO_GEN) diff --git a/init/fish_completion b/init/fish_completion index 503f574f7..bce62fc39 100644 --- a/init/fish_completion +++ b/init/fish_completion @@ -87,7 +87,7 @@ complete -c module -n '__fish_module_use_stashlist' -f -a "(module stashlist --c /Stash collection list\$/d; \ /:\$/d; \ /:ERROR:/d;')" -complete -c module -n '__fish_module_use_config' -f -a "--dump-state --reset abort_on_error advanced_version_spec auto_handling avail_indepth avail_output avail_terse_output cache_buffer_bytes cache_expiry_secs collection_pin_version collection_pin_tag collection_target color colors conflict_unload contact editor extended_default extra_siteconfig hide_auto_loaded home icase ignore_cache ignore_user_rc implicit_default implicit_requirement info_extension list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days non_exportable_tags pager paginate path_entry_reorder protected_envvars quarantine_support rcfile redirect_output require_via reset_target_state run_quarantine search_match set_shell_startup shells_with_ksh_fpath silent_shell_debug source_cache spider_indepth spider_output spider_terse_output sticky_purge tag_abbrev tag_color_name tcl_linter term_background term_width unique_name_loaded unload_match_order variant_shortcut verbosity wa_277" +complete -c module -n '__fish_module_use_config' -f -a "--dump-state --reset abort_on_error advanced_version_spec auto_handling avail_indepth avail_output avail_terse_output cache_buffer_bytes cache_expiry_secs collection_pin_version collection_pin_tag collection_target color colors conflict_unload contact editor extended_default extra_siteconfig hide_auto_loaded home icase ignore_cache ignore_user_rc implicit_default implicit_requirement info_extension linked_envvars list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days non_exportable_tags pager paginate path_entry_reorder protected_envvars quarantine_support rcfile redirect_output require_via reset_target_state run_quarantine search_match set_shell_startup shells_with_ksh_fpath silent_shell_debug source_cache spider_indepth spider_output spider_terse_output sticky_purge tag_abbrev tag_color_name tcl_linter term_background term_width unique_name_loaded unload_match_order variant_shortcut verbosity wa_277" complete -f -n '__fish_module_no_subcommand' -c module -a 'help' --description 'Print this or modulefile(s) help info' complete -f -n '__fish_module_no_subcommand' -c module -a 'avail' --description 'List all or matching available modules' diff --git a/init/zsh-functions/_module.in b/init/zsh-functions/_module.in index 01912c8c7..921fd891b 100644 --- a/init/zsh-functions/_module.in +++ b/init/zsh-functions/_module.in @@ -378,7 +378,7 @@ _module() { _arguments \ '--dump-state[Report each state value of current Modules execution]' \ '--reset[Unset environment variable relative to configuration key]' \ - '1:configuration key:(abort_on_error advanced_version_spec auto_handling avail_indepth avail_output avail_terse_output cache_buffer_bytes cache_expiry_secs collection_pin_version collection_pin_tag collection_target color colors conflict_unload contact editor extended_default extra_siteconfig hide_auto_loaded home icase ignore_cache ignore_user_rc implicit_default implicit_requirement info_extension list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days non_exportable_tags pager paginate path_entry_reorder protected_envvars quarantine_support rcfile redirect_output require_via reset_target_state run_quarantine search_match set_shell_startup shells_with_ksh_fpath silent_shell_debug source_cache spider_indepth spider_output spider_terse_output sticky_purge tag_abbrev tag_color_name tcl_linter term_background term_width unique_name_loaded unload_match_order variant_shortcut verbosity wa_277)' \ + '1:configuration key:(abort_on_error advanced_version_spec auto_handling avail_indepth avail_output avail_terse_output cache_buffer_bytes cache_expiry_secs collection_pin_version collection_pin_tag collection_target color colors conflict_unload contact editor extended_default extra_siteconfig hide_auto_loaded home icase ignore_cache ignore_user_rc implicit_default implicit_requirement info_extension linked_envvars list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days non_exportable_tags pager paginate path_entry_reorder protected_envvars quarantine_support rcfile redirect_output require_via reset_target_state run_quarantine search_match set_shell_startup shells_with_ksh_fpath silent_shell_debug source_cache spider_indepth spider_output spider_terse_output sticky_purge tag_abbrev tag_color_name tcl_linter term_background term_width unique_name_loaded unload_match_order variant_shortcut verbosity wa_277)' \ && ret=0 ;; (edit) From 5955550bf6ff487df40afac936a5cb86734813f1 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sat, 13 Jun 2026 15:57:51 +0200 Subject: [PATCH 4/7] doc: desc. linked_envvars config in man/changes/install Signed-off-by: Xavier Delaruelle --- INSTALL.rst | 4 +++- doc/source/changes.rst | 3 ++- doc/source/module.rst | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/INSTALL.rst b/INSTALL.rst index 3e0a17b3b..e208e906b 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -1721,7 +1721,9 @@ installation. | :mconfig:`implicit_requirement` | ``1`` | :instopt:`--enable-implicit-requirement`, | | | | | | :envvar:`MODULES_IMPLICIT_REQUIREMENT` | | | +-----------------------------------+----------------------------------------------+----------------------------------------------+--------------+-----------+ -| :mconfig:`info_extension` | ``0`` | :envvar:`MODULES_INFO_EXTENSION`, | | | +| :mconfig:`info_extension` | ``0`` | :envvar:`MODULES_INFO_EXTENSION` | | | ++-----------------------------------+----------------------------------------------+----------------------------------------------+--------------+-----------+ +| :mconfig:`linked_envvars` | *Empty by default* | :envvar:`MODULES_LINKED_ENVVARS` | | | +-----------------------------------+----------------------------------------------+----------------------------------------------+--------------+-----------+ | :mconfig:`list_output` | ``header:idx:variant:sym:tag:key`` | :instopt:`--with-list-output`, | | | | | | :envvar:`MODULES_LIST_OUTPUT`, | | | diff --git a/doc/source/changes.rst b/doc/source/changes.rst index 936afc35c..8563f0bd3 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -1290,7 +1290,8 @@ The following Modules configuration option has been introduced on Modules 5. | | :mconfig:`spider_indepth`, :mconfig:`require_via` | +------------+-----------------------------------------------------------------+ | 5.7 | :mconfig:`path_entry_reorder`, :mconfig:`paginate`, | -| | :mconfig:`non_exportable_tags`, :mconfig:`info_extension` | +| | :mconfig:`non_exportable_tags`, :mconfig:`info_extension`, | +| | :mconfig:`linked_envvars` | +------------+-----------------------------------------------------------------+ :mconfig:`auto_handling` diff --git a/doc/source/module.rst b/doc/source/module.rst index a1435e5ab..420674e30 100644 --- a/doc/source/module.rst +++ b/doc/source/module.rst @@ -1248,6 +1248,21 @@ Module Sub-Commands .. versionadded:: 5.7 + .. mconfig:: linked_envvars + + Define links between environment variables to apply same value modification + to each linked variables. + + This configuration option is set to an empty value by default. The + :envvar:`MODULES_LINKED_ENVVARS` environment variable is defined by + :subcmd:`config` sub-command when changing this configuration option from + its default value. See :envvar:`MODULES_LINKED_ENVVARS` description for + details + + .. only:: html or latex + + .. versionadded:: 5.7 + .. mconfig:: list_output Content to report in addition to module names on :subcmd:`list` sub-command From 41748448f96bca6e7576df16738bc4b262f3437b Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sat, 13 Jun 2026 15:58:25 +0200 Subject: [PATCH 5/7] doc: desc. MODULES_LINKED_ENVVARS in man/changes Signed-off-by: Xavier Delaruelle --- doc/source/changes.rst | 5 +++-- doc/source/module.rst | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/doc/source/changes.rst b/doc/source/changes.rst index 8563f0bd3..7e3dbefae 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -1075,8 +1075,9 @@ The following environment variables appeared on Modules 5. +------------+-----------------------------------------------------------------+ | 5.7 | :envvar:`MODULES_PATH_ENTRY_REORDER`, | | | :envvar:`MODULES_PAGINATE`, | -| | :envvar:`MODULES_NON_EXPORTABLE_TAGS` | -| | :envvar:`MODULES_INFO_EXTENSION` | +| | :envvar:`MODULES_NON_EXPORTABLE_TAGS`, | +| | :envvar:`MODULES_INFO_EXTENSION`, | +| | :envvar:`MODULES_LINKED_ENVVARS` | +------------+-----------------------------------------------------------------+ Modules Specific Tcl Commands diff --git a/doc/source/module.rst b/doc/source/module.rst index 420674e30..97b39717f 100644 --- a/doc/source/module.rst +++ b/doc/source/module.rst @@ -5164,6 +5164,32 @@ ENVIRONMENT .. versionadded:: 5.7 +.. envvar:: MODULES_LINKED_ENVVARS + + A colon-separated list of environment variable link sets. Each link set is a + group of environment variable names separated by the ampersand character. + When an environment variable modification command is applied to the first + variable in a link set, the same command is automatically applied to all + other variables in that set. + + This link mechanism applies to all environment variable management modulefile + commands and module sub-commands (:mfcmd:`append-path`, + :mfcmd:`prepend-path`, :mfcmd:`pushenv`, :mfcmd:`remove-path`, + :mfcmd:`setenv` and :mfcmd:`unsetenv`). + + For example, if the configuration option is set to ``FOO&BAR&BAZ:BAR&QUX``, a + :mfcmd:`prepend-path` command applied to ``FOO`` will also be applied to + ``BAR``, ``BAZ``, and ``QUX``. Linking is not reflexive: a command applied to + ``QUX`` is not propagated to any other environment variable in the link set. + + This environment variable value supersedes the default value set in the + :mconfig:`linked_envvars` configuration option. It can be defined with the + :subcmd:`config` sub-command. + + .. only:: html or latex + + .. versionadded:: 5.7 + .. envvar:: MODULES_LIST_OUTPUT A colon separated list of the elements to report in addition to module names From e377985cf817ff3f4d952137ed0516e431ad99c6 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sun, 14 Jun 2026 09:40:45 +0200 Subject: [PATCH 6/7] ts: test linked_envvars config option Signed-off-by: Xavier Delaruelle --- testsuite/install.00-init/010-environ.exp | 3 ++- testsuite/modules.00-init/010-environ.exp | 3 ++- testsuite/modules.70-maint/220-config.exp | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/testsuite/install.00-init/010-environ.exp b/testsuite/install.00-init/010-environ.exp index 04c9788c3..4d9f2a918 100644 --- a/testsuite/install.00-init/010-environ.exp +++ b/testsuite/install.00-init/010-environ.exp @@ -94,8 +94,9 @@ setenv_var MODULES_PAGINATE 1 unsetenv_var MODULES_LOGGED_EVENTS unsetenv_var MODULES_LOGGER -# clean any protected variable configuration +# clean any environment variable-specific configuration unsetenv_var MODULES_PROTECTED_ENVVARS +unsetenv_var MODULES_LINKED_ENVVARS # clean any output redirection configuration unsetenv_var MODULES_REDIRECT_OUTPUT diff --git a/testsuite/modules.00-init/010-environ.exp b/testsuite/modules.00-init/010-environ.exp index 5de7d5dff..bdc13240d 100644 --- a/testsuite/modules.00-init/010-environ.exp +++ b/testsuite/modules.00-init/010-environ.exp @@ -95,8 +95,9 @@ setenv_var MODULES_PAGINATE 1 unsetenv_var MODULES_LOGGED_EVENTS unsetenv_var MODULES_LOGGER -# clean any protected variable configuration +# clean any environment variable-specific configuration unsetenv_var MODULES_PROTECTED_ENVVARS +unsetenv_var MODULES_LINKED_ENVVARS # clean any output redirection configuration unsetenv_var MODULES_REDIRECT_OUTPUT diff --git a/testsuite/modules.70-maint/220-config.exp b/testsuite/modules.70-maint/220-config.exp index 76a009848..5cfc41a87 100644 --- a/testsuite/modules.70-maint/220-config.exp +++ b/testsuite/modules.70-maint/220-config.exp @@ -85,6 +85,7 @@ array set configdfl [list\ implicit_default [expr {$install_implicitdefault eq {y}}]\ implicit_requirement [expr {$install_implicitrequirement eq {y}}]\ info_extension 0\ + linked_envvars {}\ list_output $install_listoutput\ list_terse_output $install_listterseoutput\ locked_configs $install_lockedconfigs\ @@ -155,6 +156,7 @@ array set configvar [list\ implicit_default MODULES_IMPLICIT_DEFAULT\ implicit_requirement MODULES_IMPLICIT_REQUIREMENT\ info_extension MODULES_INFO_EXTENSION\ + linked_envvars MODULES_LINKED_ENVVARS\ list_output MODULES_LIST_OUTPUT\ list_terse_output MODULES_LIST_TERSE_OUTPUT\ logged_events MODULES_LOGGED_EVENTS\ @@ -273,6 +275,7 @@ array set configkind [list\ avail_output l\ avail_terse_output l\ colors l\ + linked_envvars l\ list_output l\ list_terse_output l\ logged_events l\ From bfeb7a3da87217b5c55e6bbd6f232e0599324933 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sun, 14 Jun 2026 17:53:31 +0200 Subject: [PATCH 7/7] ts: add tests to check linked_envvars Signed-off-by: Xavier Delaruelle --- testsuite/example/initrc.in | 3 + testsuite/modulefiles.4/link/1 | 105 ++ testsuite/modulefiles.4/link/2 | 1 + .../modules.50-cmds/730-linked_envvars.exp | 1001 +++++++++++++++++ testsuite/modules.70-maint/120-autoinit.exp | 56 +- 5 files changed, 1159 insertions(+), 7 deletions(-) create mode 100644 testsuite/modulefiles.4/link/1 create mode 100644 testsuite/modulefiles.4/link/2 create mode 100644 testsuite/modules.50-cmds/730-linked_envvars.exp diff --git a/testsuite/example/initrc.in b/testsuite/example/initrc.in index 0002253e2..4d12bb2a6 100644 --- a/testsuite/example/initrc.in +++ b/testsuite/example/initrc.in @@ -48,6 +48,9 @@ if {[info exists env(TESTSUITE_INITRC)]} { restorereset2 { module restore __init__ } + linked_envvars1 { + append-path FOO value + } } } catch {module load unk} diff --git a/testsuite/modulefiles.4/link/1 b/testsuite/modulefiles.4/link/1 new file mode 100644 index 000000000..90e311888 --- /dev/null +++ b/testsuite/modulefiles.4/link/1 @@ -0,0 +1,105 @@ +#%Module +if {[info exists env(TESTSUITE_LINKED_ENVVARS)]} { + module-whatis [module-info name] + module-help [module-info name] + proc ModulesTest {} { return 1 } + switch -- $env(TESTSUITE_LINKED_ENVVARS) { + append1 { + append-path FOO value + } + prepend1 { + prepend-path FOO value + } + remove1 { + remove-path FOO value + } + setenv1 { + setenv FOO value + } + unsetenv1 { + unsetenv FOO + } + pushenv1 { + pushenv FOO value + } + append2 { + append-path -d { } FOO value val1 + } + prepend2 { + prepend-path -d { } --duplicates FOO value + } + remove2 { + remove-path -d { } FOO value val2 --append-on-unload val1 + } + setenv2 { + setenv --set-if-undef FOO value + } + unsetenv2 { + unsetenv --unset-on-unload FOO value + } + pushenv2 { + # no specific option currently available on pushenv + pushenv FOO value + } + set1 { + set ::env(FOO) value + } + unset1 { + unset -nocomplain ::env(FOO) + } + append3 { + set var value + append-path FOO $var + } + prepend3 { + set var value + prepend-path FOO $var + } + remove3 { + set var value + remove-path FOO $var + } + setenv3 { + set var value + setenv FOO $var + } + unsetenv3 { + set var value + unsetenv FOO $var + } + pushenv3 { + set var value + pushenv FOO $var + } + setenv4 { + setenv QUX value + setenv BAZ value + } + setenv5 { + setenv FOOFOO value + } + unsetenv5 { + unsetenv FOOFOO value + } + append6 { + append-path FOO value + append-path BAR val + } + append_err1 { + append-path --bad FOO value + } + } + if {$env(TESTSUITE_LINKED_ENVVARS) in {append1 prepend1 remove1 setenv1\ + unsetenv1 pushenv1}} { + switch -- [module-info mode] { + help - test - display { + puts stderr "BAR: [getenv --return-value BAR]" + puts stderr "QUX: [getenv --return-value QUX]" + } + whatis { + module-whatis "BAR: [getenv --return-value BAR]" + module-whatis "QUX: [getenv --return-value QUX]" + } + } + } +} diff --git a/testsuite/modulefiles.4/link/2 b/testsuite/modulefiles.4/link/2 new file mode 100644 index 000000000..1c148cdd2 --- /dev/null +++ b/testsuite/modulefiles.4/link/2 @@ -0,0 +1 @@ +#%Module diff --git a/testsuite/modules.50-cmds/730-linked_envvars.exp b/testsuite/modules.50-cmds/730-linked_envvars.exp new file mode 100644 index 000000000..13df65202 --- /dev/null +++ b/testsuite/modules.50-cmds/730-linked_envvars.exp @@ -0,0 +1,1001 @@ +############################################################################## +# Modules Revision 3.0 +# Providing a flexible user environment +# +# File: modules.50-cmds/%M% +# Revision: %I% +# First Edition: 2026/06/14 +# Last Mod.: %U%, %G% +# +# Authors: Xavier Delaruelle, xavier.delaruelle@cea.fr +# +# Description: Testuite testsequence +# Command: load, unload, display, help, show, test, +# refresh, whatis +# Modulefiles: link, source-sh +# Sub-Command: +# +# Comment: %C{ +# Test linked_envvars mechanism +# }C% +# +############################################################################## + +set mp $modpath.4 +set mpre $modpathre.4 +setenv_var MODULEPATH $mp + + +# basic link setup +setenv_var MODULES_LINKED_ENVVARS FOO&BAR + +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +set ans [list] +lappend ans [list unset FOO] +lappend ans [list unset BAR] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set __MODULES_PUSHENV_FOO link/1&value] +lappend ans [list set __MODULES_PUSHENV_BAR link/1&value] +testouterr_cmd bash {load link/1} $ans {} + +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +testouterr_cmd bash {append-path FOO value} $ans {} +testouterr_cmd bash {prepend-path FOO value} $ans {} + +set ans [list] +lappend ans [list unset FOO] +lappend ans [list unset BAR] +testouterr_cmd bash {remove-path FOO value} $ans {} + +skip_if_quick_mode + + +# multi var link and recurvise link, var not identically initialized +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAZ:BAR&QUX +setenv_var FOO val1 +setenv_var BAR val2 +setenv_var QUX val3 + +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set ans [list] +lappend ans [list set FOO val1:value] +lappend ans [list set BAZ value] +lappend ans [list set BAR val2:value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX val3:value] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +set ans [list] +lappend ans [list set FOO value:val1] +lappend ans [list set BAZ value] +lappend ans [list set BAR value:val2] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value:val3] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAZ value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +set ans [list] +lappend ans [list set FOO val1] +lappend ans [list unset BAZ] +lappend ans [list set BAR val2] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX val3] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +set ans [list] +lappend ans [list unset FOO] +lappend ans [list unset BAZ] +lappend ans [list unset BAR] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list unset QUX] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +set ans [list] +lappend ans [list set __MODULES_PUSHENV_QUX link/1&value:&val3] +lappend ans [list set FOO value] +lappend ans [list set BAZ value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value] +lappend ans [list set __MODULES_PUSHENV_FOO link/1&value:&val1] +lappend ans [list set __MODULES_PUSHENV_BAZ link/1&value] +lappend ans [list set __MODULES_PUSHENV_BAR link/1&value:&val2] +testouterr_cmd bash {load link/1} $ans {} + +set ans [list] +lappend ans [list set FOO val1:value] +lappend ans [list set BAZ value] +lappend ans [list set BAR val2:value] +lappend ans [list set QUX val3:value] +testouterr_cmd bash {append-path FOO value} $ans {} + +set ans [list] +lappend ans [list set FOO value:val1] +lappend ans [list set BAZ value] +lappend ans [list set BAR value:val2] +lappend ans [list set QUX value:val3] +testouterr_cmd bash {prepend-path FOO value} $ans {} + +set ans [list] +lappend ans [list set FOO val1] +lappend ans [list unset BAZ] +lappend ans [list set BAR val2] +lappend ans [list set QUX val3] +testouterr_cmd bash {remove-path FOO value} $ans {} + + +# test when options are used on modulefile commands +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAZ:BAR&QUX +setenv_var FOO val1 +setenv_var BAR val2 +setenv_var QUX value + +setenv_var TESTSUITE_LINKED_ENVVARS append2 +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO val1:2] +lappend ans [list set FOO {val1 value}] +lappend ans [list set BAZ {value val1}] +lappend ans [list set BAR {val2 value val1}] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set __MODULES_SHARE_QUX value:2] +lappend ans [list set QUX {value val1}] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS prepend2 +set ans [list] +lappend ans [list set FOO {value val1}] +lappend ans [list set BAZ value] +lappend ans [list set BAR {value val2}] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set __MODULES_SHARE_QUX value:2] +lappend ans [list set QUX {value value}] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS setenv2 +set ans [list] +lappend ans [list set BAZ value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS remove2 +set ans [list] +lappend ans [list set FOO val1] +lappend ans [list unset BAZ] +lappend ans [list unset BAR] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list unset QUX] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv2 +set ans [list] +lappend ans [list unset FOO] +lappend ans [list unset BAZ] +lappend ans [list unset BAR] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list unset QUX] +testouterr_cmd bash {load link/1} $ans {} + +# no specific option currently available on pushenv +setenv_var TESTSUITE_LINKED_ENVVARS pushenv2 +set ans [list] +lappend ans [list set __MODULES_PUSHENV_QUX link/1&value:&value] +lappend ans [list set FOO value] +lappend ans [list set BAZ value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value] +lappend ans [list set __MODULES_PUSHENV_FOO link/1&value:&val1] +lappend ans [list set __MODULES_PUSHENV_BAZ link/1&value] +lappend ans [list set __MODULES_PUSHENV_BAR link/1&value:&val2] +testouterr_cmd bash {load link/1} $ans {} + +set ans [list] +lappend ans [list set FOO {val1,value}] +lappend ans [list set BAZ {value,val1}] +lappend ans [list set BAR {val2,value,val1}] +lappend ans [list set QUX {value,val1}] +testouterr_cmd bash {append-path -d , FOO value val1} $ans {} + +set ans [list] +lappend ans [list set FOO {value,val1}] +lappend ans [list set BAZ value] +lappend ans [list set BAR {value,val2}] +lappend ans [list set __MODULES_SHARE_QUX value:2] +lappend ans [list set QUX {value,value}] +testouterr_cmd bash {prepend-path -d , --duplicates FOO value} $ans {} + +set ans [list] +lappend ans [list set FOO val1] +lappend ans [list unset BAZ] +lappend ans [list unset BAR] +lappend ans [list unset QUX] +testouterr_cmd bash {remove-path -d , FOO value val2} $ans {} + + +# test other evaluation modes +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAZ:BAR&QUX +setenv_var FOO val1 +setenv_var BAR val2 +setenv_var QUX value + +# help mode +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set tserr "$modlin +Module Specific Help for $mpre/link/1: + +BAR: val2:value +QUX: value +link/1 +$modlin" +testouterr_cmd_re bash {help link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +set tserr "$modlin +Module Specific Help for $mpre/link/1: + +BAR: value:val2 +QUX: value +link/1 +$modlin" +testouterr_cmd_re bash {help link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 +set tserr "$modlin +Module Specific Help for $mpre/link/1: + +BAR: value +QUX: value +link/1 +$modlin" +testouterr_cmd_re bash {help link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +set tserr "$modlin +Module Specific Help for $mpre/link/1: + +BAR: val2 +QUX: +link/1 +$modlin" +testouterr_cmd_re bash {help link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +set tserr "$modlin +Module Specific Help for $mpre/link/1: + +BAR: +QUX: +link/1 +$modlin" +testouterr_cmd_re bash {help link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +set tserr "$modlin +Module Specific Help for $mpre/link/1: + +BAR: value +QUX: value +link/1 +$modlin" +testouterr_cmd_re bash {help link/1} OK $tserr + + +# test mode +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set tserr "$modlin +Module Specific Test for $mpre/link/1: + +BAR: val2:value +QUX: value +Test result: PASS +$modlin" +testouterr_cmd_re bash {test link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +set tserr "$modlin +Module Specific Test for $mpre/link/1: + +BAR: value:val2 +QUX: value +Test result: PASS +$modlin" +testouterr_cmd_re bash {test link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 +set tserr "$modlin +Module Specific Test for $mpre/link/1: + +BAR: value +QUX: value +Test result: PASS +$modlin" +testouterr_cmd_re bash {test link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +set tserr "$modlin +Module Specific Test for $mpre/link/1: + +BAR: val2 +QUX: +Test result: PASS +$modlin" +testouterr_cmd_re bash {test link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +set tserr "$modlin +Module Specific Test for $mpre/link/1: + +BAR: +QUX: +Test result: PASS +$modlin" +testouterr_cmd_re bash {test link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +set tserr "$modlin +Module Specific Test for $mpre/link/1: + +BAR: value +QUX: value +Test result: PASS +$modlin" +testouterr_cmd_re bash {test link/1} OK $tserr + + +# display mode +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +append-path\tFOO value +append-path\tBAR value +append-path\tBAZ value +append-path\tQUX value +BAR: val2:value +QUX: value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +prepend-path\tFOO value +prepend-path\tBAR value +prepend-path\tBAZ value +prepend-path\tQUX value +BAR: value:val2 +QUX: value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +setenv\t\tFOO value +setenv\t\tBAR value +setenv\t\tBAZ value +setenv\t\tQUX value +BAR: value +QUX: value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +remove-path\tFOO value +remove-path\tBAR value +remove-path\tBAZ value +remove-path\tQUX value +BAR: val2 +QUX: +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +unsetenv\tFOO +unsetenv\tBAR +unsetenv\tBAZ +unsetenv\tQUX +BAR: +QUX: +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +pushenv\t\tFOO value +pushenv\t\tBAR value +pushenv\t\tBAZ value +pushenv\t\tQUX value +BAR: value +QUX: value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + + +# display mode with options on commands +setenv_var TESTSUITE_LINKED_ENVVARS append2 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +append-path\t-d { } FOO value val1 +append-path\t-d { } BAR value val1 +append-path\t-d { } BAZ value val1 +append-path\t-d { } QUX value val1 +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS prepend2 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +prepend-path\t-d { } --duplicates FOO value +prepend-path\t-d { } --duplicates BAR value +prepend-path\t-d { } --duplicates BAZ value +prepend-path\t-d { } --duplicates QUX value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS setenv2 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +setenv\t\t--set-if-undef FOO value +setenv\t\t--set-if-undef BAR value +setenv\t\t--set-if-undef BAZ value +setenv\t\t--set-if-undef QUX value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS remove2 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +remove-path\t-d { } FOO value val2 --append-on-unload val1 +remove-path\t-d { } BAR value val2 --append-on-unload val1 +remove-path\t-d { } BAZ value val2 --append-on-unload val1 +remove-path\t-d { } QUX value val2 --append-on-unload val1 +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv2 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +unsetenv\t--unset-on-unload FOO value +unsetenv\t--unset-on-unload BAR value +unsetenv\t--unset-on-unload BAZ value +unsetenv\t--unset-on-unload QUX value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv2 +set tserr "$modlin +$mpre/link/1: + +module-whatis\tlink/1 +module-help\tlink/1 +pushenv\t\tFOO value +pushenv\t\tBAR value +pushenv\t\tBAZ value +pushenv\t\tQUX value +$modlin" +testouterr_cmd_re bash {display link/1} OK $tserr + + +# whatis mode +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set tserr "$modlin $mpre $modlin +\\s*link/1: link/1 +\\s*link/1: BAR: val2 +\\s*link/1: QUX: value" +testouterr_cmd_re bash {whatis link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +testouterr_cmd_re bash {whatis link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 +testouterr_cmd_re bash {whatis link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +testouterr_cmd_re bash {whatis link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +testouterr_cmd_re bash {whatis link/1} OK $tserr + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +testouterr_cmd_re bash {whatis link/1} OK $tserr + + +# scan mode +setenv_var TESTSUITE_LINKED_ENVVARS append1 +testouterr_cmd_re bash {avail -t -o link/1 envvar:FOO envvar:BAR envvar:BAZ envvar:QUX} OK link/1 + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +testouterr_cmd_re bash {avail -t -o link/1 envvar:FOO envvar:BAR envvar:BAZ envvar:QUX} OK link/1 + +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 +testouterr_cmd_re bash {avail -t -o link/1 envvar:FOO envvar:BAR envvar:BAZ envvar:QUX} OK link/1 + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +testouterr_cmd_re bash {avail -t -o link/1 envvar:FOO envvar:BAR envvar:BAZ envvar:QUX} OK link/1 + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +testouterr_cmd_re bash {avail -t -o link/1 envvar:FOO envvar:BAR envvar:BAZ envvar:QUX} OK link/1 + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +testouterr_cmd_re bash {avail -t -o link/1 envvar:FOO envvar:BAR envvar:BAZ envvar:QUX} OK link/1 + + +# unload mode +setenv_loaded_module [list link/1] [list $mp/link/1] +setenv_var FOO val1:value +setenv_var BAR val2:value +setenv_var BAZ value +setenv_var QUX value +setenv_var __MODULES_SHARE_QUX value:2 + +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set ans [list] +lappend ans [list set FOO val1] +lappend ans [list unset BAZ] +lappend ans [list set BAR val2] +lappend ans [list unset _LMFILES_] +lappend ans [list unset LOADEDMODULES] +lappend ans [list unset __MODULES_SHARE_QUX] +lappend ans [list set QUX value] +testouterr_cmd bash {unload link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS prepend1 +setenv_var FOO value:val1 +setenv_var BAR value:val2 +testouterr_cmd bash {unload link/1} $ans {} + +setenv_var FOO value +setenv_var BAR value +setenv_var BAZ value +setenv_var QUX value +unsetenv_var __MODULES_SHARE_QUX +setenv_var TESTSUITE_LINKED_ENVVARS setenv1 + +setenv_var TESTSUITE_LINKED_ENVVARS remove1 +setenv_var FOO val1 +setenv_var BAR val2 +unsetenv_var BAZ +unsetenv_var QUX +set ans [list] +lappend ans [list unset _LMFILES_] +lappend ans [list unset LOADEDMODULES] +testouterr_cmd bash {unload link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv1 +unsetenv_var FOO +unsetenv_var BAR +unsetenv_var BAZ +unsetenv_var QUX +set ans [list] +lappend ans [list unset _LMFILES_] +lappend ans [list unset LOADEDMODULES] +testouterr_cmd bash {unload link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +setenv_var FOO value +setenv_var BAR value +setenv_var BAZ value +setenv_var QUX value +setenv_var __MODULES_PUSHENV_FOO link/1&value:&val1 +setenv_var __MODULES_PUSHENV_BAZ link/1&value +setenv_var __MODULES_PUSHENV_BAR link/1&value:&val2 +setenv_var __MODULES_PUSHENV_QUX link/1&value:&value +set ans [list] +lappend ans [list unset __MODULES_PUSHENV_QUX] +lappend ans [list set FOO val1] +lappend ans [list unset BAZ] +lappend ans [list set BAR val2] +lappend ans [list unset _LMFILES_] +lappend ans [list unset LOADEDMODULES] +lappend ans [list unset __MODULES_PUSHENV_FOO] +lappend ans [list unset __MODULES_PUSHENV_BAZ] +lappend ans [list unset __MODULES_PUSHENV_BAR] +testouterr_cmd bash {unload link/1} $ans {} + + +unsetenv_loaded_module +unsetenv_var FOO +unsetenv_var BAR +unsetenv_var BAZ +unsetenv_var QUX +unsetenv_var __MODULES_PUSHENV_FOO +unsetenv_var __MODULES_PUSHENV_BAZ +unsetenv_var __MODULES_PUSHENV_BAR +unsetenv_var __MODULES_PUSHENV_QUX + + +# recursive link (2 hops) +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAZ:BAR&QUX:QUX&FOOBAR +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set FOOBAR value] +lappend ans [list set BAZ value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&QUX:BAR&BAZ&FOOBAR +testouterr_cmd bash {load link/1} $ans {} + + +# modification through Tcl regular variable commands +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAZ:BAR&QUX:QUX&FOOBAR +setenv_var TESTSUITE_LINKED_ENVVARS set1 +set ans [list] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var FOO value +setenv_var TESTSUITE_LINKED_ENVVARS unset1 +testouterr_cmd bash {load link/1} $ans {} + + +# reference to local variable +setenv_var MODULES_LINKED_ENVVARS FOO&BAR +unsetenv_var FOO + +setenv_var TESTSUITE_LINKED_ENVVARS append3 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS prepend3 +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS remove3 +set ans [list] +lappend ans [list unset FOO] +lappend ans [list unset BAR] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS setenv3 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv3 +set ans [list] +lappend ans [list unset FOO] +lappend ans [list unset BAR] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS pushenv3 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set __MODULES_PUSHENV_FOO link/1&value] +lappend ans [list set __MODULES_PUSHENV_BAR link/1&value] +testouterr_cmd bash {load link/1} $ans {} + + +# no reflexive link defined and change linked variable +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAZ:BAR&QUX +setenv_var TESTSUITE_LINKED_ENVVARS setenv4 +set ans [list] +lappend ans [list set BAZ value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value] +testouterr_cmd bash {load link/1} $ans {} + + +# variable that starts with same prefix than linked var +setenv_var MODULES_LINKED_ENVVARS FOO&BAR +setenv_var TESTSUITE_LINKED_ENVVARS setenv5 +set ans [list] +lappend ans [list set FOOFOO value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var TESTSUITE_LINKED_ENVVARS unsetenv5 +set ans [list] +lappend ans [list unset FOOFOO] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + + +# multiple env var modification commands in modulefile +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAZ:BAR&QUX +setenv_var TESTSUITE_LINKED_ENVVARS append6 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAZ value] +lappend ans [list set BAR value:val] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value:val] +testouterr_cmd bash {load link/1} $ans {} + + +# link Modules-internal env vars +setenv_var MODULES_LINKED_ENVVARS __MODULES_SHARE_FOO&BAR +setenv_var FOO value + +setenv_var TESTSUITE_LINKED_ENVVARS append1 +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO value:2] +lappend ans [list set FOO value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var MODULES_LINKED_ENVVARS __MODULES_PUSHENV_FOO&BAR +setenv_var TESTSUITE_LINKED_ENVVARS pushenv1 +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set __MODULES_PUSHENV_FOO link/1&value:&value] +testouterr_cmd bash {load link/1} $ans {} + + +# reflexive links +setenv_var MODULES_LINKED_ENVVARS FOO&BAR:BAR&FOO +setenv_var TESTSUITE_LINKED_ENVVARS append6 +unsetenv_path_var FOO +unsetenv_path_var BAR +unsetenv_path_var QUX +set ans [list] +lappend ans [list set FOO value:val] +lappend ans [list set BAR value:val] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd bash {load link/1} $ans {} + +setenv_var MODULES_LINKED_ENVVARS FOO&QUX:QUX&BAR:BAR&QUX:QUX&FOO +set ans [list] +lappend ans [list set FOO value:val] +lappend ans [list set BAR value:val] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +lappend ans [list set QUX value:val] +testouterr_cmd bash {load link/1} $ans {} + + +# check other traces are still working +setenv_var TESTSUITE_LINKED_ENVVARS append1 +setenv_var MODULES_LINKED_ENVVARS FOO&BAR +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +set tserr {.* +DEBUG \[#1:load:link/1\] evaluateModulefile: append-path FOO value +.* +DEBUG \[#1:load:link/1\] evaluateModulefile: append-path BAR value +.*} +testouterr_cmd_re bash {load -DD link/1} $ans $tserr + +set tserr {.* +TIMER append-path FOO value \(.* ms\) +.* +TIMER append-path BAR value \(.* ms\) +.*} +testouterr_cmd_re bash {load --timer -D link/1} $ans $tserr + + +# bad configuration value +setenv_var TESTSUITE_LINKED_ENVVARS append1 +setenv_var MODULES_LINKED_ENVVARS FOO&: +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +set tserr "$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS (FOO&) +$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS ()" +testouterr_cmd bash {load link/1} $ans $tserr + +setenv_var MODULES_LINKED_ENVVARS &FOO: +set tserr "$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS (&FOO) +$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS ()" +testouterr_cmd bash {load link/1} $ans $tserr + +setenv_var MODULES_LINKED_ENVVARS FOO: +set tserr "$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS (FOO) +$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS ()" +testouterr_cmd bash {load link/1} $ans $tserr + +setenv_var MODULES_LINKED_ENVVARS FOO&BAR&BAR +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set BAR value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +testouterr_cmd_re bash {load link/1} $ans {} + +setenv_var MODULES_LINKED_ENVVARS FOO&BAR:FOO&BAR +testouterr_cmd_re bash {load link/1} $ans {} + +setenv_var MODULES_LINKED_ENVVARS FOO&FOO +set ans [list] +lappend ans [list set FOO value] +lappend ans [list set _LMFILES_ $mp/link/1] +lappend ans [list set LOADEDMODULES link/1] +set tserr "$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS (FOO&FOO)" +testouterr_cmd bash {load link/1} $ans $tserr + +setenv_var MODULES_LINKED_ENVVARS {} +testouterr_cmd bash {load link/1} $ans {} + +setenv_var MODULES_LINKED_ENVVARS : +set tserr "$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS () +$warn_msgs: Ignore invalid link defined in MODULES_LINKED_ENVVARS ()" +testouterr_cmd bash {load link/1} $ans $tserr + + +# error raised +setenv_var MODULES_LINKED_ENVVARS FOO&BAR +setenv_var TESTSUITE_LINKED_ENVVARS append_err1 +set tserr [escre [msg_load link/1 [msg_moderr {invalid option '--bad' for append-path} {append-path --bad FOO value} $mp/link/1 2]]] +testouterr_cmd_re bash {load link/1} ERR $tserr + + +# test on source-sh +setenv_var MODULES_LINKED_ENVVARS FOOSP&BAR +set mp $modpath.2 +set mpre $modpathre.2 +setenv_var MODULEPATH $mp +setenv_var TESTSUITE_SHTOMOD_NOPATH 1 +setenv_var TESTSUITE_SHTOMOD_NOALIAS 1 +setenv_var TESTSUITE_SHTOMOD_NOFUNC 1 +setenv_var TESTSUITE_SHTOMOD_NOCD 1 +setenv_var TESTSUITE_SHTOMOD_NOCOMP 1 +setenv_var FOO value + +set ans [list] +lappend ans [list set BAR {value }] +lappend ans [list set FOOCB va\{ue] +lappend ans [list set _LMFILES_ $mp/source-sh/1] +lappend ans [list set LOADEDMODULES source-sh/1] +lappend ans [list set FOOWC va\*ue] +lappend ans [list set FOOEM {}] +lappend ans [list set __MODULES_LMSOURCESH {source-sh/1&bash testsuite/example/sh-to-mod.sh|setenv FOOCB va\{ue|setenv FOOEM {}|setenv FOOSP {value }|setenv FOOWC va*ue}] +lappend ans [list set FOOSP {value }] +testouterr_cmd sh {load source-sh/1} $ans {} + +set tserr "$modlin +$mpre/source-sh/1: + +setenv\t\tFOOCB va\{ue +setenv\t\tFOOEM {} +setenv\t\tFOOSP {value } +setenv\t\tBAR {value } +setenv\t\tFOOWC va\\*ue +module-whatis\tsource-sh/1 +$modlin" +testouterr_cmd_re sh {display source-sh/1} OK $tserr + +setenv_loaded_module [list source-sh/1] [list $mp/source-sh/1] +setenv_var FOOCB val\{ue +setenv_var FOOEM {} +setenv_var FOOSP {value } +setenv_var BAR {value } +setenv_var FOOWC va*ue +setenv_var __MODULES_LMSOURCESH "source-sh/1&bash testsuite/example/sh-to-mod.sh|setenv FOOCB va{ue|setenv FOOEM {}|setenv FOOSP {value }|setenv FOOWC va*ue" + +set ans [list] +lappend ans [list unset BAR] +lappend ans [list unset FOOCB] +lappend ans [list unset _LMFILES_] +lappend ans [list unset LOADEDMODULES] +lappend ans [list unset FOOWC] +lappend ans [list unset FOOEM] +lappend ans [list unset __MODULES_LMSOURCESH] +lappend ans [list unset FOOSP] +testouterr_cmd sh {unload source-sh/1} $ans {} + + +# +# Cleanup +# + +reset_test_env diff --git a/testsuite/modules.70-maint/120-autoinit.exp b/testsuite/modules.70-maint/120-autoinit.exp index fa23cb268..6fe37f388 100644 --- a/testsuite/modules.70-maint/120-autoinit.exp +++ b/testsuite/modules.70-maint/120-autoinit.exp @@ -93,7 +93,7 @@ if {[info exists insmodrcdata] && [info exists exmodrcdata] && $exmodrcdata eq $ } set custom {module restore unk} -set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 54 { }]] +set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 57 { }]] set tserr_modrc_exinstalled [msg_load null] set tserr_initrc_exinstalled "[msg_load mj]\nload m1\nload m2\n\n[msg_top_load m2 {} m1 {}]\n\nunload m2\n[msg_unload m2]\nunload m1\n[msg_unload {m1 }]\n[msg_unload mj]\nload m1\n[msg_load {m1 }]\nload m3\n[msg_load m3]\n[msg_load {'space yc/4'}]\n$err_path'unk'\n$custom" @@ -1608,6 +1608,48 @@ if {!$insmodspath && $initrc_exinstalled && !$install_setshellstartup && $modrc unsetenv_path_var BAR unsetenv_path_var FOO + + # test impact of linked envvars configuration + setenv_var MODULES_LINKED_ENVVARS FOO&BAR + setenv_var TESTSUITE_INITRC linked_envvars1 + + set ans [list] + lappend ans [list ERR] + lappend ans [list [set "func_$shell"]] + if {$install_versioning eq "y"} { + lappend ans [list set LOADEDMODULES "m1:m3:space yc/4"] + lappend ans [list set _LMFILES_ "$modpath.deps/m1:$modpath.deps/m3:$modpath wspace/space yc/4"] + lappend ans [list set MODULESHOME $moduleshome] + lappend ans [list set MODULE_VERSION "(.*)"] + lappend ans [list set __MODULES_LMTAG m1&auto-loaded] + lappend ans [list set MODULES_CMD $modulecmd_path] + lappend ans [list set __MODULES_LMPREREQ m3&m1] + lappend ans [list set MODULE_VERSION_STACK "(.*)"] + lappend ans [list set MODULEPATH "$modpath wspace:$modpath.deps"] + lappend ans [list set __MODULES_LMINIT $lminit_initrc_exinstalled] + lappend ans [list set FOO value] + lappend ans [list set BAR value] + if {$change_path} { + lappend ans [list set PATH $updatedpath] + } + lappend ans [list unset __MODULES_AUTOINIT_INPROGRESS] + } else { + lappend ans [list set FOO value] + lappend ans [list set MODULES_CMD $modulecmd_path] + lappend ans [list set BAR value] + lappend ans [list unset __MODULES_AUTOINIT_INPROGRESS] + lappend ans [list set MODULESHOME $moduleshome] + lappend ans [list set __MODULES_LMPREREQ m3&m1] + lappend ans [list set _LMFILES_ "$modpath.deps/m1:$modpath.deps/m3:$modpath wspace/space yc/4"] + lappend ans [list set LOADEDMODULES "m1:m3:space yc/4"] + lappend ans [list set __MODULES_LMINIT $lminit_initrc_exinstalled] + lappend ans [list set __MODULES_LMTAG m1&auto-loaded] + lappend ans [list set MODULEPATH "$modpath wspace:$modpath.deps"] + } + testouterr_cmd_re sh autoinit $ans $tserr_initrc_exinstalled + unsetenv_var MODULES_LINKED_ENVVARS + + # test impact of use of module sub-commands that cannot be used in an initrc script setenv_var TESTSUITE_INITRC subcmd1 @@ -1692,7 +1734,7 @@ if {!$insmodspath && $initrc_exinstalled && !$install_setshellstartup && $modrc lappend ans [list set MODULEPATH "$modpath wspace:$modpath.deps"] } set custom {module restore unk} - set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 54 { }]] + set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 57 { }]] set tserr "[msg_load mj]\nload m1\nload m2\n\n[msg_top_load m2 {} m1 {}]\n\nunload m2\n[msg_unload m2]\nunload m1\n[msg_unload {m1 }]\n[msg_unload mj]\nload m1\n[msg_load {m1 }]\nload m3\n[msg_load m3]\n[msg_load {'space yc/4'}]\n$err_path'unk'\n$custom" testouterr_cmd_re bash autoinit $ans $tserr @@ -1730,7 +1772,7 @@ if {!$insmodspath && $initrc_exinstalled && !$install_setshellstartup && $modrc lappend ans [list set MODULEPATH "$modpath wspace:$modpath.deps"] } set custom {module restore unk} - set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 54 { }]] + set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 57 { }]] set tserr "[msg_load mj]\nload m1\nload m2\n\n[msg_top_load m2 {} m1 {}]\n\nunload m2\n[msg_unload m2]\nunload m1\n[msg_unload {m1 }]\n[msg_unload mj]\nload m1\n[msg_load {m1 }]\nload m3\n[msg_load m3]\n[msg_load {'space yc/4'}]\n$err_path'unk'\n$custom" testouterr_cmd_re bash autoinit $ans $tserr @@ -1771,7 +1813,7 @@ if {!$insmodspath && $initrc_exinstalled && !$install_setshellstartup && $modrc lappend ans [list set MODULES_SET_SHELL_STARTUP 1] lappend ans [list unset __MODULES_AUTOINIT_INPROGRESS] set custom {module restore unk} - set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 54 { }]] + set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 57 { }]] set tserr "[msg_load mj]\nload m1\nload m2\n\n[msg_top_load m2 {} m1 {}]\n\nunload m2\n[msg_unload m2]\nunload m1\n[msg_unload {m1 }]\n[msg_unload mj]\nload m1\n[msg_load {m1 }]\nload m3\n[msg_load m3]\n[msg_load {'space yc/4'}]\n[msg_load {refresh/5.0 }]\n$err_path'unk'\n$custom" testouterr_cmd_re bash autoinit $ans $tserr @@ -1815,7 +1857,7 @@ if {!$insmodspath && $initrc_exinstalled && !$install_setshellstartup && $modrc lappend ans [list set MODULEPATH "$modpath.3:$modpath wspace:$modpath.deps"] } set custom {module restore unk} - set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 54 { }]] + set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 57 { }]] set tserr "[msg_load mj]\nload m1\nload m2\n\n[msg_top_load m2 {} m1 {}]\n\nunload m2\n[msg_unload m2]\nunload m1\n[msg_unload {m1 }]\n[msg_unload mj]\nload m1\n[msg_load {m1 }]\nload m3\n[msg_load m3]\n[msg_load {'space yc/4'}]\n[msg_load {foo/0.2 }]\n\n[msg_top_load {foo/0.load } {} foo/1.0 {}]\n\n$err_path'unk'\n$custom" testouterr_cmd_re bash autoinit $ans $tserr @@ -1864,7 +1906,7 @@ if {!$insmodspath && $initrc_exinstalled && !$install_setshellstartup && $modrc lappend ans [list set MODULEPATH "$modpath.3:$modpath wspace:$modpath.deps"] } set custom {module restore unk} - set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 54 { }]] + set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 57 { }]] set tserr "[msg_load mj]\nload m1\nload m2\n\n[msg_top_load m2 {} m1 {}]\n\nunload m2\n[msg_unload m2]\nunload m1\n[msg_unload {m1 }]\n[msg_unload mj]\nload m1\n[msg_load {m1 }]\nload m3\n[msg_load m3]\n[msg_load {'space yc/4'}]\n[msg_load {variant/1.0{bar=val1:\+foo}}]\n$err_path'unk'\n$custom" testouterr_cmd_re bash autoinit $ans $tserr @@ -1897,7 +1939,7 @@ if {!$insmodspath && $initrc_exinstalled && !$install_setshellstartup && $modrc lappend ans [list set MODULE_VERSION "(.*)"] } set custom {module restore unk} - set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 54 { }]] + set custom [escre [msg_moderr {Collection unk cannot be found} $custom $modrc 57 { }]] set tserr "[msg_load mj]\nload m1\nload m2\n\n[msg_top_load m2 {} m1 {}]\n\nunload m2\n[msg_unload m2]\nunload m1\n[msg_unload {m1 }]\n[msg_unload mj]\nload m1\n[msg_load {m1 }]\nload m3\n[msg_load m3]\n[msg_load {'space yc/4'}]\n[msg_unload {'space yc/4'}]\nunload m3\n[msg_unload m3]\nunload m1\n[msg_unload {m1 }]\n$err_path'unk'\n$custom" testouterr_cmd_re bash autoinit $ans $tserr