ASP-based solver: account for deprecated versions (#23491)
fixes #22351 The ASP-based solver now accounts for the presence in the DAG of deprecated versions and tries to minimize their number at highest priority.
This commit is contained in:
parent
b768d7bb09
commit
fc2ac099cd
@ -411,6 +411,7 @@ def __init__(self):
|
||||
self.gen = None # set by setup()
|
||||
self.possible_versions = {}
|
||||
self.versions_in_package_py = {}
|
||||
self.deprecated_versions = {}
|
||||
self.versions_from_externals = {}
|
||||
self.possible_virtuals = None
|
||||
self.possible_compilers = []
|
||||
@ -481,6 +482,11 @@ def pkg_version_rules(self, pkg):
|
||||
for i, v in enumerate(most_to_least_preferred):
|
||||
self.gen.fact(fn.version_declared(pkg.name, v, i))
|
||||
|
||||
# Declare deprecated versions for this package, if any
|
||||
deprecated = self.deprecated_versions[pkg.name]
|
||||
for v in sorted(deprecated):
|
||||
self.gen.fact(fn.deprecated_version(pkg.name, v))
|
||||
|
||||
def spec_versions(self, spec):
|
||||
"""Return list of clauses expressing spec's version constraints."""
|
||||
spec = specify(spec)
|
||||
@ -1020,12 +1026,16 @@ def build_version_dict(self, possible_pkgs, specs):
|
||||
self.possible_versions = collections.defaultdict(set)
|
||||
self.versions_in_package_py = collections.defaultdict(set)
|
||||
self.versions_from_externals = collections.defaultdict(set)
|
||||
self.deprecated_versions = collections.defaultdict(set)
|
||||
|
||||
for pkg_name in possible_pkgs:
|
||||
pkg = spack.repo.get(pkg_name)
|
||||
for v in pkg.versions:
|
||||
for v, version_info in pkg.versions.items():
|
||||
self.versions_in_package_py[pkg_name].add(v)
|
||||
self.possible_versions[pkg_name].add(v)
|
||||
deprecated = version_info.get('deprecated', False)
|
||||
if deprecated:
|
||||
self.deprecated_versions[pkg_name].add(v)
|
||||
|
||||
for spec in specs:
|
||||
for dep in spec.traverse():
|
||||
@ -1553,6 +1563,10 @@ def reorder_flags(self):
|
||||
check_same_flags(spec.compiler_flags, flags)
|
||||
spec.compiler_flags.update(flags)
|
||||
|
||||
def deprecated(self, pkg, version):
|
||||
msg = 'using "{0}@{1}" which is a deprecated version'
|
||||
tty.warn(msg.format(pkg, version))
|
||||
|
||||
def build_specs(self, function_tuples):
|
||||
# Functions don't seem to be in particular order in output. Sort
|
||||
# them here so that directives that build objects (like node and
|
||||
|
@ -19,6 +19,9 @@ version_declared(Package, Version) :- version_declared(Package, Version, _).
|
||||
1 { version(Package, Version) : version_declared(Package, Version) } 1
|
||||
:- node(Package).
|
||||
|
||||
% If we select a deprecated version, mark the package as deprecated
|
||||
deprecated(Package, Version) :- version(Package, Version), deprecated_version(Package, Version).
|
||||
|
||||
possible_version_weight(Package, Weight)
|
||||
:- version(Package, Version), version_declared(Package, Version, Weight),
|
||||
not preferred_version_declared(Package, Version, _).
|
||||
@ -37,6 +40,7 @@ version_satisfies(Package, Constraint)
|
||||
|
||||
#defined preferred_version_declared/3.
|
||||
#defined version_satisfies/3.
|
||||
#defined deprecated_version/2.
|
||||
|
||||
%-----------------------------------------------------------------------------
|
||||
% Spec conditions and imposed constraints
|
||||
@ -696,6 +700,11 @@ no_flags(Package, FlagType)
|
||||
% 2. a `#minimize{ 0@2 : #true }.` statement that ensures the criterion
|
||||
% is displayed (clingo doesn't display sums over empty sets by default)
|
||||
|
||||
% Minimize the number of deprecated versions being used
|
||||
opt_criterion(16, "deprecated versions used").
|
||||
#minimize{ 0@16 : #true }.
|
||||
#minimize{ 1@16,Package : deprecated(Package, _)}.
|
||||
|
||||
% The highest priority is to minimize the:
|
||||
% 1. Version weight
|
||||
% 2. Number of variants with a non default value, if not set
|
||||
|
@ -28,3 +28,6 @@
|
||||
|
||||
% names of optimization criteria
|
||||
#show opt_criterion/2.
|
||||
|
||||
% deprecated packages
|
||||
#show deprecated/2.
|
||||
|
@ -1228,3 +1228,19 @@ def test_multivalued_variants_from_cli(self, spec_str, expected_dict):
|
||||
|
||||
for constraint, value in expected_dict.items():
|
||||
assert s.satisfies(constraint) == value
|
||||
|
||||
@pytest.mark.regression('22351')
|
||||
@pytest.mark.parametrize('spec_str,expected', [
|
||||
# Version 1.1.0 is deprecated and should not be selected, unless we
|
||||
# explicitly asked for that
|
||||
('deprecated-versions', ['deprecated-versions@1.0.0']),
|
||||
('deprecated-versions@1.1.0', ['deprecated-versions@1.1.0']),
|
||||
])
|
||||
def test_deprecated_versions_not_selected(self, spec_str, expected):
|
||||
if spack.config.get('config:concretizer') == 'original':
|
||||
pytest.xfail('Known failure of the original concretizer')
|
||||
|
||||
s = Spec(spec_str).concretized()
|
||||
|
||||
for abstract_spec in expected:
|
||||
assert abstract_spec in s
|
||||
|
@ -0,0 +1,12 @@
|
||||
# Copyright 2013-2021 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)
|
||||
class DeprecatedVersions(Package):
|
||||
"""Package with the most recent version deprecated"""
|
||||
|
||||
homepage = "http://www.example.com"
|
||||
url = "http://www.example.com/c-1.0.tar.gz"
|
||||
|
||||
version('1.1.0', '0123456789abcdef0123456789abcdef', deprecated=True)
|
||||
version('1.0.0', '0123456789abcdef0123456789abcdef')
|
Loading…
Reference in New Issue
Block a user