diff --git a/SOURCES/createmodule.py b/SOURCES/createmodule.py
index 60c6ba7..3c778c1 100755
--- a/SOURCES/createmodule.py
+++ b/SOURCES/createmodule.py
@@ -17,16 +17,18 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+from __future__ import print_function
from optparse import OptionParser
-import os,sys
+import os,sys,re
from subprocess import *
# Handle options
usage = "Usage: %prog [-p prefix] [args]"
parser = OptionParser()
parser.set_usage(usage)
-parser.add_option('-p', '--prefix', dest='prefix', help='Specify path prefix')
+parser.add_option('-p', '--prefix', action='store', type='string', dest='prefix', help='Specify path prefix')
+parser.add_option('--noprefix', action='store_true', dest='noprefix', default=False, help='Do not generate a prefix')
(options, args) = parser.parse_args()
# Need a script name
@@ -40,22 +42,31 @@ def getenv(cmd = ':'):
p = Popen(cmd + ";env", shell=True, stdout=PIPE, stderr=PIPE)
(stdout, stderr) = p.communicate()
if p.returncode != 0:
- print "EROR: Could not execute initscript:"
- print "%s returned exit code %d" % (cmd, p.returncode)
- print stderr
+ print("EROR: Could not execute initscript:")
+ print("%s returned exit code %d" % (cmd, p.returncode))
+ print(stderr)
exit(1)
if stderr != '':
- print "WARNING: initscript sent the following to stderr:"
- print stderr
+ print("WARNING: initscript sent the following to stderr:")
+ print(stderr)
# Parse the output key=value pairs
+ skip = False
for line in stdout.splitlines():
+ if skip:
+ if line == '}':
+ skip = False
+ continue
try:
(var,value) = line.split('=',1)
except ValueError:
- print "ERROR: Could not parse output:"
- print stdout
+ print("ERROR: Could not parse output line:")
+ print(line)
exit(1)
- env[var] = value
+ # Exported functions - not handled
+ if value.find('() {') == 0:
+ skip = True
+ else:
+ env[var] = value
return env
#Record initial environment
@@ -68,6 +79,7 @@ env2=getenv(". " + " ".join(args))
chdir = None
appendpath = {}
prependpath = {}
+unhandled = {}
setenv = {}
unsetenv = []
pathnames = []
@@ -77,7 +89,7 @@ def normpaths(paths):
newpaths = []
for path in paths:
normpath = os.path.normpath(path)
- if normpath not in newpaths:
+ if normpath not in newpaths and normpath != '.':
newpaths.append(os.path.normpath(path))
return newpaths
@@ -98,89 +110,128 @@ for key in env1.keys():
del env2[key]
continue
# Determine modifcations to beginning and end of the string
- (prepend,append) = env2[key].split(env1[key])
+ try:
+ (prepend,append) = env2[key].split(env1[key])
+ except ValueError:
+ continue
if prepend:
- prependpaths = prepend.strip(':').split(':')
+ presep = prepend[-1:]
+ prependpaths = prepend.strip(presep).split(presep)
# LICENSE variables often include paths outside install directory
if 'LICENSE' not in key:
pathnames += prependpaths
- prependpath[key] = ':'.join(normpaths(prependpaths))
+ if presep not in prependpath:
+ prependpath[presep] = {}
+ newpath = presep.join(normpaths(prependpaths))
+ if newpath:
+ prependpath[presep][key] = newpath
+ else:
+ unhandled[key] = env2[key]
if append:
- appendpaths = append.strip(':').split(':')
+ appsep = append[0:1]
+ appendpaths = append.strip(appsep).split(appsep)
# LICENSE variables often include paths outside install directory
if 'LICENSE' not in key:
pathnames += appendpaths
- appendpath[key] = ':'.join(normpaths(appendpaths))
+ if appsep not in appendpath:
+ appendpath[appsep] = {}
+ newpath = appsep.join(normpaths(appendpaths))
+ if newpath:
+ appendpath[appsep][key] = newpath
+ else:
+ unhandled[key] = env2[key]
del env2[key]
# We're left with new keys in env2
for key in env2.keys():
# Use prepend-path for new paths
- if ('PATH' in key) or (':' in env2[key]):
+ if (re.search('(DIRS|FILES|PATH)$',key)) or (':' in env2[key]):
prependpaths = env2[key].strip(':').split(':')
# MANPATH can have system defaults added it it wasn't previously set
# LICENSE variables often include paths outside install directory
if key != 'MANPATH' and 'LICENSE' not in key:
pathnames += prependpaths
- prependpath[key] = ':'.join(normpaths(prependpaths))
+ if ':' not in prependpath:
+ prependpath[':'] = {}
+ prependpath[':'][key] = ':'.join(normpaths(prependpaths))
continue
# Set new variables
setenv[key] = os.path.normpath(env2[key])
if 'LICENSE' not in key:
pathnames.append(setenv[key])
+# Report unhandled keys
+for key in unhandled.keys():
+ print("Unhandled change of", key, file=sys.stderr)
+ print("Before <%s>" % env1[key], file=sys.stderr)
+ print("After <%s>" % unhandled[key], file=sys.stderr)
+ for sepkey in appendpath.keys():
+ appendpath[sepkey].pop(key, None)
+ for sepkey in prependpath.keys():
+ prependpath[sepkey].pop(key, None)
+
# Determine a prefix
-prefix = None
+prefix=None
if options.prefix:
prefix = options.prefix
-else:
+elif not options.noprefix:
prefix = os.path.commonprefix(pathnames).rstrip('/')
if prefix == '':
prefix = None
# Print out the modulefile
-print "#%Module 1.0"
+print("#%Module 1.0")
# Prefix
if prefix is not None:
- print "\nset prefix " + prefix + "\n"
+ print("\nset prefix " + prefix + "\n")
# Chdir
if chdir is not None:
- print "chdir\t" + chdir
+ print("chdir\t" + chdir)
# Function to format output line with tabs and substituting prefix
def formatline(item, key, value=None):
- print item,
- print "\t"*(2-(len(item)+1)/8),
- print key,
+ print(item, end=' ')
+ print("\t"*(2-(len(item)+1)/8), end=' ')
+ print(key, end=' ')
if value is not None:
- print "\t"*(3-(len(key)+1)/8),
+ print("\t"*(3-(len(key)+1)/8), end=' ')
if prefix is not None:
- print value.replace(prefix,'$prefix')
+ print(value.replace(prefix,'$prefix'))
else:
- print value
+ print(value)
# Paths first, grouped by variable name
-pathkeys = appendpath.keys() + prependpath.keys()
-pathkeys.sort()
-for key in pathkeys:
- if key in prependpath:
- formatline("prepend-path",key,prependpath[key])
- if key in appendpath:
- formatline("append-path",key,appendpath[key])
+for sepkey in prependpath.keys():
+ pathkeys = prependpath[sepkey].keys()
+ pathkeys.sort()
+ for key in pathkeys:
+ if sepkey == ":":
+ formatline("prepend-path",key,prependpath[sepkey][key])
+ else:
+ formatline("prepend-path --delim %s" % sepkey,key,prependpath[sepkey][key])
+
+for sepkey in appendpath.keys():
+ pathkeys = appendpath[sepkey].keys()
+ pathkeys.sort()
+ for key in pathkeys:
+ if sepkey == ":":
+ formatline("append-path",key,appendpath[sepkey][key])
+ else:
+ formatline("append-path --delim %s" % sepkey,key,appendpath[sepkey][key])
# Setenv
-setenvkeys = setenv.keys()
+setenvkeys = list(setenv.keys())
setenvkeys.sort()
if setenvkeys:
- print
+ print()
for key in setenvkeys:
formatline("setenv",key,setenv[key])
# Unsetenv
unsetenv.sort()
if unsetenv:
- print
+ print()
for key in unsetenv:
formatline("unsetenv",key)
diff --git a/SOURCES/createmodule.sh b/SOURCES/createmodule.sh
index b44cf05..b0edfc5 100755
--- a/SOURCES/createmodule.sh
+++ b/SOURCES/createmodule.sh
@@ -48,8 +48,11 @@ printenvarray () {
env | while read x
do
key=${x%%=*}
- value=${x#*=}
- echo [$key]="'$value'"
+ value=`printenv "$key"`
+ if [ $? -eq 0 ]
+ then
+ echo [$key]="'$value'"
+ fi
done
}
@@ -71,11 +74,13 @@ echo "#%Module 1.0"
#Prefix
[ -n "$prefix" ] && echo -e "\nset prefix $prefix\n"
+# dedup - remove duplicate entries from a list
#Subshell so we can sort the output
(
dedup() {
list=`mktemp`
- echo $1 | sed -r -e 's,[^/]+/\.\./,,g' -e 's,[^/]+/\.\./,,g' -e 's/:/\n/g' |
+ [ -n "$2" ] && sep=$2 || sep=:
+ echo $1 | sed -r -e 's,[^/]+/\.\./,,g' -e 's,[^/]+/\.\./,,g' -e "s/\\$sep/\n/g" |
while read x
do
grep -Fx ${x} $list && continue
@@ -86,7 +91,7 @@ dedup() {
echo $x
fi
echo $x >> $list
- done | tr '\n' : | sed -e 's/:$//'
+ done | tr '\n' $sep | sed -e "s/\\$sep\$//"
rm $list
}
@@ -111,25 +116,61 @@ do
#Test for prepend
elif [ "${env2[$key]%${env1[$key]}}" != "${env2[$key]}" ]
then
- added=$(dedup ${env2[$key]%:${env1[$key]}})
- echo -e "prepend-path\t$key\t${added}"
+ added=${env2[$key]%${env1[$key]}}
+ sep=${added: -1}
+ added=${added%$sep}
+ added=$(dedup $added $sep)
+ if [ $sep = : ]
+ then
+ echo -e "prepend-path\t$key\t${added}"
+ else
+ echo -e "prepend-path\t--delim $sep\t$key\t${added}"
+ fi
#Test for prepend plus : added at end (MANPATH)
- elif [ "${env2[$key]%${env1[$key]}:}" != "${env2[$key]}" ]
+ elif [ "${key: -4}" = PATH -a "${env2[$key]%${env1[$key]}:}" != "${env2[$key]}" ]
then
added=$(dedup ${env2[$key]%${env1[$key]}:})
echo -e "prepend-path\t$key\t${added}"
#Test for append
elif [ "${env2[$key]#${env1[$key]}}" != "${env2[$key]}" ]
then
- added=$(dedup ${env2[$key]#:${env1[$key]}})
- echo -e "append-path\t$key\t${added}"
+ added=${env2[$key]#${env1[$key]}}
+ sep=${added:0:1}
+ added=${added#$sep}
+ added=$(dedup $added $sep)
+ if [ $sep = : ]
+ then
+ echo -e "append-path\t$key\t${added}"
+ else
+ echo -e "append-path\t--delim $sep\t$key\t${added}"
+ fi
#Test for prepend plus append
- elif [ "${env2[$key]%${env1[$key]}:*}" != "${env2[$key]}" ]
+ elif [ "${env2[$key]%${env1[$key]}*}" != "${env2[$key]}" ]
then
- added=$(dedup ${env2[$key]%:${env1[$key]}*})
- echo -e "prepend-path\t$key\t${added}"
- added=$(dedup ${env2[$key]#*${env1[$key]}:})
- echo -e "append-path\t$key\t${added}"
+ prepended=${env2[$key]%${env1[$key]}*}
+ presep=${prepended: -1}
+ prepended=${prepended%$presep}
+ prepended=$(dedup $prepended $presep)
+ appended=${env2[$key]#*${env1[$key]}}
+ appsep=${appended:0:1}
+ appended=${appended#$appsep}
+ appended=$(dedup $appended $appsep)
+ if [ $presep != $appsep -o -z "$prepended" -o -z "$appended" ]
+ then
+ #Unhandled
+ echo "Unhandled change of $key" 1>&2
+ echo "Before <${env1[$key]}>" 1>&2
+ echo "After <${env2[$key]}>" 1>&2
+ else
+ if [ $presep = : ]
+ then
+ echo -e "prepend-path\t$key\t${prepended}"
+ echo -e "append-path\t$key\t${appended}"
+ else
+ echo -e "prepend-path\t--delim $presep\t$key\t${prepended}"
+ echo -e "append-path\t--delim $appsep\t$key\t${appended}"
+ fi
+ fi
else
#Unhandled
echo "Unhandled change of $key" 1>&2
@@ -137,7 +178,7 @@ do
echo "After <${env2[$key]}>" 1>&2
fi
fi
- #Delete keys we've handled
+ #Delete keys we have handled
unset env1[$key]
unset env2[$key]
done
@@ -150,7 +191,7 @@ do
continue
fi
#Use prepend-path for new paths
- if [ "${key/PATH/}" != "$key" ]
+ if [ "${key: -4}" = PATH -o "${key: -4}" = DIRS -o "${key: -4}" = FILES ]
then
# TODO - Need to handle stripping of default MANPATH
echo -e "prepend-path\t${key}\t"$(dedup ${env2[$key]})
diff --git a/SOURCES/environment-modules-3.2.10-ignore-nested-dirs.patch b/SOURCES/environment-modules-3.2.10-ignore-nested-dirs.patch
new file mode 100644
index 0000000..b53e71b
--- /dev/null
+++ b/SOURCES/environment-modules-3.2.10-ignore-nested-dirs.patch
@@ -0,0 +1,15 @@
+diff -up modules-3.2.9/locate_module.c.SourceVers modules-3.2.9/locate_module.c
+--- modules-3.2.9/locate_module.c.SourceVers 2013-06-30 17:23:01.451210176 +0200
++++ modules-3.2.9/locate_module.c 2013-06-30 17:24:16.963201645 +0200
+@@ -1194,6 +1194,11 @@ int SourceVers( Tcl_Interp *interp, char
+ ** The version has been specified in the
+ ** '.version' file. Set up the result code
+ **/
++ /* version can be only located in the current directory */
++ if (strrchr(version, '/')) {
++ ErrorLogger( ERR_BADMODNAM, LOC, version, NULL);
++ return( TCL_ERROR);
++ }
+ /* for deep modulefile dirs ... just use lowest part */
+ if (!(modname = (char*) strrchr( name, '/'))) {
+ modname = name;
diff --git a/SOURCES/environment-modules-3.2.10-unload-from-module.patch b/SOURCES/environment-modules-3.2.10-unload-from-module.patch
new file mode 100644
index 0000000..c848752
--- /dev/null
+++ b/SOURCES/environment-modules-3.2.10-unload-from-module.patch
@@ -0,0 +1,24 @@
+diff -up modules-3.2.10/ModuleCmd_Load.c.unload_from_modulefile modules-3.2.10/ModuleCmd_Load.c
+--- modules-3.2.10/ModuleCmd_Load.c.unload_from_modulefile 2014-07-08 10:43:41.615212949 +0200
++++ modules-3.2.10/ModuleCmd_Load.c 2014-07-08 13:49:21.674701003 +0200
+@@ -126,7 +126,7 @@ int ModuleCmd_Load( Tcl_Interp *interp,
+ ** Set up the flags controling the Tcl callback functions
+ **/
+
+- /* avoid changes when invoked as a subcommand */
++ /* avoid changes when invoked as a subcommand and loading */
+ if (!(g_flags & M_SUBCMD)) {
+ if( load) {
+ g_flags |= M_LOAD;
+@@ -136,6 +136,11 @@ int ModuleCmd_Load( Tcl_Interp *interp,
+ g_flags &= ~M_LOAD;
+ }
+ g_flags |= M_SUBCMD;
++ } else {
++ if (!load) {
++ g_flags |= M_REMOVE;
++ g_flags &= ~M_LOAD;
++ }
+ }
+
+ /**
diff --git a/SPECS/environment-modules.spec b/SPECS/environment-modules.spec
index 6ef809d..ef1f405 100644
--- a/SPECS/environment-modules.spec
+++ b/SPECS/environment-modules.spec
@@ -1,6 +1,6 @@
Name: environment-modules
Version: 3.2.10
-Release: 8%{?dist}
+Release: 10%{?dist}
Summary: Provides dynamic modification of a user's environment
Group: System Environment/Base
@@ -20,6 +20,8 @@ Patch2: environment-modules-clear.patch
# Patch from modules list to add completion to avail command
Patch3: environment-modules-avail.patch
Patch4: environment-modules-3.2.9-call-test-by-full-path-in-csh.patch
+Patch5: environment-modules-3.2.10-ignore-nested-dirs.patch
+Patch6: environment-modules-3.2.10-unload-from-module.patch
BuildRequires: tcl-devel, tclx-devel, libX11-devel
BuildRequires: dejagnu
@@ -59,6 +61,8 @@ have access to the module alias.
%patch2 -p1 -b .clear
%patch3 -p1 -b .avail
%patch4 -p1 -b .call-test-by-full-path-in-csh
+%patch5 -p1 -b .ignore-nested-dirs
+%patch6 -p1 -b .unload-from-module
%build
@@ -100,6 +104,13 @@ make test
%changelog
+* Mon Jun 22 2015 Jan Synáček - 3.2.10-10
+- fix: createmodule scripts incorrectly handles env vars prefixed/suffixed without colon (#1233223)
+
+* Wed Apr 29 2015 Jan Synáček - 3.2.10-9
+- fix: SourceVers wrongly sets version in nested directory (#1180652)
+- fix: unload from loaded modulefile broken (#1117327)
+
* Fri Jan 24 2014 Daniel Mach - 3.2.10-8
- Mass rebuild 2014-01-24
@@ -238,7 +249,7 @@ make test
* Wed Dec 20 2006 - Orion Poplawski - 3.2.3-3
- Add --with-version-path to set VERSIONPATH (bug 220260)
-* Tue Aug 28 2006 - Orion Poplawski - 3.2.3-2
+* Tue Aug 29 2006 - Orion Poplawski - 3.2.3-2
- Rebuild for FC6
* Fri Jun 2 2006 - Orion Poplawski - 3.2.3-1