Skip to content

Commit efc3d5c

Browse files
committed
bugs: expand --filter-stablereqs across every package in a target
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
1 parent 1e7cea5 commit efc3d5c

3 files changed

Lines changed: 87 additions & 16 deletions

File tree

‎NEWS.rst‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ pkgdev 0.2.18 (unreleased)
1616
- bugs: a bugzilla error while filing now names the bug and packages being
1717
filed or modified (Arthur Zamarin, #229)
1818

19+
- bugs: fix ``--filter-stablereqs`` collapsing a target which matches several
20+
packages down to a single one (Arthur Zamarin)
21+
1922
pkgdev 0.2.17 (2026-08-14)
2023
--------------------------
2124

‎src/pkgdev/scripts/pkgdev_bugs.py‎

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ def __call__(self, parser, namespace, values, option_string=None):
133133
134134
# ... limited to those with an active StableRequest result
135135
pkgdev bugs --find-by-maintainer foo@gentoo.org --filter-stablereqs
136+
137+
# file stablereq bugs for all packages inside category "dev-libs" with an active StableRequest
138+
pkgdev bugs --filter-stablereqs "dev-libs/*"
136139
""",
137140
)
138141
BugzillaApiKey.mangle_argparser(bugs)
@@ -676,6 +679,21 @@ def _find_dependencies(self, pkg: package, keywords: set[str], stable: bool = Tr
676679
)
677680
yield from results.items()
678681

682+
def _stablereqs(self, pkgset) -> list[tuple[atom, list[package]]]:
683+
"""The stablereq of every package in the set, as a target of its own."""
684+
per_pkg: dict[str, list[package]] = defaultdict(list)
685+
for pkg in pkgset:
686+
per_pkg[pkg.key].append(pkg)
687+
688+
found = []
689+
# the check reads the versions of a single package, so feed one at a time
690+
for pkgs in per_pkg.values():
691+
for res in self.stablereq_check.feed(sorted(pkgs)):
692+
if isinstance(res, stablereq.StableRequest):
693+
found.append((atom(f"={res.category}/{res.package}-{res.version}"), pkgs))
694+
break
695+
return found
696+
679697
def load_targets(self, targets: list[tuple[str, object, frozenset[str]]]):
680698
result = []
681699
search_repo = self.options.search_repo
@@ -684,23 +702,23 @@ def load_targets(self, targets: list[tuple[str, object, frozenset[str]]]):
684702
try:
685703
pkgset = search_repo.match(target)
686704
if self.options.filter_stablereqs:
687-
for res in self.stablereq_check.feed(sorted(pkgset)):
688-
if isinstance(res, stablereq.StableRequest):
689-
target = atom(f"={res.category}/{res.package}-{res.version}")
690-
break
691-
else: # no stablereq
705+
# a target may match many packages, each with its own stablereq
706+
found = self._stablereqs(pkgset)
707+
else:
708+
found = [(target, pkgset)]
709+
710+
for restrict, candidates in found:
711+
if masked.match(restrict):
712+
self.err.write(
713+
self.err.fg("yellow"),
714+
f"Target {restrict} is masked, skipping",
715+
self.err.reset,
716+
)
692717
continue
693-
if masked.match(target):
694-
self.err.write(
695-
self.err.fg("yellow"),
696-
f"Target {target} is masked, skipping",
697-
self.err.reset,
698-
)
699-
continue
700-
match = self.find_best_match([target], pkgset, False)
701-
result.append(match)
702-
if arches:
703-
self.target_arches[match] = arches
718+
match = self.find_best_match([restrict], candidates, False)
719+
result.append(match)
720+
if arches:
721+
self.target_arches[match] = arches
704722
except (ValueError, IndexError):
705723
bugs.error(f"Restriction {target} has no match in repository", status=3)
706724
self.targets = tuple(result)

‎tests/scripts/test_pkgdev_bugs.py‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pytest
77
from pkgcore.bugzilla import BugCategory, BugzillaError
88
from pkgcore.ebuild.atom import atom
9+
from pkgcore.util import parserestrict
910

1011
from pkgdev.scripts import pkgdev_bugs as bugs
1112

@@ -598,3 +599,52 @@ def test_dependency_update_error_names_the_bug(self, repo, bugzilla_cassette):
598599
with pytest.raises(BugzillaError) as excinfo:
599600
node.file_bug(bugzilla_cassette.client(api_key="API"), frozenset(), (), None)
600601
assert "adding dependencies to bug 200" in str(excinfo.value)
602+
603+
604+
class TestFilterStablereqs:
605+
"""A target matching many packages has a stablereq per package, not one."""
606+
607+
def mk_stablereq_graph(self, repo, wanted):
608+
graph = mk_graph(repo)
609+
graph.options.filter_stablereqs = True
610+
fed = []
611+
612+
class Check:
613+
def feed(self, pkgs):
614+
fed.append(tuple({pkg.key for pkg in pkgs}))
615+
for pkg in reversed(pkgs):
616+
if pkg.versioned_atom.cpvstr in wanted:
617+
yield bugs.stablereq.StableRequest(
618+
slot=pkg.slot, keywords=pkg.keywords, age=40, pkg=pkg
619+
)
620+
621+
graph.stablereq_check = Check()
622+
return graph, fed
623+
624+
def test_every_package_in_the_target_is_checked(self, repo):
625+
for name in ("a", "b", "c"):
626+
repo.create_ebuild(f"cat/{name}-1", KEYWORDS=["amd64"])
627+
repo.create_ebuild(f"cat/{name}-2", KEYWORDS=["~amd64"])
628+
repo.sync()
629+
graph, fed = self.mk_stablereq_graph(repo, {"cat/a-2", "cat/c-2"})
630+
631+
graph.load_targets([(None, parserestrict.parse_match("cat/*"), frozenset())])
632+
633+
assert sorted(str(pkg.versioned_atom) for pkg in graph.targets) == ["=cat/a-2", "=cat/c-2"]
634+
# one package per feed, as the check reads a single package's versions
635+
assert fed and all(len(keys) == 1 for keys in fed)
636+
637+
def test_target_without_any_stablereq_is_dropped(self, repo):
638+
repo.create_ebuild("cat/a-1", KEYWORDS=["amd64"])
639+
repo.sync()
640+
graph, _ = self.mk_stablereq_graph(repo, set())
641+
graph.load_targets([(None, parserestrict.parse_match("cat/*"), frozenset())])
642+
assert graph.targets == ()
643+
644+
def test_single_package_target_is_unchanged(self, repo):
645+
repo.create_ebuild("cat/a-1", KEYWORDS=["amd64"])
646+
repo.create_ebuild("cat/a-2", KEYWORDS=["~amd64"])
647+
repo.sync()
648+
graph, _ = self.mk_stablereq_graph(repo, {"cat/a-2"})
649+
graph.load_targets([(None, parserestrict.parse_match("cat/a"), frozenset())])
650+
assert [str(pkg.versioned_atom) for pkg in graph.targets] == ["=cat/a-2"]

0 commit comments

Comments
 (0)