Repository: ESMCI/cime

Issue:
MODEL_VERSION doesn't get set correctly for non CESM checkouts...
For cesm MODEL_VERSION gets set by reading in the ChangeLog at the top of SRCROOT as follows in case.py. This is with the latest master.

```
    def set_model_version(self, model):
        version = "unknown"
        srcroot = self.get_value("SRCROOT")
        if model == "cesm":
            changelog = os.path.join(srcroot,"ChangeLog")
            if os.path.isfile(changelog):
                for line in open(changelog, "r"):
                    m = re.search("Tag name: (cesm.*)$", line)
                    if m is not None:
                        version = m.group(1)
                        break
```
This logic requires that ChangeLog exist at the top of SRCROOT, and that the tag name start with cesm. Neither of these things are true for CLM checkouts. Nor would be true for a CAM checkout.

This problem doesn't happen for acme since they use get_current_commit from utils.py, which fills the value with the SHA1 using a git command (git rev-parse HEAD). For acme, they also save a bunch of provenance information including the value from "git describe".

Since, cesm has now moved over to git, could we have MODEL_VERSION for cesm set by "git describe" of SRCROOT rather than the ChangeLog file? 'git describe' is nice since it gets you the most recent tagname plus part of the SHA from any commits since that tag. For example, 'git describe' on current master of cesm gives you "cesm2_0_alpha09a".

@billsacks @bandre-ucar @gold2718 @cacraigucar



Discussion:
We talked about this at the cseg meeting this morning and @jedwards4b agreed to take this on. Both in the sense of have cesm do something closer to acme, and making sure MODEL_VERSION is set in a way that would work for CESM, CLM, and CAM.
I believe that we can use the --status flag from checkout_externals to do this and will work on this approach.

Resolving patch:
diff --git a/scripts/lib/CIME/case.py b/scripts/lib/CIME/case.py
--- a/scripts/lib/CIME/case.py
+++ b/scripts/lib/CIME/case.py
@@ -638,7 +638,7 @@ def _get_component_config_data(self, files):
                    "Config file {} for component {} not found.".format(comp_config_file, comp_name))
             compobj = Component(comp_config_file, comp_class)
             # For files following version 3 schema this also checks the compsetname validity
-            
+
             self._component_description[comp_class] = compobj.get_description(self._compsetname)
             expect(self._component_description[comp_class] is not None,"No description found in file {} for component {} in comp_class {}".format(comp_config_file, comp_name, comp_class))
             logger.info("{} component is {}".format(comp_class, self._component_description[comp_class]))
@@ -1256,16 +1256,8 @@ def get_mpirun_cmd(self, job="case.run"):
     def set_model_version(self, model):
         version = "unknown"
         srcroot = self.get_value("SRCROOT")
-        if model == "cesm":
-            changelog = os.path.join(srcroot,"ChangeLog")
-            if os.path.isfile(changelog):
-                for line in open(changelog, "r"):
-                    m = re.search("Tag name: (cesm.*)$", line)
-                    if m is not None:
-                        version = m.group(1)
-                        break
-        elif model == "e3sm":
-            version = get_current_commit(True, srcroot)
+        version = get_current_commit(True, srcroot, tag=(model=="cesm"))
+
         self.set_value("MODEL_VERSION", version)
 
         if version != "unknown":
diff --git a/scripts/lib/CIME/provenance.py b/scripts/lib/CIME/provenance.py
--- a/scripts/lib/CIME/provenance.py
+++ b/scripts/lib/CIME/provenance.py
@@ -79,9 +79,16 @@ def _save_build_provenance_e3sm(case, lid):
 def _save_build_provenance_cesm(case, lid): # pylint: disable=unused-argument
     version = case.get_value("MODEL_VERSION")
     # version has already been recorded
+    srcroot = case.get_value("SRCROOT")
+    manic = os.path.join(srcroot, "manage_externals","checkout_externals")
+    if os.path.exists(manic):
+        out = run_cmd_no_fail(manic + " --status --verbose", from_dir=srcroot)
     caseroot = case.get_value("CASEROOT")
     with open(os.path.join(caseroot, "README.case"), "a") as fd:
-        fd.write("CESM version is {}\n".format(version))
+        if version is not None and version != "unknown":
+            fd.write("CESM version is {}\n".format(version))
+        if out is not None:
+            fd.write("{}\n".format(out))
 
 def save_build_provenance(case, lid=None):
     with SharedArea():
diff --git a/scripts/lib/CIME/utils.py b/scripts/lib/CIME/utils.py
--- a/scripts/lib/CIME/utils.py
+++ b/scripts/lib/CIME/utils.py
@@ -604,14 +604,17 @@ def get_current_branch(repo=None):
         else:
             return output.replace("refs/heads/", "")
 
-def get_current_commit(short=False, repo=None):
+def get_current_commit(short=False, repo=None, tag=False):
     """
     Return the sha1 of the current HEAD commit
 
     >>> get_current_commit() is not None
     True
     """
-    rc, output, _ = run_cmd("git rev-parse {} HEAD".format("--short" if short else ""), from_dir=repo)
+    if tag:
+        rc, output, _ = run_cmd("git describe --tags $(git log -n1 --pretty='%h')", from_dir=repo)
+    else:
+        rc, output, _ = run_cmd("git rev-parse {} HEAD".format("--short" if short else ""), from_dir=repo)
     if rc == 0:
         return output
     else:


Test patch: