From de599e61198012a5c7a6bda37e864609bc8d5754 Mon Sep 17 00:00:00 2001 From: Brian Harring Date: Sun, 25 Dec 2022 14:50:50 -0800 Subject: [PATCH] Force stable sorting of /etc/portage/* files loading. Specifically, alphanumeric sorting; a '00' should always be parsed before an '01' or 'a'. The ordering must be stable so that globals- in a 00 file- can be overridden per package via other files. If there is no stable ordering forced on how the order of files read, then this isn't supported. Closes: https://github.com/pkgcore/pkgcore/issues/385 Signed-off-by: Brian Harring Signed-off-by: Arthur Zamarin --- src/pkgcore/ebuild/domain.py | 3 +- tests/ebuild/test_domain.py | 56 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/ebuild/test_domain.py diff --git a/src/pkgcore/ebuild/domain.py b/src/pkgcore/ebuild/domain.py index 4e33e0fc9..7e76f1112 100644 --- a/src/pkgcore/ebuild/domain.py +++ b/src/pkgcore/ebuild/domain.py @@ -132,7 +132,8 @@ def generate_filter(masks, unmasks, *extra): def _read_config_file(path): """Read all the data files under a given path.""" try: - for fs_obj in iter_scan(path, follow_symlinks=True): + # sort based on location by default; this is to ensure 00 is before 01, and before a + for fs_obj in sorted(iter_scan(path, follow_symlinks=True)): if not fs_obj.is_reg or "/." in fs_obj.location: continue for lineno, line in iter_read_bash( diff --git a/tests/ebuild/test_domain.py b/tests/ebuild/test_domain.py new file mode 100644 index 000000000..6629cfb9a --- /dev/null +++ b/tests/ebuild/test_domain.py @@ -0,0 +1,56 @@ +from unittest import mock + +import pytest + +from pkgcore.ebuild import domain as domain_mod +from pkgcore.ebuild import profiles +from pkgcore.fs.livefs import iter_scan +from pkgcore.restrictions import packages + +from .test_profiles import profile_mixin + + +class TestDomain: + @pytest.fixture(autouse=True, scope="function") + def _setup(self, tmp_path_factory): + self.confdir = tmp_path_factory.mktemp("conf") + self.rootdir = tmp_path_factory.mktemp("root") + self.pmixin = profile_mixin() + self.profile_base = tmp_path_factory.mktemp("profiles") + self.profile1 = self.profile_base / "profile1" + self.pmixin.mk_profile(self.profile_base, str(self.profile1)) + + def mk_domain(self): + return domain_mod.domain( + profiles.OnDiskProfile(str(self.profile_base), "profile1"), + [], + [], + ROOT=self.rootdir, + config_dir=self.confdir, + ) + + def test_sorting(self): + """assert that configuration files are read in alphanum ordering""" + cdir = self.confdir / "package.use" + cdir.mkdir() + + # assert the base state; no files, no content. + assert () == self.mk_domain().pkg_use + + open(cdir / "00", "w").write("*/* X") + open(cdir / "01", "w").write("*/* -X Y") + + # Force the returned ordering to be reversed; this is to assert that + # the domain forces a sort. + orig_func = iter_scan + + def rev_iter_scan(*args, **kwargs): + return iter(sorted(orig_func(*args, **kwargs), reverse=True)) + + with mock.patch( + "pkgcore.fs.livefs.iter_scan", side_effect=rev_iter_scan + ), mock.patch("pkgcore.ebuild.domain.iter_scan", side_effect=rev_iter_scan): + assert ( + (packages.AlwaysTrue, ((), ("X",))), + (packages.AlwaysTrue, (("X",), ("Y",))), + ) == self.mk_domain().pkg_use