summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xel6/createmodule.py237
-rwxr-xr-xel6/createmodule.sh207
-rw-r--r--el6/environment-modules-3.2.10-ignore-nested-dirs.patch15
-rw-r--r--el6/environment-modules-3.2.10-unload-from-module.patch24
-rw-r--r--el6/environment-modules-3.2.7-bindir.patch11
-rw-r--r--el6/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch11
-rw-r--r--el6/environment-modules-3.2.9-clear.patch11
-rw-r--r--el6/environment-modules-3.2.9-gcc-no-strict.patch11
-rw-r--r--el6/environment-modules-3.2.9-module-path.patch9
-rw-r--r--el6/environment-modules.spec231
-rw-r--r--el6/modules.sh7
-rwxr-xr-xel7/createmodule.py237
-rwxr-xr-xel7/createmodule.sh207
-rw-r--r--el7/environment-modules-3.2.10-ignore-nested-dirs.patch15
-rw-r--r--el7/environment-modules-3.2.10-unload-from-module.patch24
-rw-r--r--el7/environment-modules-3.2.7-bindir.patch11
-rw-r--r--el7/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch11
-rw-r--r--el7/environment-modules-avail.patch12
-rw-r--r--el7/environment-modules-clear.patch11
-rw-r--r--el7/environment-modules-versioning.patch10
-rw-r--r--el7/environment-modules.spec271
-rw-r--r--el7/modules.sh7
22 files changed, 1590 insertions, 0 deletions
diff --git a/el6/createmodule.py b/el6/createmodule.py
new file mode 100755
index 0000000..62c4d18
--- /dev/null
+++ b/el6/createmodule.py
@@ -0,0 +1,237 @@
+#!/usr/bin/python
+#
+# createmodule.py - Takes the name of a environment init script and
+# produces a modulefile that duplicates the changes made by the init script
+#
+# Copyright (C) 2012 by Orion E. Poplawski <orion@cora.nwra.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from __future__ import print_function
+
+from optparse import OptionParser
+import os,sys,re
+from subprocess import *
+
+# Handle options
+usage = "Usage: %prog [-p prefix] <initscript> [args]"
+parser = OptionParser()
+parser.set_usage(usage)
+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
+if not args:
+ parser.print_usage()
+ exit(1)
+
+# Return environment after a command
+def getenv(cmd = ':'):
+ env = {}
+ 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)
+ exit(1)
+ if 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 line:")
+ print(line)
+ exit(1)
+ # Exported functions - not handled
+ if value.find('() {') == 0:
+ skip = True
+ else:
+ env[var] = value
+ return env
+
+#Record initial environment
+env1=getenv()
+
+#Record environment after sourcing the initscript
+env2=getenv(". " + " ".join(args))
+
+# Initialize our variables for storing modifications
+chdir = None
+appendpath = {}
+prependpath = {}
+unhandled = {}
+setenv = {}
+unsetenv = []
+pathnames = []
+
+# Function to nomalize all paths in a list of paths and remove duplicate items
+def normpaths(paths):
+ newpaths = []
+ for path in paths:
+ normpath = os.path.normpath(path)
+ if normpath not in newpaths and normpath != '.':
+ newpaths.append(os.path.normpath(path))
+ return newpaths
+
+# Start with existing keys and look for changes
+for key in env1.keys():
+ # Test for delete
+ if key not in env2:
+ unsetenv.append(key)
+ continue
+ # No change
+ if env1[key] == env2[key]:
+ del env2[key]
+ continue
+ #Working directory change
+ if key == 'PWD':
+ chdir=os.path.normpath(env2[key])
+ pathnames.append(chdir)
+ del env2[key]
+ continue
+ # Determine modifcations to beginning and end of the string
+ try:
+ (prepend,append) = env2[key].split(env1[key])
+ except ValueError:
+ continue
+ if prepend:
+ presep = prepend[-1:]
+ prependpaths = prepend.strip(presep).split(presep)
+ # LICENSE variables often include paths outside install directory
+ if 'LICENSE' not in key:
+ pathnames += 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:
+ 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
+ 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 (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
+ 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
+if options.prefix:
+ prefix = options.prefix
+elif not options.noprefix:
+ prefix = os.path.commonprefix(pathnames).rstrip('/')
+ if prefix == '':
+ prefix = None
+
+# Print out the modulefile
+print("#%Module 1.0")
+
+# Prefix
+if prefix is not None:
+ print("\nset prefix " + prefix + "\n")
+
+# Chdir
+if chdir is not None:
+ print("chdir\t" + chdir)
+
+# Function to format output line with tabs and substituting prefix
+def formatline(item, key, value=None):
+ 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), end=' ')
+ if prefix is not None:
+ print(value.replace(prefix,'$prefix'))
+ else:
+ print(value)
+
+# Paths first, grouped by variable name
+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 = list(setenv.keys())
+setenvkeys.sort()
+if setenvkeys:
+ print()
+for key in setenvkeys:
+ formatline("setenv",key,setenv[key])
+
+# Unsetenv
+unsetenv.sort()
+if unsetenv:
+ print()
+for key in unsetenv:
+ formatline("unsetenv",key)
diff --git a/el6/createmodule.sh b/el6/createmodule.sh
new file mode 100755
index 0000000..f722797
--- /dev/null
+++ b/el6/createmodule.sh
@@ -0,0 +1,207 @@
+#!/bin/bash
+#
+# createmodule.sh - Takes the name of a environment init script and
+# produces a modulefile that duplicates the changes made by the init script
+#
+# Copyright (C) 2010-2012 by Orion E. Poplawski <orion@cora.nwra.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+usage="Usage: $0 [-p prefix] <initscript> [args]"
+
+usage() {
+ echo $usage 1>&2
+ exit 1
+}
+
+while getopts "p:" opt
+do
+ case $opt in
+ p) prefix=$OPTARG; shift 2;;
+ *) usage;;
+ esac
+done
+
+# Need a script name
+[ -z "$1" ] && usage
+
+# Need to be a readable script
+if [ ! -r "$1" ]
+then
+ echo "ERROR: Cannot read $1" 1>&2
+ exit 1
+fi
+
+#Will print out array assignment list
+printenvarray () {
+ env | while read x
+ do
+ key=${x%%=*}
+ value=`printenv "$key"`
+ if [ $? -eq 0 ]
+ then
+ echo [$key]="'$value'"
+ fi
+ done
+}
+
+#Apparently we need to declare the associative arrays
+declare -A env1 env2
+
+#Record starting environment
+eval env1=(`printenvarray`)
+
+#Source the environment script
+. "$@"
+
+#Record ending environment
+eval env2=(`printenvarray`)
+
+#Print out the modulefile
+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`
+ [ -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
+ if [ -n "$prefix" ]
+ then
+ echo $x | sed -e s,$prefix,\$prefix,
+ else
+ echo $x
+ fi
+ echo $x >> $list
+ done | tr '\n' $sep | sed -e "s/\\$sep\$//"
+ rm $list
+}
+
+#Keys that changed
+for key in "${!env1[@]}"
+do
+ if [ "${env1[$key]}" != "${env2[$key]}" ]
+ then
+ #Working directory change
+ if [ "$key" = PWD ]
+ then
+ if [ -n "$prefix" ]
+ then
+ echo -e "chdir\t\t${env2[PWD]}" | sed -e s,$prefix,\$prefix,g
+ else
+ echo -e "chdir\t\t${env2[PWD]}"
+ fi
+ #Test for delete
+ elif [ -z "${env2[$key]}" ]
+ then
+ echo -e "unsetenv\t${key}\t${env2[$key]}"
+ #Test for prepend
+ elif [ "${env2[$key]%${env1[$key]}}" != "${env2[$key]}" ]
+ then
+ 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 [ "${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=${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]}" ]
+ then
+ 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
+ echo "Before <${env1[$key]}>" 1>&2
+ echo "After <${env2[$key]}>" 1>&2
+ fi
+ fi
+ #Delete keys we have handled
+ unset env1[$key]
+ unset env2[$key]
+done
+
+#New keys
+for key in "${!env2[@]}"
+do
+ if [ "$key" = OLDPWD ]
+ then
+ continue
+ fi
+ #Use prepend-path for new paths
+ 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]})
+ else
+ if [ -n "$prefix" ]
+ then
+ echo -e "setenv\t\t${key}\t${env2[$key]}" | sed -e s,$prefix,\$prefix,g
+ else
+ echo -e "setenv\t\t${key}\t${env2[$key]}"
+ fi
+ fi
+done
+) | sort
diff --git a/el6/environment-modules-3.2.10-ignore-nested-dirs.patch b/el6/environment-modules-3.2.10-ignore-nested-dirs.patch
new file mode 100644
index 0000000..b53e71b
--- /dev/null
+++ b/el6/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/el6/environment-modules-3.2.10-unload-from-module.patch b/el6/environment-modules-3.2.10-unload-from-module.patch
new file mode 100644
index 0000000..c848752
--- /dev/null
+++ b/el6/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/el6/environment-modules-3.2.7-bindir.patch b/el6/environment-modules-3.2.7-bindir.patch
new file mode 100644
index 0000000..1efb0ee
--- /dev/null
+++ b/el6/environment-modules-3.2.7-bindir.patch
@@ -0,0 +1,11 @@
+--- modules-3.2.7/init/Makefile.in.bindir 2009-09-22 12:13:52.000000000 -0600
++++ modules-3.2.7/init/Makefile.in 2009-09-23 12:19:50.797470155 -0600
+@@ -404,7 +404,7 @@
+ sed -e "/@$(if $(subst 0,,$(WANTS_VERSIONING)),NOT,)VERSIONING\@/d; \
+ s,@$(if $(subst 0,,$(WANTS_VERSIONING)),,NOT)VERSIONING\@,,g; \
+ s,@prefix\@,${prefix},g; \
+- s,@bindir\@,${exec_prefix}/bin,g; \
++ s,@bindir\@,${bindir},g; \
+ s,@VERSION\@,@VERSION@,g; \
+ s,@BASEPREFIX\@,@BASEPREFIX@,g;" < $< > $@
+
diff --git a/el6/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch b/el6/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch
new file mode 100644
index 0000000..2e8b04e
--- /dev/null
+++ b/el6/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch
@@ -0,0 +1,11 @@
+--- modules-3.2.9/init/csh.in 2010-11-11 19:23:18.000000000 +0100
++++ modules-3.2.9-new/init/csh.in 2013-05-14 08:43:11.686954109 +0200
+@@ -34,7 +34,7 @@
+ set prefix = "$prefix""set noglob;"
+ set postfix = "$postfix""unset noglob;"
+ endif
+-set postfix = "set _exit="'$status'"; $postfix; test 0 = "'$_exit;'
++set postfix = "set _exit="'$status'"; $postfix; @bindir@/test 0 = "'$_exit;'
+
+ @VERSIONING@alias module $prefix'eval `'$exec_prefix'/bin/modulecmd '$modules_shell' '$histchar'*`; '$postfix
+ @NOTVERSIONING@alias module $prefix'eval `'$exec_prefix'/modulecmd '$modules_shell' '$histchar'*`; '$postfix
diff --git a/el6/environment-modules-3.2.9-clear.patch b/el6/environment-modules-3.2.9-clear.patch
new file mode 100644
index 0000000..0817db5
--- /dev/null
+++ b/el6/environment-modules-3.2.9-clear.patch
@@ -0,0 +1,11 @@
+--- modules-3.2.9/utility.c 2011-11-28 22:27:13.000000000 +0100
++++ modules-3.2.9-new/utility.c 2012-06-13 15:17:41.570629148 +0200
+@@ -727,7 +727,7 @@ int Output_Modulefile_Changes( Tcl_Inter
+ output_unset_variable( (char*) key);
+ } else {
+ val = EMGetEnv(interp, key);
+- if(val && *val)
++ if(val)
+ output_set_variable(interp, (char*) key, val);
+ null_free((void *)&val);
+ }
diff --git a/el6/environment-modules-3.2.9-gcc-no-strict.patch b/el6/environment-modules-3.2.9-gcc-no-strict.patch
new file mode 100644
index 0000000..3317c5f
--- /dev/null
+++ b/el6/environment-modules-3.2.9-gcc-no-strict.patch
@@ -0,0 +1,11 @@
+--- modules-3.2.9/Makefile.in.orig 2012-09-12 09:02:22.000000000 +0200
++++ modules-3.2.9/Makefile.in 2012-09-12 09:12:40.588789305 +0200
+@@ -203,7 +203,7 @@
+ BASEPREFIX = @BASEPREFIX@
+ CC = @CC@
+ CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
++CFLAGS = @CFLAGS@ -fno-strict-aliasing
+ CPP = @CPP@
+ CPPFLAGS = @CPPFLAGS@
+ CYGPATH_W = @CYGPATH_W@
diff --git a/el6/environment-modules-3.2.9-module-path.patch b/el6/environment-modules-3.2.9-module-path.patch
new file mode 100644
index 0000000..2ab7ad7
--- /dev/null
+++ b/el6/environment-modules-3.2.9-module-path.patch
@@ -0,0 +1,9 @@
+--- modules-3.2.9/modulefiles/modules.in.orig 2010-11-11 19:23:19.000000000 +0100
++++ modules-3.2.9/modulefiles/modules.in 2012-08-17 09:35:50.204227697 +0200
+@@ -26,5 +26,5 @@
+ prepend-path PATH @bindir@
+ prepend-path MANPATH @mandir@
+
+-module use @VERSIONPATH@
++module use @exec_prefix@
+
diff --git a/el6/environment-modules.spec b/el6/environment-modules.spec
new file mode 100644
index 0000000..fbb6e5c
--- /dev/null
+++ b/el6/environment-modules.spec
@@ -0,0 +1,231 @@
+%global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompile[[:space:]].*$!!g')
+Name: environment-modules
+Version: 3.2.10
+Release: 3%{?dist}
+Summary: Provides dynamic modification of a user's environment
+
+Group: System Environment/Base
+License: GPLv2+
+URL: http://modules.sourceforge.net/
+Source0: http://downloads.sourceforge.net/modules/modules-%{version}.tar.bz2
+Source1: modules.sh
+Source2: createmodule.sh
+Source3: createmodule.py
+Patch0: environment-modules-3.2.7-bindir.patch
+Patch1: environment-modules-3.2.9-clear.patch
+Patch3: environment-modules-3.2.9-module-path.patch
+Patch4: environment-modules-3.2.9-gcc-no-strict.patch
+Patch5: environment-modules-3.2.9-call-test-by-full-path-in-csh.patch
+Patch6: environment-modules-3.2.10-ignore-nested-dirs.patch
+Patch7: environment-modules-3.2.10-unload-from-module.patch
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+BuildRequires: tcl-devel, tclx-devel, libX11-devel
+#For ps in startup script
+Requires: procps
+
+%description
+The Environment Modules package provides for the dynamic modification of
+a user's environment via modulefiles.
+
+Each modulefile contains the information needed to configure the shell
+for an application. Once the Modules package is initialized, the
+environment can be modified on a per-module basis using the module
+command which interprets modulefiles. Typically modulefiles instruct
+the module command to alter or set shell environment variables such as
+PATH, MANPATH, etc. modulefiles may be shared by many users on a system
+and users may have their own collection to supplement or replace the
+shared modulefiles.
+
+Modules can be loaded and unloaded dynamically and atomically, in an
+clean fashion. All popular shells are supported, including bash, ksh,
+zsh, sh, csh, tcsh, as well as some scripting languages such as perl.
+
+Modules are useful in managing different versions of applications.
+Modules can also be bundled into metamodules that will load an entire
+suite of different applications.
+
+NOTE: You will need to get a new shell after installing this package to
+have access to the module alias.
+
+
+%prep
+%setup -q -n modules-%{version}
+%patch0 -p1 -b .bindir
+%patch1 -p1 -b .clear
+%patch3 -p1 -b .module-path
+%patch4 -p1 -b .gcc-no-strict
+%patch5 -p1 -b .call-test-by-full-path-in-csh
+%patch6 -p1 -b .ignore-nested-dirs
+%patch7 -p1 -b .unload-from-module
+
+
+%build
+%configure --disable-versioning \
+ --prefix=%{_datadir} \
+ --exec-prefix=%{_datadir}/Modules \
+ --with-module-path=%{_sysconfdir}/modulefiles
+
+# --with-debug=42 --with-log-facility-debug=stderr
+make %{?_smp_mflags}
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
+cp -p %SOURCE1 $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/modules.sh
+cp -p %SOURCE2 %SOURCE3 $RPM_BUILD_ROOT%{_datadir}/Modules/bin
+ln -s %{_datadir}/Modules/init/csh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/modules.csh
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/modulefiles
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+
+%files
+%defattr(-,root,root,-)
+%doc LICENSE.GPL README TODO
+%{_sysconfdir}/modulefiles
+%config(noreplace) %{_sysconfdir}/profile.d/*
+# as %{_sysconfdir}/profile.d/modules.csh is a symlink to this file, it has to
+# be marked as config(noreplace) as well if we want to preserve the changes
+%config(noreplace) %{_datadir}/Modules/init/csh
+%{_bindir}/modulecmd
+%dir %{_datadir}/Modules
+%{_datadir}/Modules/bin/
+%dir %{_datadir}/Modules/init
+%{_datadir}/Modules/init/*
+%config(noreplace) %{_datadir}/Modules/init/.modulespath
+%{_datadir}/Modules/modulefiles
+%{_mandir}/man1/module.1.gz
+%{_mandir}/man4/modulefile.4.gz
+
+
+%changelog
+* Mon Nov 2 2015 Jan Synáček <jsynacek@redhat.com> - 3.2.10-3
+- fix: createmodule scripts incorrectly handles env vars prefixed/suffixed without colon (#1180139)
+
+* Thu Nov 27 2014 Jan Synáček <jsynacek@redhat.com> - 3.2.10-2
+- fix: SourceVers wrongly sets version in nested directory (#979789)
+- fix: unload from loaded modulefile broken (#1117307)
+
+* Thu Mar 13 2014 Jan Synáček <jsynacek@redhat.com> - 3.2.10-1
+- Rebase to 3.2.10
+- Drop regexp patch
+- Resolves: #976369
+
+* Tue May 14 2013 Jan Synáček <jsynacek@redhat.com> - 3.2.9c-6
+- Call test command in csh alias by its full path (bug #929007)
+- Correctly preserve the target file that the config symlink points to
+ (this change makes the previous fix for bug #953198 whole)
+
+* Mon May 13 2013 Jan Synáček <jsynacek@redhat.com> - 3.2.9c-5
+- Make .modulespath a config file (bug #918540)
+- Do not replace modified profile.d scripts (bug #953198)
+- Remove use of test command in csh alias (bug #929007)
+
+* Wed Sep 12 2012 Jan Synáček <jsynacek@redhat.com> - 3.2.9c-4
+- Revert timestamps fix attempt
+- Prevent rpm from bytecompiling the internal python file
+- Related: #848865
+
+* Wed Sep 12 2012 Jan Synáček <jsynacek@redhat.com> - 3.2.9c-3
+- Add -fno-strict-aliasing to silence gcc warnings
+- Fix timestamps to silence multilib test
+- Related: #848865
+
+* Tue Sep 11 2012 Jan Synáček <jsynacek@redhat.com> - 3.2.9c-2
+- Bump build version, rebuild with the new patch
+- Related: #848865
+
+* Wed Jun 27 2012 Jan Synáček <jsynacek@redhat.com> - 3.2.9c-1
+- Rebase to 3.2.9c (bug #765630, #818177)
+ + Fix 'module clear'
+- Fix memory problems with 'modules switch' (bug #818177)
+- Fix "module use" path in default modules file (bug #848865)
+
+* Mon Nov 30 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-6
+- Add Requires: propcs (bug #54272)
+
+* Mon Oct 26 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-5
+- Don't assume different shell init scripts exist (bug #530770)
+
+* Fri Oct 23 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-4
+- Don't load bash init script when bash is running as "sh" (bug #529745)
+
+* Mon Oct 19 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-3
+- Support different flavors of "sh" (bug #529493)
+
+* Wed Sep 23 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-2
+- Add patch to fix modulecmd path in init files
+
+* Wed Sep 23 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-1
+- Update to 3.2.7b
+
+* Mon Sep 21 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7-1
+- Update to 3.2.7, fixes bug #524475
+- Drop versioning patch fixed upstream
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.6-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Tue Feb 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.6-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Wed Sep 3 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-6
+- Change %%patch -> %%patch0
+
+* Fri Mar 14 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-5
+- Add BR libX11-devel so modulecmd can handle X resources
+
+* Wed Mar 5 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-4
+- Add patch to fix extraneous version path entry properly
+- Use --with-module-path to point to /etc/modulefiles for local modules,
+ this also fixes bug #436041
+
+* Sat Feb 9 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-3
+- Rebuild for gcc 3.4
+
+* Thu Jan 03 2008 - Alex Lancaster <alexlan at fedoraproject.org> - 3.2.6-2
+- Rebuild for new Tcl (8.5).
+
+* Fri Nov 2 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-1
+- Update to 3.2.6
+
+* Tue Aug 21 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.5-2
+- Update license tag to GPLv2
+
+* Fri Feb 16 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.5-1
+- Update to 3.2.5
+
+* Wed Feb 14 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.4-2
+- Rebuild for Tcl downgrade
+
+* Fri Feb 09 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.4-1
+- Update to 3.2.4
+
+* Wed Dec 20 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.3-3
+- Add --with-version-path to set VERSIONPATH (bug 220260)
+
+* Tue Aug 29 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.3-2
+- Rebuild for FC6
+
+* Fri Jun 2 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.3-1
+- Update to 3.2.3
+
+* Fri May 5 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.2-1
+- Update to 3.2.2
+
+* Fri Mar 24 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.1-1
+- Update to 3.2.1
+
+* Thu Feb 9 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.0p1-1
+- Update to 3.2.0p1
+
+* Fri Jan 27 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.0-2
+- Add profile.d links
+
+* Tue Jan 24 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.0-1
+- Fedora Extras packaging
diff --git a/el6/modules.sh b/el6/modules.sh
new file mode 100644
index 0000000..48cc324
--- /dev/null
+++ b/el6/modules.sh
@@ -0,0 +1,7 @@
+shell=`/bin/basename \`/bin/ps -p $$ -ocomm=\``
+if [ -f /usr/share/Modules/init/$shell ]
+then
+ . /usr/share/Modules/init/$shell
+else
+ . /usr/share/Modules/init/sh
+fi
diff --git a/el7/createmodule.py b/el7/createmodule.py
new file mode 100755
index 0000000..3c778c1
--- /dev/null
+++ b/el7/createmodule.py
@@ -0,0 +1,237 @@
+#!/usr/bin/python
+#
+# createmodule.py - Takes the name of a environment init script and
+# produces a modulefile that duplicates the changes made by the init script
+#
+# Copyright (C) 2012 by Orion E. Poplawski <orion@cora.nwra.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from __future__ import print_function
+
+from optparse import OptionParser
+import os,sys,re
+from subprocess import *
+
+# Handle options
+usage = "Usage: %prog [-p prefix] <initscript> [args]"
+parser = OptionParser()
+parser.set_usage(usage)
+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
+if not args:
+ parser.print_usage()
+ exit(1)
+
+# Return environment after a command
+def getenv(cmd = ':'):
+ env = {}
+ 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)
+ exit(1)
+ if 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 line:")
+ print(line)
+ exit(1)
+ # Exported functions - not handled
+ if value.find('() {') == 0:
+ skip = True
+ else:
+ env[var] = value
+ return env
+
+#Record initial environment
+env1=getenv()
+
+#Record environment after sourcing the initscript
+env2=getenv(". " + " ".join(args))
+
+# Initialize our variables for storing modifications
+chdir = None
+appendpath = {}
+prependpath = {}
+unhandled = {}
+setenv = {}
+unsetenv = []
+pathnames = []
+
+# Function to nomalize all paths in a list of paths and remove duplicate items
+def normpaths(paths):
+ newpaths = []
+ for path in paths:
+ normpath = os.path.normpath(path)
+ if normpath not in newpaths and normpath != '.':
+ newpaths.append(os.path.normpath(path))
+ return newpaths
+
+# Start with existing keys and look for changes
+for key in env1.keys():
+ # Test for delete
+ if key not in env2:
+ unsetenv.append(key)
+ continue
+ # No change
+ if env1[key] == env2[key]:
+ del env2[key]
+ continue
+ #Working directory change
+ if key == 'PWD':
+ chdir=os.path.normpath(env2[key])
+ pathnames.append(chdir)
+ del env2[key]
+ continue
+ # Determine modifcations to beginning and end of the string
+ try:
+ (prepend,append) = env2[key].split(env1[key])
+ except ValueError:
+ continue
+ if prepend:
+ presep = prepend[-1:]
+ prependpaths = prepend.strip(presep).split(presep)
+ # LICENSE variables often include paths outside install directory
+ if 'LICENSE' not in key:
+ pathnames += 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:
+ 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
+ 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 (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
+ 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
+if options.prefix:
+ prefix = options.prefix
+elif not options.noprefix:
+ prefix = os.path.commonprefix(pathnames).rstrip('/')
+ if prefix == '':
+ prefix = None
+
+# Print out the modulefile
+print("#%Module 1.0")
+
+# Prefix
+if prefix is not None:
+ print("\nset prefix " + prefix + "\n")
+
+# Chdir
+if chdir is not None:
+ print("chdir\t" + chdir)
+
+# Function to format output line with tabs and substituting prefix
+def formatline(item, key, value=None):
+ 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), end=' ')
+ if prefix is not None:
+ print(value.replace(prefix,'$prefix'))
+ else:
+ print(value)
+
+# Paths first, grouped by variable name
+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 = list(setenv.keys())
+setenvkeys.sort()
+if setenvkeys:
+ print()
+for key in setenvkeys:
+ formatline("setenv",key,setenv[key])
+
+# Unsetenv
+unsetenv.sort()
+if unsetenv:
+ print()
+for key in unsetenv:
+ formatline("unsetenv",key)
diff --git a/el7/createmodule.sh b/el7/createmodule.sh
new file mode 100755
index 0000000..b0edfc5
--- /dev/null
+++ b/el7/createmodule.sh
@@ -0,0 +1,207 @@
+#!/bin/bash
+#
+# createmodule.sh - Takes the name of a environment init script and
+# produces a modulefile that duplicates the changes made by the init script
+#
+# Copyright (C) 2010-2012 by Orion E. Poplawski <orion@cora.nwra.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+usage="Usage: $0 [-p prefix] <initscript> [args]"
+
+usage() {
+ echo $usage 1>&2
+ exit 1
+}
+
+while getopts "p:" opt
+do
+ case $opt in
+ p) prefix=$OPTARG; shift 2;;
+ *) usage;;
+ esac
+done
+
+# Need a script name
+[ -z "$1" ] && usage
+
+# Need to be a readable script
+if [ ! -r "$1" ]
+then
+ echo "ERROR: Cannot read $1" 1>&2
+ exit 1
+fi
+
+#Will print out array assignment list
+printenvarray () {
+ env | while read x
+ do
+ key=${x%%=*}
+ value=`printenv "$key"`
+ if [ $? -eq 0 ]
+ then
+ echo [$key]="'$value'"
+ fi
+ done
+}
+
+#Apparently we need to declare the associative arrays
+declare -A env1 env2
+
+#Record starting environment
+eval env1=(`printenvarray`)
+
+#Source the environment script
+. "$@"
+
+#Record ending environment
+eval env2=(`printenvarray`)
+
+#Print out the modulefile
+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`
+ [ -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
+ if [ -n "$prefix" ]
+ then
+ echo $x | sed -e s,$prefix,\$prefix,
+ else
+ echo $x
+ fi
+ echo $x >> $list
+ done | tr '\n' $sep | sed -e "s/\\$sep\$//"
+ rm $list
+}
+
+#Keys that changed
+for key in "${!env1[@]}"
+do
+ if [ "${env1[$key]}" != "${env2[$key]}" ]
+ then
+ #Working directory change
+ if [ "$key" = PWD ]
+ then
+ if [ -n "$prefix" ]
+ then
+ echo -e "chdir\t\t${env2[PWD]}" | sed -e s,$prefix,\$prefix,g
+ else
+ echo -e "chdir\t\t${env2[PWD]}"
+ fi
+ #Test for delete
+ elif [ -z "${env2[$key]}" ]
+ then
+ echo -e "unsetenv\t${key}\t${env2[$key]}"
+ #Test for prepend
+ elif [ "${env2[$key]%${env1[$key]}}" != "${env2[$key]}" ]
+ then
+ 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 [ "${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=${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]}" ]
+ then
+ 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
+ echo "Before <${env1[$key]}>" 1>&2
+ echo "After <${env2[$key]}>" 1>&2
+ fi
+ fi
+ #Delete keys we have handled
+ unset env1[$key]
+ unset env2[$key]
+done
+
+#New keys
+for key in "${!env2[@]}"
+do
+ if [ "$key" = OLDPWD ]
+ then
+ continue
+ fi
+ #Use prepend-path for new paths
+ 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]})
+ else
+ if [ -n "$prefix" ]
+ then
+ echo -e "setenv\t\t${key}\t${env2[$key]}" | sed -e s,$prefix,\$prefix,g
+ else
+ echo -e "setenv\t\t${key}\t${env2[$key]}"
+ fi
+ fi
+done
+) | sort
diff --git a/el7/environment-modules-3.2.10-ignore-nested-dirs.patch b/el7/environment-modules-3.2.10-ignore-nested-dirs.patch
new file mode 100644
index 0000000..b53e71b
--- /dev/null
+++ b/el7/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/el7/environment-modules-3.2.10-unload-from-module.patch b/el7/environment-modules-3.2.10-unload-from-module.patch
new file mode 100644
index 0000000..c848752
--- /dev/null
+++ b/el7/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/el7/environment-modules-3.2.7-bindir.patch b/el7/environment-modules-3.2.7-bindir.patch
new file mode 100644
index 0000000..1efb0ee
--- /dev/null
+++ b/el7/environment-modules-3.2.7-bindir.patch
@@ -0,0 +1,11 @@
+--- modules-3.2.7/init/Makefile.in.bindir 2009-09-22 12:13:52.000000000 -0600
++++ modules-3.2.7/init/Makefile.in 2009-09-23 12:19:50.797470155 -0600
+@@ -404,7 +404,7 @@
+ sed -e "/@$(if $(subst 0,,$(WANTS_VERSIONING)),NOT,)VERSIONING\@/d; \
+ s,@$(if $(subst 0,,$(WANTS_VERSIONING)),,NOT)VERSIONING\@,,g; \
+ s,@prefix\@,${prefix},g; \
+- s,@bindir\@,${exec_prefix}/bin,g; \
++ s,@bindir\@,${bindir},g; \
+ s,@VERSION\@,@VERSION@,g; \
+ s,@BASEPREFIX\@,@BASEPREFIX@,g;" < $< > $@
+
diff --git a/el7/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch b/el7/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch
new file mode 100644
index 0000000..2e8b04e
--- /dev/null
+++ b/el7/environment-modules-3.2.9-call-test-by-full-path-in-csh.patch
@@ -0,0 +1,11 @@
+--- modules-3.2.9/init/csh.in 2010-11-11 19:23:18.000000000 +0100
++++ modules-3.2.9-new/init/csh.in 2013-05-14 08:43:11.686954109 +0200
+@@ -34,7 +34,7 @@
+ set prefix = "$prefix""set noglob;"
+ set postfix = "$postfix""unset noglob;"
+ endif
+-set postfix = "set _exit="'$status'"; $postfix; test 0 = "'$_exit;'
++set postfix = "set _exit="'$status'"; $postfix; @bindir@/test 0 = "'$_exit;'
+
+ @VERSIONING@alias module $prefix'eval `'$exec_prefix'/bin/modulecmd '$modules_shell' '$histchar'*`; '$postfix
+ @NOTVERSIONING@alias module $prefix'eval `'$exec_prefix'/modulecmd '$modules_shell' '$histchar'*`; '$postfix
diff --git a/el7/environment-modules-avail.patch b/el7/environment-modules-avail.patch
new file mode 100644
index 0000000..8d6f52b
--- /dev/null
+++ b/el7/environment-modules-avail.patch
@@ -0,0 +1,12 @@
+diff -up modules-3.2.10/init/bash_completion.in.avail modules-3.2.10/init/bash_completion.in
+--- modules-3.2.10/init/bash_completion.in.avail 2012-10-25 13:33:34.000000000 -0600
++++ modules-3.2.10/init/bash_completion.in 2013-01-15 12:05:37.247309733 -0700
+@@ -56,7 +56,7 @@ _module() {
+ unuse) COMPREPLY=( $(IFS=: compgen -W "${MODULEPATH}" -- "$cur") );;
+ use|*-a*) ;; # let readline handle the completion
+ -u|--userlvl) COMPREPLY=( $(compgen -W "novice expert advanced" -- "$cur") );;
+- display|help|show|whatis)
++ av*|disp*|help|show|whatis)
+ COMPREPLY=( $(compgen -W "$(_module_avail)" -- "$cur") );;
+ *) if test $COMP_CWORD -gt 2
+ then
diff --git a/el7/environment-modules-clear.patch b/el7/environment-modules-clear.patch
new file mode 100644
index 0000000..0817db5
--- /dev/null
+++ b/el7/environment-modules-clear.patch
@@ -0,0 +1,11 @@
+--- modules-3.2.9/utility.c 2011-11-28 22:27:13.000000000 +0100
++++ modules-3.2.9-new/utility.c 2012-06-13 15:17:41.570629148 +0200
+@@ -727,7 +727,7 @@ int Output_Modulefile_Changes( Tcl_Inter
+ output_unset_variable( (char*) key);
+ } else {
+ val = EMGetEnv(interp, key);
+- if(val && *val)
++ if(val)
+ output_set_variable(interp, (char*) key, val);
+ null_free((void *)&val);
+ }
diff --git a/el7/environment-modules-versioning.patch b/el7/environment-modules-versioning.patch
new file mode 100644
index 0000000..7bda920
--- /dev/null
+++ b/el7/environment-modules-versioning.patch
@@ -0,0 +1,10 @@
+diff -up modules-3.2.10/modulefiles/modules.in.versioning modules-3.2.10/modulefiles/modules.in
+--- modules-3.2.10/modulefiles/modules.in.versioning 2012-10-25 13:33:34.000000000 -0600
++++ modules-3.2.10/modulefiles/modules.in 2013-01-15 11:30:22.046031158 -0700
+@@ -26,5 +26,5 @@ setenv MODULESHOME $prefix
+ prepend-path PATH @bindir@
+ prepend-path MANPATH @mandir@
+
+-module use @VERSIONPATH@
++@VERSIONING@module use @VERSIONPATH@
+
diff --git a/el7/environment-modules.spec b/el7/environment-modules.spec
new file mode 100644
index 0000000..ef1f405
--- /dev/null
+++ b/el7/environment-modules.spec
@@ -0,0 +1,271 @@
+Name: environment-modules
+Version: 3.2.10
+Release: 10%{?dist}
+Summary: Provides dynamic modification of a user's environment
+
+Group: System Environment/Base
+License: GPLv2+
+URL: http://modules.sourceforge.net/
+Source0: http://downloads.sourceforge.net/modules/modules-%{version}.tar.bz2
+Source1: modules.sh
+Source2: createmodule.sh
+Source3: createmodule.py
+Patch0: environment-modules-3.2.7-bindir.patch
+# Comment out stray module use in modules file when not using versioning
+# https://bugzilla.redhat.com/show_bug.cgi?id=895555
+Patch1: environment-modules-versioning.patch
+# Fix module clear command
+# https://bugzilla.redhat.com/show_bug.cgi?id=895551
+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
+BuildRequires: man
+#For ps in startup script
+Requires: procps
+
+%description
+The Environment Modules package provides for the dynamic modification of
+a user's environment via modulefiles.
+
+Each modulefile contains the information needed to configure the shell
+for an application. Once the Modules package is initialized, the
+environment can be modified on a per-module basis using the module
+command which interprets modulefiles. Typically modulefiles instruct
+the module command to alter or set shell environment variables such as
+PATH, MANPATH, etc. modulefiles may be shared by many users on a system
+and users may have their own collection to supplement or replace the
+shared modulefiles.
+
+Modules can be loaded and unloaded dynamically and atomically, in an
+clean fashion. All popular shells are supported, including bash, ksh,
+zsh, sh, csh, tcsh, as well as some scripting languages such as perl.
+
+Modules are useful in managing different versions of applications.
+Modules can also be bundled into metamodules that will load an entire
+suite of different applications.
+
+NOTE: You will need to get a new shell after installing this package to
+have access to the module alias.
+
+
+%prep
+%setup -q -n modules-%{version}
+%patch0 -p1 -b .bindir
+%patch1 -p1 -b .versioning
+%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
+%configure --disable-versioning \
+ --prefix=%{_datadir} \
+ --exec-prefix=%{_datadir}/Modules \
+ --with-man-path=$(manpath) \
+ --with-module-path=%{_sysconfdir}/modulefiles
+# --with-debug=42 --with-log-facility-debug=stderr
+make %{?_smp_mflags}
+
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
+cp -p %SOURCE1 $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/modules.sh
+cp -p %SOURCE2 %SOURCE3 $RPM_BUILD_ROOT%{_datadir}/Modules/bin
+ln -s %{_datadir}/Modules/init/csh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/modules.csh
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/modulefiles
+
+
+%check
+make test
+
+
+%files
+%doc LICENSE.GPL README TODO
+%{_sysconfdir}/modulefiles
+%config(noreplace) %{_sysconfdir}/profile.d/*
+%{_bindir}/modulecmd
+%dir %{_datadir}/Modules
+%{_datadir}/Modules/bin/
+%dir %{_datadir}/Modules/init
+%config(noreplace) %{_datadir}/Modules/init/*
+%config(noreplace) %{_datadir}/Modules/init/.modulespath
+%{_datadir}/Modules/modulefiles
+%{_mandir}/man1/module.1.gz
+%{_mandir}/man4/modulefile.4.gz
+
+
+%changelog
+* Mon Jun 22 2015 Jan Synáček <jsynacek@redhat.com> - 3.2.10-10
+- fix: createmodule scripts incorrectly handles env vars prefixed/suffixed without colon (#1233223)
+
+* Wed Apr 29 2015 Jan Synáček <jsynacek@redhat.com> - 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 <dmach@redhat.com> - 3.2.10-8
+- Mass rebuild 2014-01-24
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 3.2.10-7
+- Mass rebuild 2013-12-27
+
+* Thu Aug 8 2013 Jan Synáček <jsynacek@redhat.com> - 3.2.10-6
+- Call test command in csh alias by its full path (bug #977331)
+
+* Tue May 14 2013 Orion Poplawski <orion@cora.nwra.com> - 3.2.10-5
+- Really do not replace modified profile.d scripts (bug #962762)
+- Specfile cleanup
+
+* Wed Apr 17 2013 Orion Poplawski <orion@cora.nwra.com> - 3.2.10-4
+- Do not replace modified profile.d scripts (bug #953199)
+
+* Wed Feb 13 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.10-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
+
+* Tue Jan 15 2013 Orion Poplawski <orion@cora.nwra.com> - 3.2.10-2
+- Add patch to comment out stray module use in modules file when not using
+ versioning (bug #895555)
+- Add patch to fix module clear command (bug #895551)
+- Add patch from modules list to add completion to avail command
+
+* Fri Dec 21 2012 Orion Poplawski <orion@cora.nwra.com> - 3.2.10-1
+- Update to 3.2.10
+- Drop regex patch
+
+* Wed Oct 31 2012 Orion Poplawski <orion@cora.nwra.com> - 3.2.9c-5
+- Updated createmodule.sh, added createmodule.py, can handle path prefixes
+
+* Fri Aug 24 2012 Orion Poplawski <orion@cora.nwra.com> - 3.2.9c-4
+- Add patch to fix segfault from Tcl RexExp handling (bug 834580)
+
+* Wed Jul 18 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.9c-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.9c-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Tue Nov 29 2011 Orion Poplawski <orion@cora.nwra.com> - 3.2.9c-1
+- Update to 3.2.9c (fixes bug 753760)
+
+* Tue Nov 22 2011 Orion Poplawski <orion@cora.nwra.com> - 3.2.9b-2
+- Make .modulespath a config file
+
+* Tue Nov 15 2011 Orion Poplawski <orion@cora.nwra.com> - 3.2.9b-1
+- Update to 3.2.9b
+
+* Fri Nov 11 2011 Orion Poplawski <orion@cora.nwra.com> - 3.2.9a-2
+- Add %%check section
+
+* Fri Nov 11 2011 Orion Poplawski <orion@cora.nwra.com> - 3.2.9a-1
+- Update to 3.2.9a
+- Drop strcpy patch
+
+* Thu Sep 22 2011 Orion Poplawski <orion@cora.nwra.com> - 3.2.8a-3
+- Add patch to fix overlapping strcpy() in Remove_Path, hopefully fixes
+ bug 737043
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.8a-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Mon Oct 4 2010 Orion Poplawski <orion@cora.nwra.com> - 3.2.8a-1
+- Update to 3.2.8a, changes --with-def-man-path to --with-man-path
+
+* Mon Oct 4 2010 Orion Poplawski <orion@cora.nwra.com> - 3.2.8-1
+- Update to 3.2.8
+- Drop mandir patch, use --with-def-man-path
+
+* Thu Jan 7 2010 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-7
+- Add patch to set a sane default MANPATH
+- Add createmodule.sh utility script for creating modulefiles
+
+* Mon Nov 30 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-6
+- Add Requires: propcs (bug #54272)
+
+* Mon Oct 26 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-5
+- Don't assume different shell init scripts exist (bug #530770)
+
+* Fri Oct 23 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-4
+- Don't load bash init script when bash is running as "sh" (bug #529745)
+
+* Mon Oct 19 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-3
+- Support different flavors of "sh" (bug #529493)
+
+* Wed Sep 23 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-2
+- Add patch to fix modulecmd path in init files
+
+* Wed Sep 23 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7b-1
+- Update to 3.2.7b
+
+* Mon Sep 21 2009 Orion Poplawski <orion@cora.nwra.com> - 3.2.7-1
+- Update to 3.2.7, fixes bug #524475
+- Drop versioning patch fixed upstream
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.6-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Tue Feb 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.6-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Wed Sep 3 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-6
+- Change %%patch -> %%patch0
+
+* Fri Mar 14 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-5
+- Add BR libX11-devel so modulecmd can handle X resources
+
+* Wed Mar 5 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-4
+- Add patch to fix extraneous version path entry properly
+- Use --with-module-path to point to /etc/modulefiles for local modules,
+ this also fixes bug #436041
+
+* Sat Feb 9 2008 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-3
+- Rebuild for gcc 3.4
+
+* Thu Jan 03 2008 - Alex Lancaster <alexlan at fedoraproject.org> - 3.2.6-2
+- Rebuild for new Tcl (8.5).
+
+* Fri Nov 2 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.6-1
+- Update to 3.2.6
+
+* Tue Aug 21 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.5-2
+- Update license tag to GPLv2
+
+* Fri Feb 16 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.5-1
+- Update to 3.2.5
+
+* Wed Feb 14 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.4-2
+- Rebuild for Tcl downgrade
+
+* Fri Feb 09 2007 - Orion Poplawski <orion@cora.nwra.com> - 3.2.4-1
+- Update to 3.2.4
+
+* Wed Dec 20 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.3-3
+- Add --with-version-path to set VERSIONPATH (bug 220260)
+
+* Tue Aug 29 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.3-2
+- Rebuild for FC6
+
+* Fri Jun 2 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.3-1
+- Update to 3.2.3
+
+* Fri May 5 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.2-1
+- Update to 3.2.2
+
+* Fri Mar 24 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.1-1
+- Update to 3.2.1
+
+* Thu Feb 9 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.0p1-1
+- Update to 3.2.0p1
+
+* Fri Jan 27 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.0-2
+- Add profile.d links
+
+* Tue Jan 24 2006 - Orion Poplawski <orion@cora.nwra.com> - 3.2.0-1
+- Fedora Extras packaging
diff --git a/el7/modules.sh b/el7/modules.sh
new file mode 100644
index 0000000..48cc324
--- /dev/null
+++ b/el7/modules.sh
@@ -0,0 +1,7 @@
+shell=`/bin/basename \`/bin/ps -p $$ -ocomm=\``
+if [ -f /usr/share/Modules/init/$shell ]
+then
+ . /usr/share/Modules/init/$shell
+else
+ . /usr/share/Modules/init/sh
+fi