summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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
3 files changed, 56 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()