Repository: ESMCI/cime

Issue:
Enable source scripts in module_system
In a module system, it's useful to add `source setup_script` (e.g. `source compilervars.sh intel64`) to set up env-vars for new packages (that don't have a module to `module load package/x.y.z`). This doesn't appear to be working in current env_mach_specific.xml workflow.


Discussion:

Resolving patch:
diff --git a/scripts/lib/CIME/XML/env_mach_specific.py b/scripts/lib/CIME/XML/env_mach_specific.py
--- a/scripts/lib/CIME/XML/env_mach_specific.py
+++ b/scripts/lib/CIME/XML/env_mach_specific.py
@@ -191,9 +191,16 @@ def make_env_mach_specific_file(self, shell, case, output_dir=''):
         if envs_to_set is not None:
             for env_name, env_value in envs_to_set:
                 if shell == "sh":
-                    lines.append("export {}={}".format(env_name, env_value))
+                    if env_name:
+                        lines.append("export {}={}".format(env_name, env_value))
+                    else:
+                        lines.append("source {}".format(env_value))
+
                 elif shell == "csh":
-                    lines.append("setenv {} {}".format(env_name, env_value))
+                    if env_name:
+                        lines.append("setenv {} {}".format(env_name, env_value))
+                    else:
+                        lines.append("echo \"This case includes a shell source file {} which cannot be used from csh type shells\"".format(env_value))
                 else:
                     expect(False, "Unknown shell type: '{}'".format(shell))
 
@@ -209,8 +216,13 @@ def _load_envs(self, envs_to_set, verbose=False):
                 del os.environ[env_name]
                 logger_func("Unsetting Environment {}".format(env_name))
             elif env_value is not None:
-                os.environ[env_name] = env_value
-                logger_func("Setting Environment {}={}".format(env_name, env_value))
+                if env_name is None:
+                    cmd = "source "+ env_value
+                    self._source_sh_file(cmd, verbose=True)
+                else:
+                    print("Setting Environment {}={}".format(env_name, env_value))
+                    logger_func("Setting Environment {}={}".format(env_name, env_value))
+                    os.environ[env_name] = env_value
 
     def _compute_module_actions(self, module_nodes, case, job=None):
         return self._compute_actions(module_nodes, "command", case, job=job)
@@ -256,7 +268,7 @@ def _match_attribs(self, attribs, case, job=None):
                     expect(val is not None, "Cannot match attrib '%s', case has no value for it" % attrib.upper())
                     if not self._match(val, attribs[attrib]):
                         return False
-            elif attrib == "name":
+            elif attrib in ("name", "source"):
                 pass
             else:
                 val = case.get_value(attrib.upper())
@@ -332,7 +344,6 @@ def _load_module_modules(self, modules_to_load, verbose=False):
     def _load_modules_generic(self, modules_to_load, verbose=False):
         sh_init_cmd = self.get_module_system_init_path("sh")
         sh_mod_cmd = self.get_module_system_cmd_path("sh")
-        logger_func = logger.warning if verbose else logger.debug
 
         # Purpose is for environment management system that does not have
         # a python interface and therefore can only determine what they
@@ -349,8 +360,12 @@ def _load_modules_generic(self, modules_to_load, verbose=False):
         for action,argument in modules_to_load:
             cmd += " && {} {} {}".format(sh_mod_cmd, action, "" if argument is None else argument)
 
+        self._source_sh_file(cmd, verbose=verbose)
+
+    def _source_sh_file(self, cmd, verbose=False):
         # Use null terminated lines to give us something more definitive to split on.
         # Env vars can contain newlines, so splitting on newlines can be ambiguous
+        logger_func = logger.warning if verbose else logger.debug
         cmd += " && env -0"
         logger_func("cmd: {}".format(cmd))
         output = run_cmd_no_fail(cmd)


Test patch: