diff --git a/.gitignore b/.gitignore index c70edb5c..832fd5af 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ /contrib/rpm/environment-modules.spec /contrib/scripts/add.modules /contrib/modulefiles/modules +/contrib/modulefiles/version /testsuite/example/.modulespath /testsuite/example/modulerc /compat diff --git a/INSTALL.rst b/INSTALL.rst index 1c508e46..2bac3225 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -225,7 +225,11 @@ instance ``--disable-set-manpath``): script between the two installed version of Modules (by setting-up the ``switchml`` shell function or alias). (default=yes) ---enable-versioning Append Modules version to installation prefix. +--enable-versioning Append Modules version to installation prefix and deploy + a ``versions`` modulepath shared between all versioning + enabled Modules installation. A modulefile corresponding + to Modules version is added to the shared modulepath and + enables to switch from one Modules version to another. (default=no) Optional Packages (the default for each option is displayed within diff --git a/Makefile b/Makefile index 186deae3..e19c7655 100644 --- a/Makefile +++ b/Makefile @@ -96,6 +96,13 @@ endif include version.inc endif +# comment entries if feature not enabled +ifeq ($(versioning),y) + setversioning := +else + setversioning := \# +endif + define translate-in-script sed -e 's|@prefix@|$(prefix)|g' \ -e 's|@libexecdir@|$(libexecdir)|g' \ @@ -106,6 +113,7 @@ sed -e 's|@prefix@|$(prefix)|g' \ -e 's|@TCLSH@|$(TCLSH)|g' \ -e 's|@pager@|$(pager)|g' \ -e 's|@pageropts@|$(pageropts)|g' \ + -e 's|@VERSIONING@|$(setversioning)|g' \ -e 's|@MODULES_RELEASE@|$(MODULES_RELEASE)|g' \ -e 's|@MODULES_BUILD@|$(MODULES_BUILD)|g' \ -e 's|@MODULES_RPM_RELEASE@|$(MODULES_RPM_RELEASE)|g' \ diff --git a/Makefile.inc.in b/Makefile.inc.in index 3e75891e..6ce03305 100644 --- a/Makefile.inc.in +++ b/Makefile.inc.in @@ -2,6 +2,7 @@ # run ./configure to generate Makefile.inc # set default installation paths +baseprefix := @baseprefix@ prefix := @prefix@ bindir := @bindir@ libexecdir := @libexecdir@ @@ -12,6 +13,9 @@ datarootdir := @datarootdir@ mandir := @mandir@ docdir := @docdir@ +# versioning mode installation +versioning := @versioning@ + # modulepaths and modulefiles to enable in default config modulepath := @modulepath@ loadedmodules := @loadedmodules@ diff --git a/configure b/configure index 6feaf734..f0fe247b 100755 --- a/configure +++ b/configure @@ -26,8 +26,8 @@ prog=${progpath##*/} targetlist="${progdir}/Makefile.inc ${progdir}/site.exp" # argument list -arglist="TCLSH SPHINXBUILD prefix bindir libexecdir etcdir initdir \ -datarootdir mandir docdir modulefilesdir setmanpath setbinpath \ +arglist="TCLSH SPHINXBUILD baseprefix prefix bindir libexecdir etcdir \ +initdir datarootdir mandir docdir modulefilesdir setmanpath setbinpath \ setdotmodulespath docinstall examplemodulefiles compatversion versioning \ pager pageropts modulepath loadedmodules quarantinevars" compatarglist= @@ -126,7 +126,11 @@ Optional Features: --enable-compat-version also build and install Modules compatibility (C) version and enable switching capabilities between the two versions [yes] - --enable-versioning append modules version to installation prefix [no] + --enable-versioning append modules version to installation prefix and + deploy a \`versions' modulepath, shared between all + versioning enabled Modules installation, containing + modulefiles that enable to switch from one Modules + version to another [no] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -329,6 +333,7 @@ if [ $defpageropts -eq 1 -a "${pager##*/}" != 'less' ]; then fi # adapt prefix if versioning enabled +baseprefix=$prefix if [ "$versioning" = 'y' ]; then # fetch modules version from git repository tags if [ -d '.git' ]; then diff --git a/contrib/modulefiles/modules.in b/contrib/modulefiles/modules.in index 4d1c1842..554afd86 100644 --- a/contrib/modulefiles/modules.in +++ b/contrib/modulefiles/modules.in @@ -21,3 +21,6 @@ set prefix @prefix@ setenv MODULESHOME $prefix prepend-path PATH @bindir@ prepend-path MANPATH @mandir@ + +# enable module versioning modulepath +@VERSIONING@module use @baseprefix@/versions diff --git a/contrib/modulefiles/version.in b/contrib/modulefiles/version.in new file mode 100644 index 00000000..e9f0647d --- /dev/null +++ b/contrib/modulefiles/version.in @@ -0,0 +1,43 @@ +#%Module1.0##################################################################### +## +## version modulefile +## +proc ModulesHelp { } { + global version + + puts stderr "\tInitializes new version of the module command" + puts stderr "\n\tVersion $version\n" +} + +module-whatis "Initializes new version of the module command" + +# for Tcl script use only +set version @VERSION@ + +if [ expr [ module-info mode load ] || [ module-info mode display ] ] { +# get rid of old version + module unload null + module unload modules + setenv MODULE_VERSION @VERSION@ +} + +# version stack +prepend-path MODULE_VERSION_STACK @VERSION@ + +if [ module-info mode remove ] { + set prevversion [lindex [split $env(MODULE_VERSION_STACK) : ] 0 ] + unsetenv MODULE_VERSION $prevversion + + # re-initialize previous module command version (if >4.0) + regsub $version "@libexecdir@/modulecmd.tcl" $prevprefix prevmodulecmd + if {[file exists $prevmodulecmd]} { + puts stdout [exec @TCLSH@ $prevmodulecmd [module-info shell] autoinit] + } +} + +if [ expr [ module-info mode load ] || [ module-info mode display ] ] { + # bring in new version + module load modules + puts stdout [exec @TCLSH@ @libexecdir@/modulecmd.tcl [module-info shell] autoinit] +} + diff --git a/init/Makefile b/init/Makefile index f0d78744..c1551cef 100644 --- a/init/Makefile +++ b/init/Makefile @@ -44,6 +44,9 @@ endif ALL_SHELLS = $(SH_LIKE) $(CSH_LIKE) $(OTHER) all: $(ALL_SHELLS) $(ALL_CONFIG) $(EXAMPLE_MODFILES_SRCDIR)/modules +ifeq ($(versioning),y) +all: $(EXAMPLE_MODFILES_SRCDIR)/version +endif # if enabled translate to keep text after markup elsewhere remove the # entire line @@ -65,6 +68,14 @@ else notcompatversionre := s|@notcompatversion@||g endif +# comment entries if feature not enabled +ifeq ($(versioning),y) + versdir := $(baseprefix)/versions + setversioning := +else + setversioning := \# +endif + # define translation rules for quarantine mechanism ifeq ($(quarantinevars),) setquarvarsre := /@setquarvars@/d @@ -84,6 +95,7 @@ endif define translate-in-script sed -e 's|@prefix@|$(prefix)|g' \ + -e 's|@baseprefix@|$(baseprefix)|g' \ -e 's|@libexecdir@|$(libexecdir)|g' \ -e 's|@initdir@|$(initdir)|g' \ -e 's|@etcdir@|$(etcdir)|g' \ @@ -99,6 +111,7 @@ sed -e 's|@prefix@|$(prefix)|g' \ -e '$(setquarvarsre)' $(quarvarsre) \ -e '$(notsetquarvarsre)' \ -e 's|@SHELLNAME@|$@|g' \ + -e 's|@VERSIONING@|$(setversioning)|g' \ -e 's|@VERSION@|$(MODULES_RELEASE)$(MODULES_BUILD)|g' \ -e 's|@TCLSH@|$(TCLSH)|g' $< > $@ endef @@ -124,6 +137,9 @@ profile-compat.sh: profile-compat.sh.in $(EXAMPLE_MODFILES_SRCDIR)/modules: $(EXAMPLE_MODFILES_SRCDIR)/modules.in ../version.inc $(translate-in-script) +$(EXAMPLE_MODFILES_SRCDIR)/version: $(EXAMPLE_MODFILES_SRCDIR)/version.in ../version.inc + $(translate-in-script) + # example configs for test rules install-testconfig: mkdir -p $(DESTDIR)$(initdir) @@ -157,6 +173,10 @@ endif ifeq ($(examplemodulefiles),y) cp $(addprefix $(EXAMPLE_MODFILES_SRCDIR)/,$(EXAMPLE_MODFILES)) $(DESTDIR)$(modulefilesdir)/ endif +ifeq ($(versioning),y) + mkdir -p $(DESTDIR)$(versdir) + cp $(EXAMPLE_MODFILES_SRCDIR)/version $(DESTDIR)$(versdir)/$(MODULES_RELEASE)$(MODULES_BUILD) +endif uninstall: rm -f $(addprefix $(DESTDIR)$(initdir)/,$(ALL_SHELLS) fish_completion) @@ -172,6 +192,14 @@ endif rmdir $(DESTDIR)$(initdir)/zsh-functions rmdir --ignore-fail-on-non-empty $(DESTDIR)$(initdir) @if [ -d $(DESTDIR)$(initdir) ]; then echo -e "\nWARNING: $(DESTDIR)$(initdir) is not empty so skip removal\n" >&2; fi +ifeq ($(versioning),y) + rm -f $(DESTDIR)$(versdir)/$(MODULES_RELEASE)$(MODULES_BUILD) + rmdir --ignore-fail-on-non-empty $(DESTDIR)$(versdir) + @if [ -d $(DESTDIR)$(versdir) ]; then echo -e "\nWARNING: $(DESTDIR)$(versdir) is not empty so skip removal\n" >&2; fi +endif clean: rm -f $(ALL_SHELLS) modulerc .modulespath $(EXAMPLE_MODFILES_SRCDIR)/modules +ifeq ($(versioning),y) + rm -f $(EXAMPLE_MODFILES_SRCDIR)/version +endif diff --git a/modulecmd.tcl.in b/modulecmd.tcl.in index 260dd762..4ef5e333 100755 --- a/modulecmd.tcl.in +++ b/modulecmd.tcl.in @@ -5785,6 +5785,12 @@ proc cmdModuleAutoinit {} { # default MODULESHOME setenv MODULESHOME "@prefix@" + # define current Modules version if versioning enabled + @VERSIONING@if {![info exists env(MODULE_VERSION)]} { + @VERSIONING@ setenv MODULE_VERSION "@MODULES_RELEASE@@MODULES_BUILD@" + @VERSIONING@ setenv MODULE_VERSION_STACK "@MODULES_RELEASE@@MODULES_BUILD@" + @VERSIONING@} + # initialize default MODULEPATH and LOADEDMODULES if {![info exists env(MODULEPATH)] || $env(MODULEPATH) eq ""} { # set modpaths defined in .modulespath config file if it exists diff --git a/site.exp.in b/site.exp.in index 93bfc439..9a3f1e89 100644 --- a/site.exp.in +++ b/site.exp.in @@ -6,6 +6,8 @@ set install_initdir "@initdir@" set install_libexecdir "@libexecdir@" set install_modulefilesdir "@modulefilesdir@" +set install_versioning "@versioning@" + set install_modulepath "@modulepath@" set install_loadedmodules "@loadedmodules@" diff --git a/testsuite/install.00-init/010-environ.exp b/testsuite/install.00-init/010-environ.exp index 204ba5c1..57e6697a 100644 --- a/testsuite/install.00-init/010-environ.exp +++ b/testsuite/install.00-init/010-environ.exp @@ -49,6 +49,10 @@ catch {unset env(LESS)} catch {unset env(PAGER)} catch {unset env(MODULES_PAGER)} +# clean any versioning configuration +catch {unset env(MODULE_VERSION)} +catch {unset env(MODULE_VERSION_STACK)} + catch {unset env(ENV)} catch {unset env(BASH_ENV)} catch {unset env(BASH_FUNC_module\(\))} diff --git a/testsuite/modules.00-init/010-environ.exp b/testsuite/modules.00-init/010-environ.exp index f5a68989..5283d734 100644 --- a/testsuite/modules.00-init/010-environ.exp +++ b/testsuite/modules.00-init/010-environ.exp @@ -48,5 +48,9 @@ catch {unset env(MODULES_PAGER)} catch {unset env(MODULES_COLLECTION_PIN_VERSION)} catch {unset env(MODULES_COLLECTION_TARGET)} +# clean any versioning configuration +catch {unset env(MODULE_VERSION)} +catch {unset env(MODULE_VERSION_STACK)} + set env(MODULERCFILE) "$env(TESTSUITEDIR)/etc/empty" catch {unset env(MODULESHOME)} diff --git a/testsuite/modules.70-maint/120-autoinit.exp b/testsuite/modules.70-maint/120-autoinit.exp index 47f6daa6..f19b9d05 100644 --- a/testsuite/modules.70-maint/120-autoinit.exp +++ b/testsuite/modules.70-maint/120-autoinit.exp @@ -320,7 +320,13 @@ foreach shell $supported_shells { } else { set ans [list] lappend ans [list [set "func_$shell"]] - lappend ans [list set MODULESHOME $moduleshome] + if {$install_versioning eq "y"} { + lappend ans [list set MODULE_VERSION_STACK "(.*)"] + lappend ans [list set MODULESHOME $moduleshome] + lappend ans [list set MODULE_VERSION "(.*)"] + } else { + lappend ans [list set MODULESHOME $moduleshome] + } test_cmd_re $shell "autoinit" $ans } @@ -342,22 +348,40 @@ if {(!$insmodspath || $modspath_exinstalled) && (!$insmodrc || $modrc_exinstalle set ans [list] lappend ans [list [set "func_$shell"]] if {!$insmodspath && !$insmodrc} { + if {$install_versioning eq "y"} { + lappend ans [list set MODULE_VERSION_STACK "(.*)"] + } lappend ans [list set LOADEDMODULES ""] lappend ans [list set MODULESHOME $moduleshome] lappend ans [list set MODULEPATH ""] + if {$install_versioning eq "y"} { + lappend ans [list set MODULE_VERSION "(.*)"] + } } elseif {$modspath_exinstalled} { + if {$install_versioning eq "y"} { + lappend ans [list set MODULE_VERSION_STACK "(.*)"] + } lappend ans [list set MODULEPATH_modshare "(.*)"] lappend ans [list set LOADEDMODULES ""] lappend ans [list set MODULESHOME $moduleshome] lappend ans [list set MODULEPATH "$install_modulefilesdir:$install_prefix/test/modulefiles:$install_prefix/test/etc"] + if {$install_versioning eq "y"} { + lappend ans [list set MODULE_VERSION "(.*)"] + } } elseif {!$insmodspath && $modrc_exinstalled} { lappend ans [list set _LMFILES__modshare "$install_modulefilesdir/null:1"] lappend ans [list set LOADEDMODULES_modshare "null:1"] + if {$install_versioning eq "y"} { + lappend ans [list set MODULE_VERSION_STACK "(.*)"] + } lappend ans [list set MODULEPATH_modshare "$install_modulefilesdir:1"] lappend ans [list set _LMFILES_ "$install_modulefilesdir/null"] lappend ans [list set LOADEDMODULES "null"] lappend ans [list set MODULESHOME $moduleshome] lappend ans [list set MODULEPATH "$install_modulefilesdir"] + if {$install_versioning eq "y"} { + lappend ans [list set MODULE_VERSION "(.*)"] + } } test_cmd_re $shell "autoinit" $ans