Repository: spack/spack

Issue:
Git version derived from ref incorrect for >=10.x.y
### Steps to reproduce

For example:
```console
$ spack spec -U intel-xed@git.v2023.07.09
Input spec
--------------------------------
 -   intel-xed@git.v2023.07.09=3.07.09
...snip...
```

### Error message

The automatically derived version for this ref is truncated, it should be `@git.v2023.07.09=2023.09.09`. instead of `...=3.09.09`. This seems to occur for any ref with a semver version >=10.x.y (i.e. only the last digit of the major version number is kept).

### Information on your system

* **Spack:** 0.21.0.dev0 (fc1996e0fa288852023bc7b6646e4e829476498d)
* **Python:** 3.10.12
* **Platform:** linux-ubuntu22.04-zen2
* **Concretizer:** clingo

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have searched the issues of this repo and believe this is not a duplicate
- [X] I have run the failing commands in debug mode and reported the output


Discussion:

Resolving patch:
diff --git a/lib/spack/spack/version/git_ref_lookup.py b/lib/spack/spack/version/git_ref_lookup.py
--- a/lib/spack/spack/version/git_ref_lookup.py
+++ b/lib/spack/spack/version/git_ref_lookup.py
@@ -22,11 +22,16 @@
 from .lookup import AbstractRefLookup
 
 # regular expression for semantic versioning
-SEMVER_REGEX = re.compile(
-    ".+(?P<semver>([0-9]+)[.]([0-9]+)[.]([0-9]+)"
-    "(?:-([0-9A-Za-z-]+(?:[.][0-9A-Za-z-]+)*))?"
-    "(?:[+][0-9A-Za-z-]+)?)"
-)
+_VERSION_CORE = r"\d+\.\d+\.\d+"
+_IDENT = r"[0-9A-Za-z-]+"
+_SEPARATED_IDENT = rf"{_IDENT}(?:\.{_IDENT})*"
+_PRERELEASE = rf"\-{_SEPARATED_IDENT}"
+_BUILD = rf"\+{_SEPARATED_IDENT}"
+_SEMVER = rf"{_VERSION_CORE}(?:{_PRERELEASE})?(?:{_BUILD})?"
+
+# clamp on the end, so versions like v1.2.3-rc1 will match
+# without the leading 'v'.
+SEMVER_REGEX = re.compile(rf"{_SEMVER}$")
 
 
 class GitRefLookup(AbstractRefLookup):
@@ -186,11 +191,10 @@ def lookup_ref(self, ref) -> Tuple[Optional[str], int]:
                         commit_to_version[tag_commit] = v
                         break
                 else:
-                    # try to parse tag to copare versions spack does not know
-                    match = SEMVER_REGEX.match(tag)
+                    # try to parse tag to compare versions spack does not know
+                    match = SEMVER_REGEX.search(tag)
                     if match:
-                        semver = match.groupdict()["semver"]
-                        commit_to_version[tag_commit] = semver
+                        commit_to_version[tag_commit] = match.group()
 
             ancestor_commits = []
             for tag_commit in commit_to_version:


Test patch:
diff --git a/lib/spack/spack/test/versions.py b/lib/spack/spack/test/versions.py
--- a/lib/spack/spack/test/versions.py
+++ b/lib/spack/spack/test/versions.py
@@ -26,6 +26,7 @@
     is_git_version,
     ver,
 )
+from spack.version.git_ref_lookup import SEMVER_REGEX
 
 
 def assert_ver_lt(a, b):
@@ -976,3 +977,25 @@ def test_unresolvable_git_versions_error(config, mock_packages):
         # The package exists, but does not have a git property set. When dereferencing
         # the version, we should get VersionLookupError, not a generic AttributeError.
         spack.spec.Spec(f"git-test-commit@{'a' * 40}").version.ref_version
+
+
+@pytest.mark.parametrize(
+    "tag,expected",
+    [
+        ("v100.2.3", "100.2.3"),
+        ("v1.2.3", "1.2.3"),
+        ("v1.2.3-pre.release+build.1", "1.2.3-pre.release+build.1"),
+        ("v1.2.3+build.1", "1.2.3+build.1"),
+        ("v1.2.3+build_1", None),
+        ("v1.2.3-pre.release", "1.2.3-pre.release"),
+        ("v1.2.3-pre_release", None),
+        ("1.2.3", "1.2.3"),
+        ("1.2.3.", None),
+    ],
+)
+def test_semver_regex(tag, expected):
+    result = SEMVER_REGEX.search(tag)
+    if expected is None:
+        assert result is None
+    else:
+        assert result.group() == expected