From 97193a25ce0c0df6a03cc7d719b0e6e25a37d3a1 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Fri, 17 Mar 2023 11:36:29 +0100 Subject: Mitigation for GitVersion bug when no `=reference` is given (#36159) * ASP-based solver: use satisfies instead of intersects They are semantically equivalent for concrete versions, but the GitVersion.intersects implementation is buggy * Mitigation for git version bug fixes #36134 This commit works around the issue in #36134, by using GitVersion.satisfies instead of GitVersion.intersects There are still underlying issues when trying to infer the "reference version" when no explicit one is given, but: 1. They are not reproducible with our synthetic repo 2. They occur only when the `git.` form of Git version is used Here we just work around the user facing issue and ensure the tests are correct with our synthetic repository. --- lib/spack/spack/solver/asp.py | 3 ++- lib/spack/spack/test/versions.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index b4da31c3c1..ea839e15e1 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -1877,8 +1877,9 @@ class SpackSolverSetup(object): """Define what version_satisfies(...) means in ASP logic.""" for pkg_name, versions in sorted(self.version_constraints): # version must be *one* of the ones the spec allows. + # Also, "possible versions" contain only concrete versions, so satisfies is appropriate allowed_versions = [ - v for v in sorted(self.possible_versions[pkg_name]) if v.intersects(versions) + v for v in sorted(self.possible_versions[pkg_name]) if v.satisfies(versions) ] # This is needed to account for a variable number of diff --git a/lib/spack/spack/test/versions.py b/lib/spack/spack/test/versions.py index f39340c529..d10ade63ca 100644 --- a/lib/spack/spack/test/versions.py +++ b/lib/spack/spack/test/versions.py @@ -771,3 +771,40 @@ def test_version_intersects_satisfies_semantic(lhs_str, rhs_str, expected): assert lhs.intersects(rhs) is rhs.intersects(lhs) assert lhs.satisfies(rhs) is lhs_sat_rhs assert rhs.satisfies(lhs) is rhs_sat_lhs + + +@pytest.mark.parametrize( + "spec_str,tested_intersects,tested_satisfies", + [ + ( + "git-test-commit@git.1.x", + [("@:2", True), ("@:1", True), ("@:0", False), ("@1.3:", False)], + [("@:2", True), ("@:1", True), ("@:0", False), ("@1.3:", False)], + ), + ( + "git-test-commit@git.v2.0", + [("@:2", True), ("@:1", False), ("@:0", False), ("@1.3:", True)], + [("@:2", True), ("@:1", False), ("@:0", False), ("@1.3:", True)], + ), + ], +) +@pytest.mark.skipif(sys.platform == "win32", reason="Not supported on Windows (yet)") +def test_git_versions_without_explicit_reference( + spec_str, + tested_intersects, + tested_satisfies, + mock_git_version_info, + mock_packages, + monkeypatch, +): + repo_path, filename, commits = mock_git_version_info + monkeypatch.setattr( + spack.package_base.PackageBase, "git", "file://%s" % repo_path, raising=False + ) + spec = spack.spec.Spec(spec_str) + + for test_str, expected in tested_intersects: + assert spec.intersects(test_str) is expected, test_str + + for test_str, expected in tested_intersects: + assert spec.intersects(test_str) is expected, test_str -- cgit v1.2.3-60-g2f50