ASP-based solver: fix rules on version weights selection (#31153)
* ASP: sort and deduplicate version weights from installed specs * Pick version weights according to provenance * Add unit test
This commit is contained in:
parent
392b548312
commit
267358a799
@ -748,7 +748,13 @@ def key_fn(version):
|
|||||||
|
|
||||||
pkg = packagize(pkg)
|
pkg = packagize(pkg)
|
||||||
declared_versions = self.declared_versions[pkg.name]
|
declared_versions = self.declared_versions[pkg.name]
|
||||||
most_to_least_preferred = sorted(declared_versions, key=key_fn)
|
partially_sorted_versions = sorted(set(declared_versions), key=key_fn)
|
||||||
|
|
||||||
|
most_to_least_preferred = []
|
||||||
|
for _, group in itertools.groupby(partially_sorted_versions, key=key_fn):
|
||||||
|
most_to_least_preferred.extend(list(sorted(
|
||||||
|
group, reverse=True, key=lambda x: spack.version.ver(x.version)
|
||||||
|
)))
|
||||||
|
|
||||||
for weight, declared_version in enumerate(most_to_least_preferred):
|
for weight, declared_version in enumerate(most_to_least_preferred):
|
||||||
self.gen.fact(fn.version_declared(
|
self.gen.fact(fn.version_declared(
|
||||||
|
@ -107,10 +107,28 @@ possible_version_weight(Package, Weight)
|
|||||||
:- version(Package, Version),
|
:- version(Package, Version),
|
||||||
version_declared(Package, Version, Weight).
|
version_declared(Package, Version, Weight).
|
||||||
|
|
||||||
version_weight(Package, Weight)
|
% we can't use the weight for an external version if we don't use the
|
||||||
|
% corresponding external spec.
|
||||||
|
:- version(Package, Version),
|
||||||
|
version_weight(Package, Weight),
|
||||||
|
version_declared(Package, Version, Weight, "external"),
|
||||||
|
not external(Package).
|
||||||
|
|
||||||
|
% we can't use a weight from an installed spec if we are building it
|
||||||
|
% and vice-versa
|
||||||
|
:- version(Package, Version),
|
||||||
|
version_weight(Package, Weight),
|
||||||
|
version_declared(Package, Version, Weight, "installed"),
|
||||||
|
build(Package).
|
||||||
|
|
||||||
|
:- version(Package, Version),
|
||||||
|
version_weight(Package, Weight),
|
||||||
|
not version_declared(Package, Version, Weight, "installed"),
|
||||||
|
not build(Package).
|
||||||
|
|
||||||
|
1 { version_weight(Package, Weight) : version_declared(Package, Version, Weight) } 1
|
||||||
:- version(Package, Version),
|
:- version(Package, Version),
|
||||||
node(Package),
|
node(Package).
|
||||||
Weight = #min{W : version_declared(Package, Version, W)}.
|
|
||||||
|
|
||||||
% node_version_satisfies implies that exactly one of the satisfying versions
|
% node_version_satisfies implies that exactly one of the satisfying versions
|
||||||
% is the package's version, and vice versa.
|
% is the package's version, and vice versa.
|
||||||
|
@ -1753,3 +1753,36 @@ def test_misleading_error_message_on_version(self, mutable_database):
|
|||||||
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError,
|
with pytest.raises(spack.solver.asp.UnsatisfiableSpecError,
|
||||||
match="'dep-with-variants' satisfies '@999'"):
|
match="'dep-with-variants' satisfies '@999'"):
|
||||||
solver.driver.solve(setup, [root_spec], reuse=reusable_specs)
|
solver.driver.solve(setup, [root_spec], reuse=reusable_specs)
|
||||||
|
|
||||||
|
@pytest.mark.regression('31148')
|
||||||
|
def test_version_weight_and_provenance(self):
|
||||||
|
"""Test package preferences during coconcretization."""
|
||||||
|
import spack.solver.asp
|
||||||
|
if spack.config.get('config:concretizer') == 'original':
|
||||||
|
pytest.skip('Original concretizer cannot reuse')
|
||||||
|
|
||||||
|
reusable_specs = [
|
||||||
|
spack.spec.Spec(spec_str).concretized()
|
||||||
|
for spec_str in ('b@0.9', 'b@1.0')
|
||||||
|
]
|
||||||
|
root_spec = spack.spec.Spec('a foobar=bar')
|
||||||
|
|
||||||
|
with spack.config.override("concretizer:reuse", True):
|
||||||
|
solver = spack.solver.asp.Solver()
|
||||||
|
setup = spack.solver.asp.SpackSolverSetup()
|
||||||
|
result = solver.driver.solve(
|
||||||
|
setup, [root_spec], reuse=reusable_specs, out=sys.stdout
|
||||||
|
)
|
||||||
|
# The result here should have a single spec to build ('a')
|
||||||
|
# and it should be using b@1.0 with a version badness of 2
|
||||||
|
# The provenance is:
|
||||||
|
# version_declared("b","1.0",0,"package_py").
|
||||||
|
# version_declared("b","0.9",1,"package_py").
|
||||||
|
# version_declared("b","1.0",2,"installed").
|
||||||
|
# version_declared("b","0.9",3,"installed").
|
||||||
|
for criterion in [
|
||||||
|
(1, None, 'number of packages to build (vs. reuse)'),
|
||||||
|
(2, 0, 'version badness')
|
||||||
|
]:
|
||||||
|
assert criterion in result.criteria
|
||||||
|
assert result.specs[0].satisfies('^b@1.0')
|
||||||
|
Loading…
Reference in New Issue
Block a user