Repository: ESMCI/cime

Issue:
Trailing slash in casename creates unexpected behavior
If the `casename` argument to `CIME.case.create()` has a trailing slash, the method used to extract the `casename` from a path results in an empty string for `lookups['CASE']`, which I suspect is not an intended result.  In CESM2, this causes the `CASE` variable to not be set in `env_case.xml`, which prevents building the model.

This results from the use of `os.path.basename()` in [scripts/lib/CIME/case/case.py#L1561](https://github.com/ESMCI/cime/blob/b7892a96367a2f144c6a5bea2e71ca7fdd9a41c6/scripts/lib/CIME/case/case.py#L1561), which [returns an empty string if the input path has a trailing slash](https://docs.python.org/3.6/library/os.path.html#os.path.basename).

I suspect that it isn't intended that users give casenames with a trailing slash, but this might inadvertently occur when users (like me) are constructing shell scripts to configure/build/run simulations.  In my case, this resulted from me referring to my case as both an argument to `create_newcase` and as a path that I would refer to in the shell script; I habitually add trailing slashes to directory paths when writing shell scripts.

If it is the case that users should not give a trailing slash, then perhaps `case.py` could be modified to flag an error if the `casename` argument has a trailing slash?


Discussion:
I'm seeing something similar in a CTSM build.  

tag: cime6.0.45

See here in my build script that I have  a trailing slash for my local variable CASEROOT, which is appended with another string to complete the path to the case.

![Screenshot from 2022-09-13 16-54-26](https://user-images.githubusercontent.com/5891980/190007308-3ab0e5c3-47e9-45d0-80d9-6b75c54cb61f.png)

When I have the trailing slash on that CASEROOT variable the build fails.  When I remove that trailing slash, it builds fine.  From what I can tell, it gets confused during the make calls while processing depencies, first during mct.  Snippet of the mct.bldlog:

```
make -f /home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/Tools/Makefile  -C /home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/gnu/openmpi/debug/nothreads/nuopc/mct CIME_MODEL=cesm  SMP=FALSE CASEROOT="/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13" CASETOOLS="/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/Tools" CIMEROOT="/home/rgknox/Models/CTSM/cime" SRCROOT="/home/rgknox/Models/CTSM" COMP_INTERFACE="nuopc" COMPILER="gnu" DEBUG="TRUE" EXEROOT="/home/rgknox/LandRuns/CTSM//bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld" RUNDIR="/home/rgknox/LandRuns/CTSM//bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/run" INCROOT="/home/rgknox/LandRuns/CTSM//bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/lib/include" LIBROOT="/home/rgknox/LandRuns/CTSM//bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/lib" MACH="eddi" MPILIB="openmpi" NINST_VALUE="c1a1l1" OS="LINUX" PIO_VERSION=2 SHAREDLIBROOT="/home/rgknox/LandRuns/CTSM//bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld" SMP_PRESENT="FALSE" USE_ESMF_LIB="TRUE" USE_MOAB="FALSE" COMP_LND="clm" USE_TRILINOS="FALSE" USE_ALBANY="FALSE" USE_PETSC="FALSE" COMP_NAME=mct /home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/gnu/openmpi/debug/nothreads/nuopc/mct/Makefile.conf
make: Entering directory '/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/gnu/openmpi/debug/nothreads/nuopc/mct'
/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/Tools/mkSrcfiles
cp -f Filepath Deppath
/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/Tools/mkDepends  Deppath Srcfiles > Depends
make: Leaving directory '/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/gnu/openmpi/debug/nothreads/nuopc/mct'
cat: Filepath: No such file or directory
cat: Srcfiles: No such file or directory
make: *** No rule to make target '/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/gnu/openmpi/debug/nothreads/nuopc/mct/Makefile.conf'.  Stop.
ERROR: cat: Filepath: No such file or directory
cat: Srcfiles: No such file or directory
make: *** No rule to make target '/home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/gnu/openmpi/debug/nothread
```


My take was that the perl (or other) scripting was having trouble processing a double slash in the file path.  (But I don't have a good handle on what's going on)


Actually I think that the problem for @rgknox  is in make - the target is 
  /home/rgknox/LandRuns/CTSM/bci-eddi-testdamage-v1.Cceb000a71-Fc263eac6.2022-09-13/bld/gnu/openmpi/debug/nothreads/nuopc/mct/Makefile.conf

Which does not match the same path with a // .

@rgknox I have been unable to reproduce this issue, however I did observe that your use of variable CASEROOT is
inconsistent with the way it is used within the model.   CIME defines CASEROOT as the directory of the case, what you are calling CASE_NAME above.   I think that maybe what is happening is that the Makefile is confusing CASEROOT as you have it defined in the environment and the same variable as defined in env_case.xml - can you try to reproduce your issue again using CASE_ROOT instead of CASEROOT?
@jedwards4b I changed the variable name in my script from CASEROOT to CASE_ROOT (I also tried ROOT_CASE).  I still get a failure if I have a trailing slash on the string, and no failure if I don't.

Here is my full script for reference: 
https://drive.google.com/file/d/1yqSvnHvg26jAZk7pfLseJcU4DCU4dR5T/view?usp=sharing
Including the full script helps.  Fix on the way.

Resolving patch:
diff --git a/CIME/build.py b/CIME/build.py
--- a/CIME/build.py
+++ b/CIME/build.py
@@ -272,7 +272,11 @@ def xml_to_make_variable(case, varname, cmake=False):
         return ""
     if isinstance(varvalue, bool):
         varvalue = stringify_bool(varvalue)
-
+    elif isinstance(varvalue, str):
+        # assure that paths passed to make do not end in / or contain //
+        varvalue = varvalue.replace("//", "/")
+        if varvalue.endswith("/"):
+            varvalue = varvalue[:-1]
     if cmake or isinstance(varvalue, str):
         return '{}{}="{}" '.format("-D" if cmake else "", varname, varvalue)
     else:


Test patch: