Repository: ESMCI/cime

Issue:
Feature request: xmlchange tells you what steps need to be rerun for the change to take effect
This is a feature request that popped to mind, which is for the sake of relatively inexperienced users: It would be nice if xmlchange noticed when you change a setting that requires you to re-do some step, and gave you the commands you need to run for the change to take effect.

For example, if you change a setting in env_build.xml after you have already done the build, then it will tell you something like:

```
For this change to take effect, run:
./case.build --clean-all
./case.build
```

(I'm actually not sure if those are the commands you need to run when changing env_build.xml... maybe this feature request is as much for me as for "inexperienced users", or maybe I myself fall into the "inexperienced user" category in this respect....)

I'm imagining some pretty simple rules like: If a setting in env_build is changed after the build is complete, then you need to redo the build; if a setting in env_mach_pes is changed after case.setup is complete, then you need to redo case.setup. That may be all that's really needed.

What made me think of this was thinking of how things have changed since CESM1: In CESM1, you needed to explicitly specify the file to change via xmlchange. Now that is determined automatically. That automatic determination is very nice, but the downside is that it lets you change files without realizing that (for example) you're changing a build-time setting that requires a rebuild.


Discussion:
Feeling from today's cseg meeting: We'd like to do this, but it isn't the highest priority. Mariana agreed with my sense that this mainly / only applies to changes to env_mach_pes.xml (need to rerun case.setup, and then presumably the build) and env_build.xml (need to rerun case.build).

Resolving patch:
diff --git a/scripts/lib/CIME/case/case.py b/scripts/lib/CIME/case/case.py
--- a/scripts/lib/CIME/case/case.py
+++ b/scripts/lib/CIME/case/case.py
@@ -368,11 +368,12 @@ def get_resolved_value(self, item, recurse=0, allow_unresolved_envvars=False):
 
         return item
 
-    def set_value(self, item, value, subgroup=None, ignore_type=False, allow_undefined=False):
+    def set_value(self, item, value, subgroup=None, ignore_type=False, allow_undefined=False, return_file=False):
         """
         If a file has been defined, and the variable is in the file,
-        then that value will be set in the file object and the file
-        name is returned
+        then that value will be set in the file object and the resovled value
+        is returned unless return_file is True, in which case (resolved_value, filename)
+        is returned where filename is the name of the modified file.
         """
         if item == "CASEROOT":
             self._caseroot = value
@@ -382,7 +383,7 @@ def set_value(self, item, value, subgroup=None, ignore_type=False, allow_undefin
             result = env_file.set_value(item, value, subgroup, ignore_type)
             if (result is not None):
                 logger.debug("Will rewrite file {} {}".format(env_file.filename, item))
-                return result
+                return (result, env_file.filename) if return_file else result
 
         if len(self._files) == 1:
             expect(allow_undefined or result is not None,
diff --git a/scripts/lib/CIME/case/case_setup.py b/scripts/lib/CIME/case/case_setup.py
--- a/scripts/lib/CIME/case/case_setup.py
+++ b/scripts/lib/CIME/case/case_setup.py
@@ -173,7 +173,6 @@ def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False):
             else:
                 case.set_value("TOTALPES", case.total_tasks*case.thread_count)
 
-
             # May need to select new batch settings if pelayout changed (e.g. problem is now too big for prev-selected queue)
             env_batch = case.get_env("batch")
             env_batch.set_job_defaults([(case.get_primary_job(), {})], case)
@@ -225,8 +224,6 @@ def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False):
 
         logger.info("You can now run './preview_run' to get more info on how your case will be run")
 
-        logger.info("You can now run './preview_run' to get more info on how your case will be run")
-
 ###############################################################################
 def case_setup(self, clean=False, test_mode=False, reset=False):
 ###############################################################################


Test patch: