diff --git a/.github/workflows/linux_tests.yaml b/.github/workflows/linux_tests.yaml index 86d9544bb..928cb699a 100644 --- a/.github/workflows/linux_tests.yaml +++ b/.github/workflows/linux_tests.yaml @@ -132,7 +132,7 @@ jobs: tcl85-2: runs-on: ubuntu-22.04 env: - CONFIGURE_OPTS: --with-tclsh=tclsh8.5 --prefix=/tmp/modules --with-tcl=/usr/local/lib --enable-quarantine-support --enable-silent-shell-debug-support --enable-modulespath --with-pager=more --with-dark-background-colors=hi --with-locked-configs=implicit_default --enable-wa-277 --enable-advanced-version-spec --disable-ml --disable-implicit-requirement --enable-set-shell-startup + CONFIGURE_OPTS: --with-tclsh=tclsh8.5 --prefix=/tmp/modules --with-tcl=/usr/local/lib --enable-quarantine-support --enable-silent-shell-debug-support --enable-modulespath --with-pager=more --with-dark-background-colors=hi --with-locked-configs=implicit_default --enable-wa-277 --enable-advanced-version-spec --disable-ml --disable-implicit-requirement --enable-set-shell-startup --enable-path-entry-reorder COVERAGE: y EXTRA_SCRIPT_PRETEST: make install-testinitrc-1 install-testetcrc install-testmodspath EXTRA_SCRIPT_POSTTEST: make uninstall-testconfig diff --git a/.hunspell.en.dic b/.hunspell.en.dic index 387b120fc..a24475296 100644 --- a/.hunspell.en.dic +++ b/.hunspell.en.dic @@ -1324,3 +1324,5 @@ structs reimplementation gid cmp +Achim +Gsell diff --git a/INSTALL.rst b/INSTALL.rst index 725c48f09..2dcb25d2d 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -750,6 +750,19 @@ instance :instopt:`--disable-set-manpath<--enable-set-manpath>`): .. versionchanged:: 5.6 Enables automated *require via* mechanism +.. instopt:: --enable-path-entry-reorder + + Change order of entry in a path-like environment variable, when + :mfcmd:`prepend-path`, :mfcmd:`append-path` or :subcmd:`use` target a path + entry that is already defined in the environment variable. (default=no) + + This installation option defines the default value of the + :mconfig:`path_entry_reorder` configuration option which could be changed + after installation with the :subcmd:`config` sub-command. + + .. only:: html or latex + + .. versionadded:: 5.7 .. instopt:: --enable-quarantine-support @@ -1723,6 +1736,9 @@ installation. | | | :envvar:`MODULES_PAGER`, | | | | | | :option:`--paginate`, :option:`--no-pager` | | | +-----------------------------------+----------------------------------------------+----------------------------------------------+--------------+-----------+ +| :mconfig:`path_entry_reorder` | ``0`` | :instopt:`--enable-path-entry-reorder`, | | | +| | | :envvar:`MODULES_PATH_ENTRY_REORDER` | | | ++-----------------------------------+----------------------------------------------+----------------------------------------------+--------------+-----------+ | :mconfig:`protected_envvars` | *Unset by default* | :envvar:`MODULES_PROTECTED_ENVVARS` | | | +-----------------------------------+----------------------------------------------+----------------------------------------------+--------------+-----------+ | :mconfig:`quarantine_support` | ``0`` | :instopt:`--enable-quarantine-support`, | X | | diff --git a/Makefile b/Makefile index e9146c5cb..2e2d5fa77 100644 --- a/Makefile +++ b/Makefile @@ -394,6 +394,12 @@ else setwa277 := 0 endif +ifeq ($(pathentryreorder),y) + setpathentryreorder := 1 +else + setpathentryreorder := 0 +endif + ifneq ($(tcllinteropts),) tcllintercmd := $(tcllinter) $(tcllinteropts) else @@ -442,6 +448,7 @@ sed -e 's|@prefix@|$(prefix)|g' \ -e 's|@sourcecache@|$(setsourcecache)|g' \ -e 's|@searchmatch@|$(searchmatch)|g' \ -e 's|@wa277@|$(setwa277)|g' \ + -e 's|@pathentryreorder@|$(setpathentryreorder)|g' \ -e 's|@icase@|$(icase)|g' \ -e 's|@nearlyforbiddendays@|$(nearlyforbiddendays)|g' \ -e 's|@tagabbrev@|$(tagabbrev)|g' \ diff --git a/Makefile.inc.in b/Makefile.inc.in index e9ad51750..bf13406b8 100644 --- a/Makefile.inc.in +++ b/Makefile.inc.in @@ -158,6 +158,9 @@ variantshortcut := @variantshortcut@ # editor editor := @editor@ +# path change behavior +pathentryreorder := @pathentryreorder@ + # shell completion location bashcompletiondir := @bashcompletiondir@ fishcompletiondir := @fishcompletiondir@ diff --git a/NEWS.rst b/NEWS.rst index e764bd8b9..85e3bd01b 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -38,6 +38,13 @@ Modules 5.7.0 (not yet released) environment variable on Fish shell version 4.3. * When fetching user's groups, in case a group name cannot be resolved use this group gid number as name instead of raising an error. (fix issue #604) +* Introduce :mconfig:`path_entry_reorder` configuration option that change + order of entry in a path-like environment variable when it is added again. + This new configuration option is disabled by default. This option can be + changed at installation time with :instopt:`--enable-path-entry-reorder`. + When :mconfig:`path_entry_reorder` is changed with :subcmd:`config` + sub-command, it sets the :envvar:`MODULES_PATH_ENTRY_REORDER` environment + variable. (fix issue #595 with contribution from Achim Gsell) .. _5.6 release notes: diff --git a/configure b/configure index fc4a34d25..84f07c2a5 100755 --- a/configure +++ b/configure @@ -34,7 +34,7 @@ multilibsupport libdir64 libdir32 versioning silentshdbgsupport \ setshellstartup quarantinesupport autohandling availindepth implicitdefault \ extendeddefault moduleshome initconfin pager pageropts verbosity color \ darkbgcolors lightbgcolors termbg lockedconfigs icase unloadmatchorder \ -searchmatch modulepath loadedmodules quarantinevars wa277 advversspec ml \ +searchmatch modulepath loadedmodules quarantinevars wa277 pathentryreorder advversspec ml \ windowssupport nearlyforbiddendays implicitrequirement tagabbrev \ tagcolorname mcookieversioncheck availoutput availterseoutput listoutput \ listterseoutput editor variantshortcut bashcompletiondir fishcompletiondir \ @@ -79,6 +79,7 @@ extendeddefault=y advversspec=y ml=y wa277=n +pathentryreorder=n loadedmodules= quarantinevars= binsearchpath=/usr/bin:/bin:/usr/local/bin @@ -291,6 +292,9 @@ Optional Features: --enable-require-via set modulecmd.tcl to consider that a module enabling a modulepath is a requirement for the loaded modules stored in this modulepath [no] + --enable-path-entry-reorder + change order of entry in a path-like environment + variable when it is added again [no] --enable-implicit-requirement implicitly define a requirement toward modules specified on ``module load`` or ``module unload`` @@ -803,6 +807,9 @@ for arg in "$@"; do --enable-mcookie-version-check*|--disable-mcookie-version-check) # shellcheck disable=SC2034 mcookieversioncheck=$(get_feature_value "$arg") ;; + --enable-path-entry-reorder*|--disable-path-entry-reorder) + # shellcheck disable=SC2034 + pathentryreorder=$(get_feature_value "$arg") ;; --with-bin-search-path=*|--without-bin-search-path) binsearchpath=$(get_package_value "$arg") ;; --with-moduleshome=*|--without-moduleshome) diff --git a/doc/source/changes.rst b/doc/source/changes.rst index 957478acd..e5ea70a3b 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -1071,6 +1071,8 @@ The following environment variables appeared on Modules 5. | | :envvar:`__MODULES_LMUSE`, | | | :envvar:`MODULES_REQUIRE_VIA` | +------------+-----------------------------------------------------------------+ +| 5.7 | :envvar:`MODULES_PATH_ENTRY_REORDER` | ++------------+-----------------------------------------------------------------+ Modules Specific Tcl Commands """"""""""""""""""""""""""""" @@ -1279,6 +1281,8 @@ The following Modules configuration option has been introduced on Modules 5. | 5.6 | :mconfig:`spider_output`, :mconfig:`spider_terse_output`, | | | :mconfig:`spider_indepth`, :mconfig:`require_via` | +------------+-----------------------------------------------------------------+ +| 5.7 | :mconfig:`path_entry_reorder` | ++------------+-----------------------------------------------------------------+ :mconfig:`auto_handling` diff --git a/doc/source/module.rst b/doc/source/module.rst index f74f576c7..3daec84c2 100644 --- a/doc/source/module.rst +++ b/doc/source/module.rst @@ -1370,6 +1370,23 @@ Module Sub-Commands sub-command when changing this configuration option from its default value. See :envvar:`MODULES_PAGER` description for details. + .. mconfig:: path_entry_reorder + + Change order of entry in a path-like environment variable, when + :mfcmd:`prepend-path`, :mfcmd:`append-path` or :subcmd:`use` target a path + entry that is already defined in the environment variable. + + Default value is ``0``. It can be changed at installation time with the + :instopt:`--enable-path-entry-reorder` option. The + :envvar:`MODULES_PATH_ENTRY_REORDER` environment variable is defined by + :subcmd:`config` sub-command when changing this configuration option from + its default value. See :envvar:`MODULES_PATH_ENTRY_REORDER` description + for details. + + .. only:: html or latex + + .. versionadded:: 5.7 + .. mconfig:: protected_envvars Prevents any modification of listed environment variables (colon `:` @@ -5274,6 +5291,38 @@ ENVIRONMENT .. versionchanged:: 5.5 No pager when :file:`modulecmd.tcl` is run for scripting languages +.. envvar:: MODULES_PATH_ENTRY_REORDER + + This environment variable changes the behavior of :mfcmd:`prepend-path`, + :mfcmd:`append-path` and :mfcmd:`module use` modulefile commands and + sub-commands. + + If set to ``1``, and one of these commands targets a path entry that already + exists in the environment variable, the entry is moved to the beginning or + end (depending on the command), unless duplicates are allowed. If set to + ``0``, the environment variable is not modified when the entry already + exists. + + .. parsed-literal:: + + :ps:`$` module config path_entry_reorder 0 + :ps:`$` module append-path PATHVAR /foo + :ps:`$` module append-path PATHVAR /bar + :ps:`$` module append-path PATHVAR /foo + :ps:`$` echo $PATHVAR + /foo:/bar + :ps:`$` module config path_entry_reorder 1 + :ps:`$` module append-path PATHVAR /foo + :ps:`$` echo $PATHVAR + /bar:/foo + :ps:`$` module append-path --duplicates PATHVAR /bar + :ps:`$` echo $PATHVAR + /bar:/foo:/bar + + .. only:: html or latex + + .. versionadded:: 5.7 + .. envvar:: MODULES_PROTECTED_ENVVARS A colon separated list of environment variable names that should not be diff --git a/doc/source/other-implementations.rst b/doc/source/other-implementations.rst index 26f683f4f..5d2f99f57 100644 --- a/doc/source/other-implementations.rst +++ b/doc/source/other-implementations.rst @@ -43,7 +43,6 @@ table highlights features that are unique to each implementation. * `i18n`_ * `Find best module`_ * `Path entry priorities`_ - * `Update path entry order`_ * ``--regexp`` search option * `settarg`_ * `Hook functions`_ @@ -158,6 +157,8 @@ implementation. - :ref:`Requiring via module` * - `Autoswap`_ - :ref:`Conflict unload MIGRATING` + * - `Update path entry order`_ + - :mconfig:`path_entry_reorder` configuration option * - |LMOD_DOWNSTREAM_CONFLICTS|_ environment variable - :ref:`Dependencies between modulefiles` * - |LMOD_QUARANTINE_VARS|_ environment variable @@ -286,5 +287,5 @@ additional tools that enhance how modulefiles are handled. If you're aware of a ``module``-related project missing from this list, feel free to :ref:`contact us` so we can add it. -.. |modules_version| replace:: Modules 5.6.0 +.. |modules_version| replace:: Modules 5.7.0 (not yet released) .. |lmod_version| replace:: Lmod 9.0.5 diff --git a/init/Makefile b/init/Makefile index 19c51a258..3bf487b03 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 list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days pager 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 list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days pager 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) @@ -167,6 +167,7 @@ sed -e 's|@prefix@|$(prefix)|g' \ -e 's|@comp_path_opts@|$(comp_path_opts)|g' \ -e 's|@comp_rm_path_opts@|$(comp_rm_path_opts)|g' \ -e 's|@comp_config_opts@|$(comp_config_opts)|g' \ + -e 's|@comp_path_entry_reorder@|$(comp_path_entry_reorder)|g' \ -e '$(setzshfpathre)' \ -e $$'s|@modulerc@|$(modulerc)|g' \ -e 's|@modulepath@|$(modulepath)|g' \ diff --git a/init/fish_completion b/init/fish_completion index 943429bae..1b0a07a5c 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 list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days pager 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 list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days pager 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 380773e19..397b64afe 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 list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days pager 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 list_output list_terse_output locked_configs logged_events logger mcookie_check mcookie_version_check ml nearly_forbidden_days pager 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) diff --git a/site.exp.in b/site.exp.in index 6d35a6b27..d5fff5e3d 100644 --- a/site.exp.in +++ b/site.exp.in @@ -117,6 +117,8 @@ set install_variantshortcut "@variantshortcut@" set install_editor "@editor@" +set install_pathentryreorder "@pathentryreorder@" + set install_bashcompletiondir "@bashcompletiondir@" set install_fishcompletiondir "@fishcompletiondir@" set install_zshcompletiondir "@zshcompletiondir@" diff --git a/tcl/envmngt.tcl.in b/tcl/envmngt.tcl.in index f02f32706..43b6cee41 100644 --- a/tcl/envmngt.tcl.in +++ b/tcl/envmngt.tcl.in @@ -1808,27 +1808,43 @@ proc add-path {cmd mode dflbhv args} { set val [get-env $var] foreach dir $path_list { - if {![info exists countarr($dir)] || $allow_dup} { + # remove $dir from path only if path_entry_reorder is true and + # $dir is already in path and duplicates are NOT allowed. + if {[getConf path_entry_reorder] && [info exists countarr($dir)]\ + && ! $allow_dup} { + set mpath_list [split $val $separator] + set mpath_list [lsearch -inline -all -not -exact $mpath_list $dir] + set val [join $mpath_list $separator] + } + # add $dir to beginning or end only if path_entry_reorder is true or + # $dir is NOT in path or duplicates are allowed. + # Please note: if path_entry_reorder is true and duplicates are not + # allowed, $dir is not in path ($val) - either it was not in or it + # had been removed. Hence we have to add it. + if {[getConf path_entry_reorder] || ![info exists countarr($dir)]\ + || $allow_dup} { # ignore env var set empty if no empty entry found in reference # counter array (sometimes var is cleared by setting it empty not # unsetting it) if {$val ne {} || [info exists countarr()]} { set sep [expr {$val eq $separator ? {} : $separator}] set val [expr {$bhv eq {prepend} ? "$dir$sep$val" :\ - "$val$sep$dir"}] + "$val$sep$dir"}] } else { set val $dir } } - if {[info exists countarr($dir)]} { - # do not increase counter if bare separator string is added or if - # reference count is ignored (--ignore-refcount set) unless if - # duplicate mode is enabled (--duplicates set) - if {!$val_set_is_delim && (!$ign_refcount || $allow_dup)} { - incr countarr($dir) - } - } else { + #### ref-counting + # if $dir is NOT in path + # set ref-count 1 + # else + # do NOT increase counter if bare separator string is added or if + # reference count is ignored (--ignore-refcount set) unless if + # duplicate mode is enabled (--duplicates set) + if {![info exists countarr($dir)]} { set countarr($dir) 1 + } elseif {!$val_set_is_delim && (!$ign_refcount || $allow_dup)} { + incr countarr($dir) } } @@ -2046,7 +2062,10 @@ proc getModulesEnvVarGlobList {{loaded_ctx 0}} { return $envvar_glob_list } -# ;;; Local Variables: *** -# ;;; mode:tcl *** -# ;;; End: *** +# ;;; Local Variables: +# ;;; Mode: tcl-mode +# ;;; tcl-indent-level: 3 +# ;;; tcl-continued-indent-level: 3 +# ;;; indent-tabs-mode: nil +# ;;; End: # vim:set tabstop=3 shiftwidth=3 expandtab autoindent: diff --git a/tcl/init.tcl.in b/tcl/init.tcl.in index 840dc6f6c..902ebd164 100644 --- a/tcl/init.tcl.in +++ b/tcl/init.tcl.in @@ -121,6 +121,7 @@ array set g_config_defs [list\ nearly_forbidden_days {MODULES_NEARLY_FORBIDDEN_DAYS @nearlyforbiddendays@\ 0 i {0 365} {} {} intbe}\ pager {MODULES_PAGER {@pagercmd@} 0 s}\ + path_entry_reorder {MODULES_PATH_ENTRY_REORDER @pathentryreorder@ 0 b {0 1}}\ protected_envvars {MODULES_PROTECTED_ENVVARS 0 l}\ rcfile {MODULERCFILE 0 l}\ redirect_output {MODULES_REDIRECT_OUTPUT 1 0 b {0 1}}\ diff --git a/tcl/subcmd.tcl.in b/tcl/subcmd.tcl.in index 047b523f7..360860aa9 100644 --- a/tcl/subcmd.tcl.in +++ b/tcl/subcmd.tcl.in @@ -3155,7 +3155,10 @@ proc cmdModuleSpider {show_oneperline show_mtime show_filter search_filter\ $search_match $modpath_list {*}$args } -# ;;; Local Variables: *** -# ;;; mode:tcl *** -# ;;; End: *** +# ;;; Local Variables: +# ;;; Mode: tcl-mode +# ;;; tcl-indent-level: 3 +# ;;; tcl-continued-indent-level: 3 +# ;;; indent-tabs-mode: nil +# ;;; End: # vim:set tabstop=3 shiftwidth=3 expandtab autoindent: diff --git a/testsuite/install.00-init/010-environ.exp b/testsuite/install.00-init/010-environ.exp index 528786aec..ce76cb5c6 100644 --- a/testsuite/install.00-init/010-environ.exp +++ b/testsuite/install.00-init/010-environ.exp @@ -194,4 +194,7 @@ catch {unset env(MODULERCFILE)} # setup basic locale for tests set env(LANG) "C" +# ensure that tests doesn't run with Lmod path order +unsetenv_var MODULES_PATH_ENTRY_REORDER + # vim:set tabstop=3 shiftwidth=3 expandtab autoindent: diff --git a/testsuite/modulefiles.4/append/2.0 b/testsuite/modulefiles.4/append/2.0 index 1c148cdd2..b22032e1c 100644 --- a/testsuite/modulefiles.4/append/2.0 +++ b/testsuite/modulefiles.4/append/2.0 @@ -1 +1,24 @@ -#%Module +#%Module1.0 + +############################################################################## +# Modules Revision 3.0 +# Providing a flexible user environment +# +# File: append/%M% +# Revision: %I% +# First Edition: 2026/01/08 +# Last Mod.: %U%, %G% +# +# Authors: Achim Gsell, achim.gsell@psi.ch +# +# Description: Test appending paths with path_entry_enabled +# Command: +# Sub-Command: append-path +# +# Invocation: load @M@/@V@ +# Comment: %C{ +# }C% +# +############################################################################## + +append-path FOO /test/dir1 /test/dir2 /test/dir3 diff --git a/testsuite/modulefiles.4/append/3.0 b/testsuite/modulefiles.4/append/3.0 new file mode 100644 index 000000000..1c148cdd2 --- /dev/null +++ b/testsuite/modulefiles.4/append/3.0 @@ -0,0 +1 @@ +#%Module diff --git a/testsuite/modules.00-init/010-environ.exp b/testsuite/modules.00-init/010-environ.exp index db0a2a5a1..42932b45a 100644 --- a/testsuite/modules.00-init/010-environ.exp +++ b/testsuite/modules.00-init/010-environ.exp @@ -188,6 +188,9 @@ catch {unset env(MODULES_COLLECTION_TARGET)} catch {unset env(MODULE_VERSION)} catch {unset env(MODULE_VERSION_STACK)} +# ensure that tests doesn't run with Lmod path order +unsetenv_var MODULES_PATH_ENTRY_REORDER + set env(MODULERCFILE) "$env(TESTSUITEDIR)/etc/empty" set ORIG_MODULERCFILE $env(MODULERCFILE) catch {unset env(MODULESHOME)} diff --git a/testsuite/modules.50-cmds/040-append.exp b/testsuite/modules.50-cmds/040-append.exp index eade6e4e7..223cb41fe 100644 --- a/testsuite/modules.50-cmds/040-append.exp +++ b/testsuite/modules.50-cmds/040-append.exp @@ -165,6 +165,7 @@ testouterr_cmd "sh" "load $module" $ans "" set module "append/4.0" set modulefile "$modpath/$module" +setenv_var MODULES_PATH_ENTRY_REORDER 0 unsetenv_path_var FOO set env(__MODULES_SHARE_BAR) "/path/to/dir1:2" set env(BAR) "/path/to/dir1:/path/to/dir2:/path/to/dir1" @@ -179,6 +180,22 @@ lappend ans [list set LOADEDMODULES $module] testouterr_cmd "sh" "load $module" $ans "" +setenv_var MODULES_PATH_ENTRY_REORDER 1 +unsetenv_path_var FOO +set env(__MODULES_SHARE_BAR) "/path/to/dir1:2" +set env(BAR) "/path/to/dir1:/path/to/dir2:/path/to/dir1" + +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO "/path/to/dir1:2"] +lappend ans [list set FOO "/path/to/dir1:/path/to/dir2:/path/to/dir1"] +lappend ans [list set __MODULES_SHARE_BAR "/path/to/dir1:3"] +lappend ans [list set BAR "/path/to/dir2:/path/to/dir1"] +lappend ans [list set _LMFILES_ $modulefile] +lappend ans [list set LOADEDMODULES $module] + +testouterr_cmd "sh" "load $module" $ans "" + +setenv_var MODULES_PATH_ENTRY_REORDER 0 set env(FOO) "/path/to/dir1" set ans [list] @@ -191,6 +208,20 @@ lappend ans [list set LOADEDMODULES $module] testouterr_cmd "sh" "load $module" $ans "" +setenv_var MODULES_PATH_ENTRY_REORDER 1 +set env(FOO) "/path/to/dir1" + +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO "/path/to/dir1:3"] +lappend ans [list set FOO "/path/to/dir1:/path/to/dir1:/path/to/dir2:/path/to/dir1"] +lappend ans [list set __MODULES_SHARE_BAR "/path/to/dir1:3"] +lappend ans [list set BAR "/path/to/dir2:/path/to/dir1"] +lappend ans [list set _LMFILES_ $modulefile] +lappend ans [list set LOADEDMODULES $module] + +testouterr_cmd "sh" "load $module" $ans "" + +setenv_var MODULES_PATH_ENTRY_REORDER 0 set env(__MODULES_SHARE_FOO) "/path/to/dir1:2" set env(FOO) "/path/to/dir1" @@ -204,6 +235,23 @@ lappend ans [list set LOADEDMODULES $module] testouterr_cmd "sh" "load $module" $ans "" +setenv_var MODULES_PATH_ENTRY_REORDER 1 +set env(__MODULES_SHARE_FOO) "/path/to/dir1:2" +set env(FOO) "/path/to/dir1" + +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO "/path/to/dir1:4"] +lappend ans [list set FOO "/path/to/dir1:/path/to/dir1:/path/to/dir2:/path/to/dir1"] +lappend ans [list set __MODULES_SHARE_BAR "/path/to/dir1:3"] +lappend ans [list set BAR "/path/to/dir2:/path/to/dir1"] +lappend ans [list set _LMFILES_ $modulefile] +lappend ans [list set LOADEDMODULES $module] + +testouterr_cmd "sh" "load $module" $ans "" + +# reset to default config +unset env(MODULES_PATH_ENTRY_REORDER) + # test unload mode on append-path --duplicates setenv_loaded_module [list $module] [list $modulefile] set ans [list] @@ -228,15 +276,16 @@ lappend ans [list unset _LMFILES_] lappend ans [list unset LOADEDMODULES] testouterr_cmd sh "unload $module" $ans {} +set module "append/4.1" +set modulefile "$modpath/$module" + +setenv_var MODULES_PATH_ENTRY_REORDER 0 setenv_var FOO /path/to/dir1 setenv_var __MODULES_SHARE_FOO /path/to/dir1:2 setenv_var BAR /path/to/dir1:/path/to/dir2:/path/to/dir1 setenv_var __MODULES_SHARE_BAR /path/to/dir1:2 unsetenv_loaded_module -set module "append/4.1" -set modulefile "$modpath/$module" - set ans [list] lappend ans [list set __MODULES_SHARE_FOO "/path/to/dir1:4"] lappend ans [list set FOO "/path/to/dir1:/path/to/dir1:/path/to/dir2:/path/to/dir1"] @@ -247,6 +296,25 @@ lappend ans [list set LOADEDMODULES $module] testouterr_cmd "sh" "load $module" $ans [msg_load $module "$warn_msgs: --index option has no effect on append-path"] +setenv_var MODULES_PATH_ENTRY_REORDER 1 +setenv_var FOO /path/to/dir1 +setenv_var __MODULES_SHARE_FOO /path/to/dir1:2 +setenv_var BAR /path/to/dir1:/path/to/dir2:/path/to/dir1 +setenv_var __MODULES_SHARE_BAR /path/to/dir1:2 +unsetenv_loaded_module + +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO "/path/to/dir1:4"] +lappend ans [list set FOO "/path/to/dir1:/path/to/dir1:/path/to/dir2:/path/to/dir1"] +lappend ans [list set __MODULES_SHARE_BAR "/path/to/dir1:3"] +lappend ans [list set BAR "/path/to/dir2:/path/to/dir1"] +lappend ans [list set _LMFILES_ $modulefile] +lappend ans [list set LOADEDMODULES $module] + +testouterr_cmd "sh" "load $module" $ans [msg_load $module "$warn_msgs: --index option has no effect on append-path"] + +# reset to default config +unset env(MODULES_PATH_ENTRY_REORDER) # test setting a large value in variable. For csh shell family, Modules # truncates value to avoid going over csh limit (this should be changed in @@ -297,6 +365,7 @@ testouterr_cmd_re "csh" "load $module" $ans $ts_err set module "append/6.0" set modulefile "$modpath/$module" +setenv_var MODULES_PATH_ENTRY_REORDER 0 set env(__MODULES_SHARE_FOO) "/path/to/dir3:2" set env(FOO) "/path/to/dir1:/path/to/dir4" @@ -309,6 +378,22 @@ lappend ans [list set LOADEDMODULES $module] # reference counter is automatically adjusted testouterr_cmd "sh" "load $module" $ans {} +setenv_var MODULES_PATH_ENTRY_REORDER 1 +set env(__MODULES_SHARE_FOO) "/path/to/dir3:2" +set env(FOO) "/path/to/dir1:/path/to/dir4" + +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO "/path/to/dir1:2"] +lappend ans [list set FOO "/path/to/dir4:/path/to/dir1:/path/to/dir2"] +lappend ans [list set _LMFILES_ $modulefile] +lappend ans [list set LOADEDMODULES $module] + +# reference counter is automatically adjusted +testouterr_cmd "sh" "load $module" $ans {} + +# reset to default config +unset env(MODULES_PATH_ENTRY_REORDER) + # test incoherent state on unload mode setenv_loaded_module $module $modulefile set ans [list] @@ -400,13 +485,33 @@ lappend ans [list unset LOADEDMODULES] testouterr_cmd "sh" "unload $module" $ans {} +# +# test that path entry is not removed if added twice and path_entry_reorder +# is true +# +set module "append/2.0" +set modulefile "$modpath.4/$module" + +setenv_var MODULEPATH $modpath.4 +setenv_var MODULES_PATH_ENTRY_REORDER 1 +setenv_var FOO /test/dir2 +unsetenv_var __MODULES_SHARE_FOO + +unsetenv_loaded_module +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO "/test/dir2:2"] +lappend ans [list set FOO "/test/dir1:/test/dir2:/test/dir3"] +lappend ans [list set _LMFILES_ $modulefile] +lappend ans [list set LOADEDMODULES $module] + +testouterr_cmd "sh" "load $module" $ans "" + # # --glob option # unsetenv_loaded_module unsetenv_path_var FOO -setenv_var MODULEPATH $modpath.4 set ans [list] lappend ans [list set FOO /tmp*] diff --git a/testsuite/modules.50-cmds/050-prepend.exp b/testsuite/modules.50-cmds/050-prepend.exp index e29a8d34d..99464789f 100644 --- a/testsuite/modules.50-cmds/050-prepend.exp +++ b/testsuite/modules.50-cmds/050-prepend.exp @@ -151,14 +151,13 @@ lappend ans [list set LOADEDMODULES $module] lappend ans [list set testsuite --delim=,:http://foobar.com] testouterr_cmd_re "sh" "load $module" $ans {} - # # Try prepending empty string and check reference counter # - set module "prepend/3.0" set modulefile "$modpath/$module" +setenv_var MODULES_PATH_ENTRY_REORDER 0 set ans [list] lappend ans [list set __MODULES_SHARE_FOO ":1"] lappend ans [list set FOO ""] @@ -192,6 +191,42 @@ lappend ans [list set LOADEDMODULES "$module2:$module"] testouterr_cmd_re "sh" "load $module2 $module" $ans "" +setenv_var MODULES_PATH_ENTRY_REORDER 1 +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO ":1"] +lappend ans [list set FOO ""] +lappend ans [list set _LMFILES_ $modulefile] +lappend ans [list set LOADEDMODULES $module] + +testouterr_cmd "sh" "load $module" $ans "" + +# empty var does not always mean empty path entry set, only if a corresponding +# reference counter array entry can be found +set env(FOO) "" +testouterr_cmd "sh" "load $module" $ans "" + +unset env(FOO) +set module2 "prepend/3.1" +set modulefile2 "$modpath/$module2" + +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO ":2"] +lappend ans [list set FOO "/path/to/dir:"] +lappend ans [list set _LMFILES_ "$modulefile:$modulefile2"] +lappend ans [list set LOADEDMODULES "$module:$module2"] + +testouterr_cmd_re "sh" "load $module $module2" $ans "" + +set ans [list] +lappend ans [list set __MODULES_SHARE_FOO ":2"] +lappend ans [list set FOO ":/path/to/dir"] +lappend ans [list set _LMFILES_ "$modulefile2:$modulefile"] +lappend ans [list set LOADEDMODULES "$module2:$module"] + +testouterr_cmd_re "sh" "load $module2 $module" $ans "" + +# reset to default config +unset env(MODULES_PATH_ENTRY_REORDER) # # Prepending multiple paths passed as one string diff --git a/testsuite/modules.70-maint/220-config.exp b/testsuite/modules.70-maint/220-config.exp index fe9a1676a..bafe310fc 100644 --- a/testsuite/modules.70-maint/220-config.exp +++ b/testsuite/modules.70-maint/220-config.exp @@ -93,6 +93,7 @@ array set configdfl [list\ ml [expr {$install_ml eq {y}}]\ nearly_forbidden_days $install_nearlyforbiddendays\ pager "$install_pagercmd"\ + path_entry_reorder [expr {$install_pathentryreorder eq {y}}]\ protected_envvars \ quarantine_support [expr {$install_quarantinesupport eq {y}}]\ rcfile \ @@ -158,6 +159,7 @@ array set configvar [list\ ml MODULES_ML\ nearly_forbidden_days MODULES_NEARLY_FORBIDDEN_DAYS\ pager MODULES_PAGER\ + path_entry_reorder MODULES_PATH_ENTRY_REORDER\ protected_envvars MODULES_PROTECTED_ENVVARS\ quarantine_support MODULES_QUARANTINE_SUPPORT\ rcfile MODULERCFILE\ @@ -213,6 +215,7 @@ array set configvalid [list\ mcookie_version_check {0 1}\ ml {0 1}\ nearly_forbidden_days {0 365}\ + path_entry_reorder {0 1}\ quarantine_support {0 1}\ redirect_output {0 1}\ require_via {0 1}\