Repository: spack/spack

Issue:
Installation issue: dollar signs `$` in paths for several packages, e.g. gmake@=4.4.1%gcc@=12.2.0
### Steps to reproduce the issue

```console
$ spack install --overwrite gmake@=4.4.1%gcc@=12.2.0
```


### Error message

See the last two lines. Second-last line has the path with dollar signs `$`, last line with the `Warning` is because the package is missing from the expected directory, without `$`. The error is that gmake exists at the unexpected directory with `$` symbols, so it can't be found.

<details><summary>Error message</summary>
<pre>
$ spack install --overwrite gmake@=4.4.1%gcc@=12.2.0
==> The following package specs will be reinstalled:

-- linux-rocky8-zen2 / gcc@=12.2.0 ------------------------------
kqkpdnx gmake@4.4.1%gcc \~guile build_system=autotools
==> Do you want to proceed? [y/N] y
==> Installing gmake-4.4.1-kqkpdnxusciojbahb3up4ot5xr4wdrwb
==> No binary for gmake-4.4.1-kqkpdnxusciojbahb3up4ot5xr4wdrwb found: installing from source
==> Using cached archive: /opt/ohpc/admin/spack/github/spack/var/spack/cache/_source-cache/archive/dd/dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3.tar.gz
==> No patches needed for gmake
==> gmake: Executing phase: 'autoreconf'
==> gmake: Executing phase: 'configure'
==> gmake: Executing phase: 'build'
==> gmake: Executing phase: 'install'
==> Warning: Module file /opt/ohpc/pub/spack/develop/share/spack/modules/linux-rocky8-zen2/gmake-4.4.1-gcc-12.2.0-kqkpdnx exists and will not be overwritten
==> Warning: Module file /opt/ohpc/pub/spack/develop/share/spack/lmod/linux-rocky8-x86_64/gcc/12.2.0/gmake/4.4.1-kqkpdnx.lua exists and will not be overwritten
==> gmake: Successfully installed gmake-4.4.1-kqkpdnxusciojbahb3up4ot5xr4wdrwb
  Stage: 0.04s.  Autoreconf: 0.00s.  Configure: 6.71s.  Build: 6.61s.  Install: 0.00s.  Total: 13.45s
[+] /opt/ohpc/pub/spack/develop/opt/spack/$linux-rocky8-zen2/$gcc-$12.2.0/$gmake-$4.4.1-$kqkpdnxusciojbahb3up4ot5xr4wdrwb
==> Warning: gmake@4.4.1%gcc@=12.2.0~guile build_system=autotools arch=linux-rocky8-zen2/kqkpdnx is being updated in the database with prefix /opt/ohpc/pub/spack/develop/opt/spack/linux-rocky8-zen2/gcc-12.2.0/gmake-4.4.1-kqkpdnxusciojbahb3up4ot5xr4wdrwb, but this directory does not contain an installation of the spec, due to: Install prefix /opt/ohpc/pub/spack/develop/opt/spack/linux-rocky8-zen2/gcc-12.2.0/gmake-4.4.1-kqkpdnxusciojbahb3up4ot5xr4wdrwb does not exist.
</pre></details>


### Information on your system

* **Spack:** 0.20.0.dev0 (2dcc55d6c524048e56f7231b755d133af79cdf7b)
* **Python:** 3.11.1
* **Platform:** linux-rocky8-zen2
* **Concretizer:** clingo


### Additional information

The first three lines from `spack-built-out.txt` have the issue.

```
==> gmake: Executing phase: 'autoreconf'
==> gmake: Executing phase: 'configure'
==> [2023-05-10-17:09:50.041111] '/tmp/root/spack-stage/spack-stage-gmake-4.4.1-kqkpdnxusciojbahb3up4ot5xr4wdrwb/spack-src/configure' '--prefix=/opt/ohpc/pub/spack/develop/opt/spack/$linux-rocky8-zen2/$gcc-$12.2.0/$gmake-$4.4.1-$kqkpdnxusciojbahb3up4ot5xr4wdrwb' '--without-guile' '--disable-nls'
```

