Fix filtering external specs (#44093)

When an include filter on externals is present, implicitly
include libcs.

Also, do not penalize deprecated versions if they come
from externals.
This commit is contained in:
Massimiliano Culpo 2024-05-09 18:50:15 +02:00
parent 189ae4b06e
commit f55224f161
4 changed files with 64 additions and 0 deletions

View file

@ -1649,11 +1649,15 @@ def external_packages(self):
if isinstance(reuse_yaml, typing.Mapping): if isinstance(reuse_yaml, typing.Mapping):
default_include = reuse_yaml.get("include", []) default_include = reuse_yaml.get("include", [])
default_exclude = reuse_yaml.get("exclude", []) default_exclude = reuse_yaml.get("exclude", [])
libc_externals = list(all_libcs())
for source in reuse_yaml.get("from", []): for source in reuse_yaml.get("from", []):
if source["type"] != "external": if source["type"] != "external":
continue continue
include = source.get("include", default_include) include = source.get("include", default_include)
if include:
# Since libcs are implicit externals, we need to implicitly include them
include = include + libc_externals
exclude = source.get("exclude", default_exclude) exclude = source.get("exclude", default_exclude)
spec_filters.append( spec_filters.append(
SpecFilter( SpecFilter(

View file

@ -1424,6 +1424,7 @@ opt_criterion(73, "deprecated versions used").
#minimize{ #minimize{
1@73+Priority,PackageNode 1@73+Priority,PackageNode
: attr("deprecated", PackageNode, _), : attr("deprecated", PackageNode, _),
not external(PackageNode),
build_priority(PackageNode, Priority) build_priority(PackageNode, Priority)
}. }.

View file

@ -2464,6 +2464,7 @@ def test_spec_with_build_dep_from_json(self, tmp_path):
assert s["dttop"].dag_hash() == build_dep.dag_hash() assert s["dttop"].dag_hash() == build_dep.dag_hash()
@pytest.mark.regression("44040") @pytest.mark.regression("44040")
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
def test_exclude_specs_from_reuse(self, monkeypatch): def test_exclude_specs_from_reuse(self, monkeypatch):
"""Tests that we can exclude a spec from reuse when concretizing, and that the spec """Tests that we can exclude a spec from reuse when concretizing, and that the spec
is not added back to the solve as a dependency of another reusable spec. is not added back to the solve as a dependency of another reusable spec.
@ -2503,6 +2504,48 @@ def test_exclude_specs_from_reuse(self, monkeypatch):
for dep in result["dyninst"].traverse(root=False): for dep in result["dyninst"].traverse(root=False):
assert dep.dag_hash() == reused[dep.name].dag_hash() assert dep.dag_hash() == reused[dep.name].dag_hash()
@pytest.mark.regression("44091")
@pytest.mark.parametrize(
"included_externals",
[
["deprecated-versions"],
# Try the empty list, to ensure that in that case everything will be included
# since filtering should happen only when the list is non-empty
[],
],
)
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
def test_include_specs_from_externals_and_libcs(
self, included_externals, mutable_config, tmp_path
):
"""Tests that when we include specs from externals, we always include libcs."""
mutable_config.set(
"packages",
{
"deprecated-versions": {
"externals": [{"spec": "deprecated-versions@1.1.0", "prefix": str(tmp_path)}]
}
},
)
request_str = "deprecated-client"
# When using the external the version is selected even if deprecated
with spack.config.override(
"concretizer:reuse", {"from": [{"type": "external", "include": included_externals}]}
):
result = Spec(request_str).concretized()
assert result["deprecated-versions"].satisfies("@1.1.0")
# When excluding it, we pick the non-deprecated version
with spack.config.override(
"concretizer:reuse",
{"from": [{"type": "external", "exclude": ["deprecated-versions"]}]},
):
result = Spec(request_str).concretized()
assert result["deprecated-versions"].satisfies("@1.0.0")
@pytest.fixture() @pytest.fixture()
def duplicates_test_repository(): def duplicates_test_repository():

View file

@ -0,0 +1,16 @@
# 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 DeprecatedClient(Package):
"""A package depending on another which has deprecated versions."""
homepage = "http://www.example.com"
url = "http://www.example.com/c-1.0.tar.gz"
version("1.1.0", sha256="abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890")
depends_on("deprecated-versions")