proj/pkgcore/pkgcore:master commit in: examples/

"Arthur Zamarin" <[email protected]>
Newsgroups gmane.linux.gentoo.cvs
Message-ID <1786820146.dc36e5dfb66592551f4fc73f34b09af85d0b6acd.arthurzam@gentoo>
commit:     dc36e5dfb66592551f4fc73f34b09af85d0b6acd
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Sat Aug 15 18:55:46 2026 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Sat Aug 15 18:55:46 2026 +0000
URL:        https://gitweb.gentoo.org/proj/pkgcore/pkgcore.git/commit/?id=dc36e5df

verify_at_done: add support for keywording bugs

Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 examples/verify_at_done.py | 93 ++++++++++++++++------------------------------
 1 file changed, 31 insertions(+), 62 deletions(-)

diff --git a/examples/verify_at_done.py b/examples/verify_at_done.py
index e8df79500..bfddf2d70 100755
--- a/examples/verify_at_done.py
+++ b/examples/verify_at_done.py
@@ -2,20 +2,15 @@
 
 """Go over all open stabilization or keywording bugs, and check for done bugs."""
 
+import os
 import sys
 
-from pkgcore.bugzilla import (
-    BugCategory,
-    BugQuery,
-    BugzillaError,
-    Component,
-    FlagStatus,
-)
+from pkgcore.bugzilla import Bug, BugQuery, Component, FlagStatus
 from pkgcore.bugzilla.apikey import BugzillaClientArgs
-from pkgcore.bugzilla.pkglist import ALL_KEYWORDS, NO_KEYWORDS, SAME_KEYWORDS
-from pkgcore.util import commandline
+from pkgcore.ebuild.keywording import PackageListDoneAlready, PackageMatchException
+from pkgcore.util.commandline import ArgumentParser, Tool
 
-argparser = commandline.ArgumentParser(version=False, description=__doc__)
+argparser = ArgumentParser(version=False, description=__doc__)
 BugzillaClientArgs.mangle_argparser(argparser)
 
 QUERY = (
@@ -24,69 +19,43 @@ QUERY = (
     & BugQuery.flag("sanity-check", FlagStatus.GRANTED)
 )
 
-UNEXPANDED = frozenset((ALL_KEYWORDS, SAME_KEYWORDS))
-
 
 @argparser.bind_final_check
 def check_args(parser, namespace):
-    namespace.repo = namespace.domain.ebuild_repos_raw
-    namespace.known_arches = frozenset().union(
-        *(repo.known_arches for repo in namespace.repo)
-    )
-
-
-def requested_arches(entry, cc_arches):
-    """The arches a package list line asks for.
-
-    A line carrying no keywords of its own inherits the whole CC list, which is
-    how nattka reads it too.
-    """
-    keywords = frozenset(x.lstrip("~") for x in entry.keywords)
-    if NO_KEYWORDS in keywords:
-        return frozenset()
-    return keywords or frozenset(cc_arches)
-
-
-def pending_packages(repo, bug, cc_arches):
-    """Map each requested arch to the packages it still has to stabilize.
-
-    Returns None when the bug can't be judged, either because an atom matches
-    nothing in the repo or because the package list still holds unexpanded
-    keyword shorthands. Concluding from a partial view is how an arch gets told
-    it is done while a package the repo never matched is still waiting on it.
-    """
-    pending: dict[str, list] = {}
-    for entry in bug.package_list.entries:
-        if entry.pkg is None:
-            continue
-        if UNEXPANDED & frozenset(entry.keywords):
-            return None
-        if not (pkgs := tuple(repo.itermatch(entry.pkg))):
-            return None
-        for arch in requested_arches(entry, cc_arches):
-            pending.setdefault(arch, []).extend(pkgs)
-    return pending
+    # a request is resolved against one repo: the one being worked in
+    cwd = os.getcwd()
+    repo = namespace.domain.find_repo(cwd, config=namespace.config, configure=False)
+    if repo is None:
+        parser.error(f"not inside an ebuild repository: {cwd}")
+    namespace.repo = repo
+
+
+def remaining_arches(repo, bug: Bug) -> set[str]:
+    try:
+        return {
+            arch
+            for _, keywords in bug.match_packages(repo, only_new=True)
+            for arch in keywords
+        }
+    except PackageListDoneAlready:
+        # every package is keyworded already, so nobody is waiting on anything
+        return set()
 
 
 @argparser.bind_main_func
 def main(options, out, err):
     for bug in options.bugzilla.search(QUERY).values():
-        # the heuristic for keywording is wrong, skip those for now
-        if bug.category is BugCategory.KEYWORDREQ:
+        if not (cc_arches := bug.arches(options.repo.known_arches)):
             continue
-        cc_arches = bug.arches(options.known_arches)
         try:
-            pending = pending_packages(options.repo, bug, cc_arches)
-        except BugzillaError as exc:
-            err.write(err.fg("red"), f">>> {exc}", err.reset)
-            continue
-        if not pending:
+            remaining = remaining_arches(options.repo, bug)
+        except PackageMatchException as exc:
+            # a bug nobody can resolve as written says nothing about being done
+            err.write(err.fg("red"), f">>> bug {bug.id}: {exc}", err.reset)
             continue
 
         for arch in cc_arches:
-            if not (pkgs := pending.get(arch)):
-                continue
-            if all(arch in pkg.keywords for pkg in pkgs):
+            if arch not in remaining:
                 out.write(
                     out.fg("yellow"),
                     f"{bug.url}, cc: {arch}, all packages are done",
@@ -94,8 +63,8 @@ def main(options, out, err):
                     " -> ",
                     f"nattka resolve -a {arch} {bug.id}",
                 )
+                out.write("  bug summary: ", bug.summary)
 
 
 if __name__ == "__main__":
-    tool = commandline.Tool(argparser)
-    sys.exit(tool())
+    sys.exit(Tool(argparser)())
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.