proj/pkgcore/pkgdev:main commit in: /, tests/scripts/, src/pkgdev/scripts/
"Arthur Zamarin" <[email protected]>
| Newsgroups | gmane.linux.gentoo.cvs |
|---|---|
| Message-ID | <1786821294.efc3d5cd5028bba3d07fb63786fb136deaad98ae.arthurzam@gentoo> |
commit: efc3d5cd5028bba3d07fb63786fb136deaad98ae
Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Sat Aug 15 19:14:54 2026 +0000
Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Sat Aug 15 19:14:54 2026 +0000
URL: https://gitweb.gentoo.org/proj/pkgcore/pkgdev.git/commit/?id=efc3d5cd
bugs: expand --filter-stablereqs across every package in a target
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>
NEWS.rst | 3 +++
src/pkgdev/scripts/pkgdev_bugs.py | 50 ++++++++++++++++++++++++++-------------
tests/scripts/test_pkgdev_bugs.py | 50 +++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+), 16 deletions(-)
diff --git a/NEWS.rst b/NEWS.rst
index d338b23..2bda22f 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -16,6 +16,9 @@ pkgdev 0.2.18 (unreleased)
- bugs: a bugzilla error while filing now names the bug and packages being
filed or modified (Arthur Zamarin, #229)
+- bugs: fix ``--filter-stablereqs`` collapsing a target which matches several
+ packages down to a single one (Arthur Zamarin)
+
pkgdev 0.2.17 (2026-08-14)
--------------------------
diff --git a/src/pkgdev/scripts/pkgdev_bugs.py b/src/pkgdev/scripts/pkgdev_bugs.py
index 86fda45..cc649c5 100644
--- a/src/pkgdev/scripts/pkgdev_bugs.py
+++ b/src/pkgdev/scripts/pkgdev_bugs.py
@@ -133,6 +133,9 @@ bugs = ArgumentParser(
# ... limited to those with an active StableRequest result
pkgdev bugs --find-by-maintainer [email protected] --filter-stablereqs
+
+ # file stablereq bugs for all packages inside category "dev-libs" with an active StableRequest
+ pkgdev bugs --filter-stablereqs "dev-libs/*"
""",
)
BugzillaApiKey.mangle_argparser(bugs)
@@ -676,6 +679,21 @@ class DependencyGraph:
)
yield from results.items()
+ def _stablereqs(self, pkgset) -> list[tuple[atom, list[package]]]:
+ """The stablereq of every package in the set, as a target of its own."""
+ per_pkg: dict[str, list[package]] = defaultdict(list)
+ for pkg in pkgset:
+ per_pkg[pkg.key].append(pkg)
+
+ found = []
+ # the check reads the versions of a single package, so feed one at a time
+ for pkgs in per_pkg.values():
+ for res in self.stablereq_check.feed(sorted(pkgs)):
+ if isinstance(res, stablereq.StableRequest):
+ found.append((atom(f"={res.category}/{res.package}-{res.version}"), pkgs))
+ break
+ return found
+
def load_targets(self, targets: list[tuple[str, object, frozenset[str]]]):
result = []
search_repo = self.options.search_repo
@@ -684,23 +702,23 @@ class DependencyGraph:
try:
pkgset = search_repo.match(target)
if self.options.filter_stablereqs:
- for res in self.stablereq_check.feed(sorted(pkgset)):
- if isinstance(res, stablereq.StableRequest):
- target = atom(f"={res.category}/{res.package}-{res.version}")
- break
- else: # no stablereq
+ # a target may match many packages, each with its own stablereq
+ found = self._stablereqs(pkgset)
+ else:
+ found = [(target, pkgset)]
+
+ for restrict, candidates in found:
+ if masked.match(restrict):
+ self.err.write(
+ self.err.fg("yellow"),
+ f"Target {restrict} is masked, skipping",
+ self.err.reset,
+ )
continue
- if masked.match(target):
- self.err.write(
- self.err.fg("yellow"),
- f"Target {target} is masked, skipping",
- self.err.reset,
- )
- continue
- match = self.find_best_match([target], pkgset, False)
- result.append(match)
- if arches:
- self.target_arches[match] = arches
+ match = self.find_best_match([restrict], candidates, False)
+ result.append(match)
+ if arches:
+ self.target_arches[match] = arches
except (ValueError, IndexError):
bugs.error(f"Restriction {target} has no match in repository", status=3)
self.targets = tuple(result)
diff --git a/tests/scripts/test_pkgdev_bugs.py b/tests/scripts/test_pkgdev_bugs.py
index e560ab8..6a51f4d 100644
--- a/tests/scripts/test_pkgdev_bugs.py
+++ b/tests/scripts/test_pkgdev_bugs.py
@@ -6,6 +6,7 @@ from types import SimpleNamespace
import pytest
from pkgcore.bugzilla import BugCategory, BugzillaError
from pkgcore.ebuild.atom import atom
+from pkgcore.util import parserestrict
from pkgdev.scripts import pkgdev_bugs as bugs
@@ -598,3 +599,52 @@ class TestFilingErrorContext:
with pytest.raises(BugzillaError) as excinfo:
node.file_bug(bugzilla_cassette.client(api_key="API"), frozenset(), (), None)
assert "adding dependencies to bug 200" in str(excinfo.value)
+
+
+class TestFilterStablereqs:
+ """A target matching many packages has a stablereq per package, not one."""
+
+ def mk_stablereq_graph(self, repo, wanted):
+ graph = mk_graph(repo)
+ graph.options.filter_stablereqs = True
+ fed = []
+
+ class Check:
+ def feed(self, pkgs):
+ fed.append(tuple({pkg.key for pkg in pkgs}))
+ for pkg in reversed(pkgs):
+ if pkg.versioned_atom.cpvstr in wanted:
+ yield bugs.stablereq.StableRequest(
+ slot=pkg.slot, keywords=pkg.keywords, age=40, pkg=pkg
+ )
+
+ graph.stablereq_check = Check()
+ return graph, fed
+
+ def test_every_package_in_the_target_is_checked(self, repo):
+ for name in ("a", "b", "c"):
+ repo.create_ebuild(f"cat/{name}-1", KEYWORDS=["amd64"])
+ repo.create_ebuild(f"cat/{name}-2", KEYWORDS=["~amd64"])
+ repo.sync()
+ graph, fed = self.mk_stablereq_graph(repo, {"cat/a-2", "cat/c-2"})
+
+ graph.load_targets([(None, parserestrict.parse_match("cat/*"), frozenset())])
+
+ assert sorted(str(pkg.versioned_atom) for pkg in graph.targets) == ["=cat/a-2", "=cat/c-2"]
+ # one package per feed, as the check reads a single package's versions
+ assert fed and all(len(keys) == 1 for keys in fed)
+
+ def test_target_without_any_stablereq_is_dropped(self, repo):
+ repo.create_ebuild("cat/a-1", KEYWORDS=["amd64"])
+ repo.sync()
+ graph, _ = self.mk_stablereq_graph(repo, set())
+ graph.load_targets([(None, parserestrict.parse_match("cat/*"), frozenset())])
+ assert graph.targets == ()
+
+ def test_single_package_target_is_unchanged(self, repo):
+ repo.create_ebuild("cat/a-1", KEYWORDS=["amd64"])
+ repo.create_ebuild("cat/a-2", KEYWORDS=["~amd64"])
+ repo.sync()
+ graph, _ = self.mk_stablereq_graph(repo, {"cat/a-2"})
+ graph.load_targets([(None, parserestrict.parse_match("cat/a"), frozenset())])
+ assert [str(pkg.versioned_atom) for pkg in graph.targets] == ["=cat/a-2"]