commit:     d00711f2d6cbae14a57088ef78caa3daf72069aa
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Mon Aug 28 17:43:08 2023 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Mon Aug 28 17:43:08 2023 +0000
URL:        
https://gitweb.gentoo.org/proj/pkgcore/pkgcore.git/commit/?id=d00711f2

ebuild.repository: add support for stabilization groups

This is a special metadata files that can be used to group packages
for stabilization bugs.

Resolves: https://github.com/pkgcore/pkgcore/issues/411
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 src/pkgcore/ebuild/repository.py | 24 ++++++++++++++++++++++++
 tests/ebuild/test_repository.py  | 25 +++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/src/pkgcore/ebuild/repository.py b/src/pkgcore/ebuild/repository.py
index 164aa0c97..50f115cc1 100644
--- a/src/pkgcore/ebuild/repository.py
+++ b/src/pkgcore/ebuild/repository.py
@@ -16,6 +16,7 @@ from snakeoil import chksum, klass
 from snakeoil.bash import read_dict
 from snakeoil.containers import InvertedContains
 from snakeoil.data_source import local_source
+from snakeoil.fileutils import readlines_utf8
 from snakeoil.mappings import ImmutableDict
 from snakeoil.obj import make_kls
 from snakeoil.osutils import listdir_dirs, listdir_files, pjoin
@@ -34,7 +35,9 @@ from ..restrictions import packages
 from ..util import packages as pkgutils
 from . import cpv, digest, ebd, ebuild_src
 from . import eclass_cache as eclass_cache_mod
+from . import errors as ebuild_errors
 from . import processor, repo_objs, restricts
+from .atom import atom
 from .eapi import get_eapi
 
 
@@ -670,6 +673,27 @@ class UnconfiguredTree(prototype.tree):
             pkg_deprecated.update(repo.config.pkg_deprecated)
         return packages.OrRestriction(*pkg_deprecated)
 
+    @klass.jit_attr
+    def stabilization_groups(self):
+        """Return a mapping of stabilization groups to packages."""
+        stabilization_groups = {}
+        base_dir = pjoin(self.location, "metadata", "stabilization-groups")
+        for dirname, _dirs, files in os.walk(base_dir):
+            dirbase = dirname.removeprefix(base_dir)
+            for file in files:
+                pkgs = set()
+                for lineno, line in enumerate(readlines_utf8(pjoin(dirname, 
file)), 1):
+                    try:
+                        if line := line.split("#", maxsplit=1)[0].strip():
+                            pkgs.add(atom(line))
+                    except ebuild_errors.MalformedAtom as exc:
+                        logger.error(
+                            f"{dirname.removeprefix(self.location)}/{file}, 
line {lineno}: parsing error: {exc}"
+                        )
+                group = f"{dirbase}/{file}".removeprefix("/")
+                stabilization_groups[group] = frozenset(pkgs)
+        return ImmutableDict(stabilization_groups)
+
     def _regen_operation_helper(self, **kwds):
         return _RegenOpHelper(
             self,

diff --git a/tests/ebuild/test_repository.py b/tests/ebuild/test_repository.py
index 85a248d8d..fceb70b37 100644
--- a/tests/ebuild/test_repository.py
+++ b/tests/ebuild/test_repository.py
@@ -199,6 +199,31 @@ class TestUnconfiguredTree:
             atom("<just/newer-than-42"),
         }
 
+    def test_stabilization_groups(self, tmp_path, caplog):
+        base = tmp_path / "metadata/stabilization-groups"
+        (base / "pkgcore").mkdir(parents=True)
+        (base / "gentoo").write_text(
+            textwrap.dedent(
+                """\
+                    # some text here
+                        dev-python/pkgcore
+                    dev-python/pytest # comment
+                    @bad_atom@
+                """
+            )
+        )
+        (base / "pkgcore" / "snakeoil").write_text("""dev-python/snakeoil # 
comment""")
+        mirrors = self.mk_tree(tmp_path).stabilization_groups
+        assert set(mirrors.keys()) == {"gentoo", "pkgcore/snakeoil"}
+        assert set(mirrors["gentoo"]) == {
+            atom("dev-python/pkgcore"),
+            atom("dev-python/pytest"),
+        }
+        assert set(mirrors["pkgcore/snakeoil"]) == {
+            atom("dev-python/snakeoil"),
+        }
+        assert "line 4: parsing error:" in caplog.text
+
 
 class TestSlavedTree(TestUnconfiguredTree):
     def mk_tree(self, path, *args, **kwds):

Reply via email to