[environment-modules] Updated createmodule.sh and added createmodule.py

Orion Poplawski orion at fedoraproject.org
Wed Oct 31 22:12:21 UTC 2012


commit 9c1d7d90122e1ea49eab32ac855598d3ebce4a7d
Author: Orion Poplawski <orion at nwra.com>
Date:   Wed Oct 31 16:10:14 2012 -0600

    Updated createmodule.sh and added createmodule.py

 createmodule.py |  186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 createmodule.sh |  149 +++++++++++++++++++++++++++++++------------
 2 files changed, 293 insertions(+), 42 deletions(-)
---
diff --git a/createmodule.py b/createmodule.py
new file mode 100755
index 0000000..60c6ba7
--- /dev/null
+++ b/createmodule.py
@@ -0,0 +1,186 @@
+#!/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 at 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 optparse import OptionParser
+import os,sys
+from subprocess import *
+
+# Handle options
+usage = "Usage: %prog [-p prefix] <initscript> [args]"
+parser = OptionParser()
+parser.set_usage(usage)
+parser.add_option('-p', '--prefix', dest='prefix', help='Specify path 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
+    for line in stdout.splitlines():
+        try:
+            (var,value) = line.split('=',1)
+        except ValueError:
+            print "ERROR: Could not parse output:"
+            print stdout
+            exit(1)
+        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 = {}
+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:
+             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
+    (prepend,append) = env2[key].split(env1[key])
+    if prepend:
+        prependpaths = prepend.strip(':').split(':')
+        # LICENSE variables often include paths outside install directory
+        if 'LICENSE' not in key:
+            pathnames += prependpaths
+        prependpath[key] = ':'.join(normpaths(prependpaths))
+    if append:
+        appendpaths = append.strip(':').split(':')
+        # LICENSE variables often include paths outside install directory
+        if 'LICENSE' not in key:
+            pathnames += appendpaths
+        appendpath[key] = ':'.join(normpaths(appendpaths))
+    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]):
+        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))
+        continue
+    # Set new variables
+    setenv[key] = os.path.normpath(env2[key])
+    if 'LICENSE' not in key:
+        pathnames.append(setenv[key])
+
+# Determine a prefix
+prefix = None
+if options.prefix:
+    prefix = options.prefix
+else:
+    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,
+    print "\t"*(2-(len(item)+1)/8),
+    print key,
+    if value is not None:
+        print "\t"*(3-(len(key)+1)/8),
+        if prefix is not None:
+            print value.replace(prefix,'$prefix')
+        else:
+            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])
+
+# Setenv
+setenvkeys = 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/createmodule.sh b/createmodule.sh
index 8b82b34..b44cf05 100755
--- a/createmodule.sh
+++ b/createmodule.sh
@@ -3,7 +3,7 @@
 # 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 by Orion E. Poplawski
+# Copyright (C) 2010-2012 by Orion E. Poplawski <orion at 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
@@ -18,10 +18,29 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if [ -z "$1" ]
-then
-  echo "usage: $0 <initscript> [args]" 1>&2
+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
@@ -49,53 +68,99 @@ eval env2=(`printenvarray`)
 #Print out the modulefile
 echo "#%Module 1.0"
 
+#Prefix
+[ -n "$prefix" ] && echo -e "\nset prefix $prefix\n"
+
+#Subshell so we can sort the output
+(
+dedup() {
+  list=`mktemp`
+  echo $1 | sed -r -e 's,[^/]+/\.\./,,g' -e 's,[^/]+/\.\./,,g' -e 's/:/\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' : | sed -e 's/:$//'
+  rm $list
+} 
+    
 #Keys that changed
 for key in "${!env1[@]}"
 do
-   if [ "${env1[$key]}" != "${env2[$key]}" ]
-   then
-      #Working directory change
-      if [ "$key" = PWD ]
-      then
-	echo -e "chdir\t\t${env2[PWD]}"
-      #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]}}"
-         echo -e "prepend-path\t$key\t${added%:}"
-      #Test for append
-      elif [ "${env2[$key]#${env1[$key]}}" != "${env2[$key]}" ]
+  if [ "${env1[$key]}" != "${env2[$key]}" ]
+  then
+    #Working directory change
+    if [ "$key" = PWD ]
+    then
+      if [ -n "$prefix" ]
       then
-         added="${env2[$key]#${env1[$key]}}"
-         echo -e "append-path\t$key\t${added#:}"
+        echo -e "chdir\t\t${env2[PWD]}" | sed -e s,$prefix,\$prefix,g
       else
-         #Unhandled
-         echo "Unhandled change of $key" 1>&2
-         echo "Before <${env1[$key]}>" 1>&2
-         echo "After  <${env2[$key]}>" 1>&2
+        echo -e "chdir\t\t${env2[PWD]}"
       fi
-   fi
-   #Delete keys we've handled
-   unset env1[$key]
-   unset env2[$key]
+    #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=$(dedup ${env2[$key]%:${env1[$key]}})
+      echo -e "prepend-path\t$key\t${added}"
+    #Test for prepend plus : added at end (MANPATH)
+    elif [ "${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}"
+    #Test for prepend plus append
+    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}"
+    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've 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/PATH/}" != "$key" ]
-   then
-     echo -e "prepend-path\t${key}\t${env2[$key]}"
-   else
-     echo -e "setenv\t\t${key}\t${env2[$key]}"
-   fi
+  if [ "$key" = OLDPWD ]
+  then
+    continue
+  fi
+  #Use prepend-path for new paths
+  if [ "${key/PATH/}" != "$key" ]
+  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


More information about the scm-commits mailing list