summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/solver/asp.py17
-rw-r--r--lib/spack/spack/solver/concretize.lp1
-rw-r--r--lib/spack/spack/test/concretize.py42
-rw-r--r--var/spack/repos/builtin.mock/packages/git-ref-package/package.py41
4 files changed, 97 insertions, 4 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index dc1aa5fea0..2701ea25fd 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -116,6 +116,8 @@ class Provenance(enum.IntEnum):
PACKAGE_PY = enum.auto()
# An installed spec
INSTALLED = enum.auto()
+ # lower provenance for installed git refs so concretizer prefers StandardVersion installs
+ INSTALLED_GIT_VERSION = enum.auto()
# A runtime injected from another package (e.g. a compiler)
RUNTIME = enum.auto()
@@ -2072,7 +2074,7 @@ class SpackSolverSetup:
# best possible, so they're guaranteed to be used preferentially.
version = s.versions.concrete
- if version is None or any(v == version for v in self.possible_versions[s.name]):
+ if version is None or (any((v == version) for v in self.possible_versions[s.name])):
continue
if require_checksum and not _is_checksummed_git_version(version):
@@ -2386,9 +2388,16 @@ class SpackSolverSetup:
# - Add OS to possible OS's
for dep in spec.traverse():
self.possible_versions[dep.name].add(dep.version)
- self.declared_versions[dep.name].append(
- DeclaredVersion(version=dep.version, idx=0, origin=Provenance.INSTALLED)
- )
+ if isinstance(dep.version, vn.GitVersion):
+ self.declared_versions[dep.name].append(
+ DeclaredVersion(
+ version=dep.version, idx=0, origin=Provenance.INSTALLED_GIT_VERSION
+ )
+ )
+ else:
+ self.declared_versions[dep.name].append(
+ DeclaredVersion(version=dep.version, idx=0, origin=Provenance.INSTALLED)
+ )
self.possible_oses.add(dep.os)
def define_concrete_input_specs(self, specs, possible):
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index 20bcd46ad6..8c270e1702 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -256,6 +256,7 @@ possible_version_weight(node(ID, Package), Weight)
:- attr("version", node(ID, Package), Version),
version_weight(node(ID, Package), Weight),
not pkg_fact(Package, version_declared(Version, Weight, "installed")),
+ not pkg_fact(Package, version_declared(Version, Weight, "installed_git_version")),
not build(node(ID, Package)),
internal_error("Build version weight used for reused package").
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index b1cd35bff9..547e3209eb 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -3043,3 +3043,45 @@ def test_spec_filters(specs, include, exclude, expected):
factory=lambda: specs, is_usable=lambda x: True, include=include, exclude=exclude
)
assert f.selected_specs() == expected
+
+
+@pytest.mark.only_clingo("clingo only reuse feature being tested")
+@pytest.mark.regression("38484")
+def test_git_ref_version_can_be_reused(
+ install_mockery_mutable_config, do_not_check_runtimes_on_reuse
+):
+ first_spec = spack.spec.Spec("git-ref-package@git.2.1.5=2.1.5~opt").concretized()
+ first_spec.package.do_install(fake=True, explicit=True)
+
+ with spack.config.override("concretizer:reuse", True):
+ # reproducer of the issue is that spack will solve when there is a change to the base spec
+ second_spec = spack.spec.Spec("git-ref-package@git.2.1.5=2.1.5+opt").concretized()
+ assert second_spec.dag_hash() != first_spec.dag_hash()
+ # we also want to confirm that reuse actually works so leave variant off to
+ # let solver reuse
+ third_spec = spack.spec.Spec("git-ref-package@git.2.1.5=2.1.5")
+ assert first_spec.satisfies(third_spec)
+ third_spec.concretize()
+ assert third_spec.dag_hash() == first_spec.dag_hash()
+
+
+@pytest.mark.only_clingo("clingo only reuse feature being tested")
+@pytest.mark.parametrize("standard_version", ["2.0.0", "2.1.5", "2.1.6"])
+def test_reuse_prefers_standard_over_git_versions(
+ standard_version, install_mockery_mutable_config, do_not_check_runtimes_on_reuse
+):
+ """
+ order matters in this test. typically reuse would pick the highest versioned installed match
+ but we want to prefer the standard version over git ref based versions
+ so install git ref last and ensure it is not picked up by reuse
+ """
+ standard_spec = spack.spec.Spec(f"git-ref-package@{standard_version}").concretized()
+ standard_spec.package.do_install(fake=True, explicit=True)
+
+ git_spec = spack.spec.Spec("git-ref-package@git.2.1.5=2.1.5").concretized()
+ git_spec.package.do_install(fake=True, explicit=True)
+
+ with spack.config.override("concretizer:reuse", True):
+ test_spec = spack.spec.Spec("git-ref-package@2").concretized()
+ assert git_spec.dag_hash() != test_spec.dag_hash()
+ assert standard_spec.dag_hash() == test_spec.dag_hash()
diff --git a/var/spack/repos/builtin.mock/packages/git-ref-package/package.py b/var/spack/repos/builtin.mock/packages/git-ref-package/package.py
new file mode 100644
index 0000000000..21fe10e818
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/git-ref-package/package.py
@@ -0,0 +1,41 @@
+# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+from spack.package import *
+
+
+class GitRefPackage(AutotoolsPackage):
+ """
+ dummy package copied from zlib-ng
+ """
+
+ homepage = "https://github.com/dummy/dummy"
+ url = "https://github.com/dummy/dummy/archive/2.0.0.tar.gz"
+ git = "https://github.com/dummy/dummy.git"
+
+ version("2.1.6", sha256="a5d504c0d52e2e2721e7e7d86988dec2e290d723ced2307145dedd06aeb6fef2")
+ version("2.1.5", sha256="3f6576971397b379d4205ae5451ff5a68edf6c103b2f03c4188ed7075fbb5f04")
+ version("2.1.4", sha256="a0293475e6a44a3f6c045229fe50f69dc0eebc62a42405a51f19d46a5541e77a")
+ version(
+ "2.1.3",
+ sha256="d20e55f89d71991c59f1c5ad1ef944815e5850526c0d9cd8e504eaed5b24491a",
+ deprecated=True,
+ )
+ version(
+ "2.1.2",
+ sha256="383560d6b00697c04e8878e26c0187b480971a8bce90ffd26a5a7b0f7ecf1a33",
+ deprecated=True,
+ )
+ version("2.0.7", sha256="6c0853bb27738b811f2b4d4af095323c3d5ce36ceed6b50e5f773204fb8f7200")
+ version("2.0.0", sha256="86993903527d9b12fc543335c19c1d33a93797b3d4d37648b5addae83679ecd8")
+
+ variant("compat", default=True, description="Enable compatibility API")
+ variant("opt", default=True, description="Enable optimizations")
+ variant("shared", default=True, description="Build shared library")
+ variant("pic", default=True, description="Enable position-independent code (PIC)")
+
+ conflicts("+shared~pic")
+
+ variant("new_strategies", default=True, description="Enable new deflate strategies")