These `$` are also seen in the `spack-build-env.txt`
```
SPACK_RPATH_DIRS="/opt/ohpc/pub/spack/develop/opt/spack/$linux-rocky8-zen2/$gcc-$12.2.0/$gmake-$4.4.1-$kqkpdnxusciojbahb3up4ot5xr4wdrwb/lib:/opt/ohpc/pub/spack/develop/opt/spack/$linux-rocky8-zen2/$gcc-$12.2.0/$gmake-$4.4.1-$kqkpdnxusciojbahb3up4ot5xr4wdrwb/lib64"; export SPACK_RPATH_DIRS
```


Maintainer: @haampie 

I think the issue isn't related to `gmake` though, I also see it with other packages, but not all packages.

Also attached is my config YAML (renamed to `.txt` due to file type upload error), which only differs from `defaults/config.yaml` at `config > install_tree > root`.

[spack-build-env.txt](https://github.com/spack/spack/files/11443626/spack-build-env.txt)
[spack-build-out.txt](https://github.com/spack/spack/files/11443627/spack-build-out.txt)
[config.yaml.txt](https://github.com/spack/spack/files/11443677/config.yaml.txt)

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have run `spack maintainers <name-of-the-package>` and **@mentioned** any maintainers
- [X] I have uploaded the build log and environment files
- [X] I have searched the issues of this repo and believe this is not a duplicate


Discussion:
Ping. 

Any workaround? Would be very helpful to get this fixed. Thanks!
Possibly due to the outdated Python 3.6.8 on the server. Simply writing `prefix.bin.gmake` above this line
https://github.com/spack/spack/blob/45838cee0b8b01ad999b459ed6d19e37686859c0/var/spack/repos/builtin/packages/gmake/package.py#L79

removed the `$` symbols from the path -- not sure why.

Resolving patch:
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -213,6 +213,19 @@ def __call__(self, match):
     return clr.colorize(re.sub(_SEPARATORS, insert_color(), str(spec)) + "@.")
 
 
+OLD_STYLE_FMT_RE = re.compile(r"\${[A-Z]+}")
+
+
+def ensure_modern_format_string(fmt: str) -> None:
+    """Ensure that the format string does not contain old ${...} syntax."""
+    result = OLD_STYLE_FMT_RE.search(fmt)
+    if result:
+        raise SpecFormatStringError(
+            f"Format string `{fmt}` contains old syntax `{result.group(0)}`. "
+            "This is no longer supported."
+        )
+
+
 @lang.lazy_lexicographic_ordering
 class ArchSpec:
     """Aggregate the target platform, the operating system and the target microarchitecture."""
@@ -4362,6 +4375,7 @@ def format(self, format_string=DEFAULT_FORMAT, **kwargs):
                 that accepts a string and returns another one
 
         """
+        ensure_modern_format_string(format_string)
         color = kwargs.get("color", False)
         transform = kwargs.get("transform", {})
 


Test patch:
diff --git a/lib/spack/spack/test/spec_semantics.py b/lib/spack/spack/test/spec_semantics.py
--- a/lib/spack/spack/test/spec_semantics.py
+++ b/lib/spack/spack/test/spec_semantics.py
@@ -1528,3 +1528,9 @@ def test_edge_equality_does_not_depend_on_virtual_order():
     assert edge1 == edge2
     assert tuple(sorted(edge1.virtuals)) == edge1.virtuals
     assert tuple(sorted(edge2.virtuals)) == edge1.virtuals
+
+
+def test_old_format_strings_trigger_error(default_mock_concretization):
+    s = Spec("a").concretized()
+    with pytest.raises(SpecFormatStringError):
+        s.format("${PACKAGE}-${VERSION}-${HASH}")