Repository: ESMCI/cime

Issue:
case.setup --clean puts case in an unusable state
On cime master, running `./case.setup --clean` puts the case in an unusable state:

I ran the following on cheyenne:

```
./create_newcase --case $scratch/test_0424b --compset X --res f19_g16
cd $scratch/test_0424b
./case.setup
./case.setup --clean
```

At this point, I can't seem to do anything. For example:

```
./xmlquery CASE
ERROR: Makes no sense to have empty read-only file
```

and

```
./case.setup
ERROR: Could not find a matching MPI for attributes: {'mpilib': 'mpt', 'threaded': False, 'compiler': 'intel'}
```



Discussion:

Resolving patch:
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
@@ -73,6 +73,15 @@ def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False,
 
     non_local = case.get_value("NONLOCAL")
 
+    models = case.get_values("COMP_CLASSES")
+    mach = case.get_value("MACH")
+    compiler = case.get_value("COMPILER")
+    debug = case.get_value("DEBUG")
+    mpilib = case.get_value("MPILIB")
+    sysos = case.get_value("OS")
+    comp_interface = case.get_value("COMP_INTERFACE")
+    expect(mach is not None, "xml variable MACH is not set")
+
     # Check that $DIN_LOC_ROOT exists - and abort if not a namelist compare tests
     if not non_local:
         din_loc_root = case.get_value("DIN_LOC_ROOT")
@@ -94,20 +103,16 @@ def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False,
             # rebuild the models (even on restart)
             case.set_value("BUILD_COMPLETE", False)
 
+        # Cannot leave case in bad state (missing env_mach_specific.xml)
+        if clean and not os.path.isfile("env_mach_specific.xml"):
+            case.flush()
+            configure(Machines(machine=mach), caseroot, ["Makefile"], compiler, mpilib, debug, comp_interface, sysos, noenv=True)
+            case.read_xml()
+
     if not clean:
         if not non_local:
             case.load_env()
 
-        models = case.get_values("COMP_CLASSES")
-        mach = case.get_value("MACH")
-        compiler = case.get_value("COMPILER")
-        debug = case.get_value("DEBUG")
-        mpilib = case.get_value("MPILIB")
-        sysos = case.get_value("OS")
-        comp_interface = case.get_value("COMP_INTERFACE")
-        extra_machines_dir = case.get_value("EXTRA_MACHDIR")
-        expect(mach is not None, "xml variable MACH is not set")
-
         # creates the Macros.make, Depends.compiler, Depends.machine, Depends.machine.compiler
         # and env_mach_specific.xml if they don't already exist.
         if not os.path.isfile("Macros.make") or not os.path.isfile("env_mach_specific.xml"):


Test patch:
diff --git a/scripts/tests/scripts_regression_tests.py b/scripts/tests/scripts_regression_tests.py
--- a/scripts/tests/scripts_regression_tests.py
+++ b/scripts/tests/scripts_regression_tests.py
@@ -341,6 +341,11 @@ def setUpClass(cls):
         cls._testdirs = []
         cls._do_teardown = []
         cls._testroot = os.path.join(TEST_ROOT, 'TestCreateNewcase')
+        cls._root_dir = os.getcwd()
+
+    def tearDown(self):
+        cls = self.__class__
+        os.chdir(cls._root_dir)
 
     def test_a_createnewcase(self):
         cls = self.__class__
@@ -687,7 +692,6 @@ def test_j_createnewcase_user_compset_vs_alias(self):
         and make sure they are the same by comparing the namelist files in CaseDocs.
         Ignore the modelio files and clean the directory names out first.
         """
-
         cls = self.__class__
 
         testdir1 = os.path.join(cls._testroot, 'testcreatenewcase_user_compset')
@@ -756,7 +760,6 @@ def test_j_createnewcase_user_compset_vs_alias(self):
         cls._do_teardown.append(testdir1)
         cls._do_teardown.append(testdir2)
 
-
     def test_k_append_config(self):
         machlist_before = MACHINE.list_available_machines()
         self.assertEqual(len(machlist_before)>1, True, msg="Problem reading machine list")
@@ -901,8 +904,6 @@ def tearDownClass(cls):
         if rmtestroot and do_teardown:
             shutil.rmtree(cls._testroot)
 
-
-
 ###############################################################################
 class M_TestWaitForTests(unittest.TestCase):
 ###############################################################################
@@ -1184,12 +1185,15 @@ def setUp(self):
         self._testroot          = TEST_ROOT
         self._hasbatch          = MACHINE.has_batch_system() and not NO_BATCH
         self._do_teardown       = not NO_TEARDOWN
+        self._root_dir          = os.getcwd()
 
     ###########################################################################
     def tearDown(self):
     ###########################################################################
         kill_subprocesses()
 
+        os.chdir(self._root_dir)
+
         if (self._unset_proxy):
             del os.environ["http_proxy"]
 
@@ -2525,6 +2529,19 @@ def test_self_build_cprnc(self):
 
         self._wait_for_tests(self._baseline_name, always_wait=True)
 
+    ###########################################################################
+    def test_case_clean(self):
+    ###########################################################################
+        testname = "ERS_Ln7.f19_g16_rx1.A"
+        self._create_test([testname, "--no-build"], test_id=self._baseline_name)
+
+        casedir = os.path.join(self._testroot,
+                               "{}.{}".format(CIME.utils.get_full_test_name(testname, machine=self._machine, compiler=self._compiler), self._baseline_name))
+
+        run_cmd_assert_result(self, "./case.setup --clean", from_dir=casedir)
+        run_cmd_assert_result(self, "./case.setup --clean", from_dir=casedir)
+        run_cmd_assert_result(self, "./case.setup", from_dir=casedir)
+
 ###############################################################################
 class X_TestSingleSubmit(TestCreateTestCommon):
 ###############################################################################