commit:     03df2f52b71ec03e84047409b4564ae27b7c4a46
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Sat Oct  1 14:10:02 2022 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Tue Oct  4 10:43:06 2022 +0000
URL:        
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=03df2f52

ProfilesCheck: new check for UnmatchedProfilePackageUnmask

Add missing check from repoman, for unmatched unmask of atom in
`package.mask` files. This checks for any unmask of package, which isn't
masked in parent profiles.

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

 src/pkgcheck/checks/profiles.py                    | 49 ++++++++++++++++++++--
 .../UnmatchedProfilePackageUnmask/expected.json    |  1 +
 .../UnmatchedProfilePackageUnmask/fix.patch        |  7 ++++
 testdata/repos/profiledir/profiles/profiles.desc   |  1 +
 .../profiledir/profiles/unmatched_unmasks/eapi     |  1 +
 .../profiles/unmatched_unmasks/package.mask        |  2 +
 .../profiledir/profiles/unmatched_unmasks/parent   |  1 +
 7 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/src/pkgcheck/checks/profiles.py b/src/pkgcheck/checks/profiles.py
index d825730f..73e2898e 100644
--- a/src/pkgcheck/checks/profiles.py
+++ b/src/pkgcheck/checks/profiles.py
@@ -28,6 +28,23 @@ class UnknownProfilePackage(results.ProfilesResult, 
results.Warning):
         return f'{self.path!r}: unknown package: {self.atom!r}'
 
 
+class UnmatchedProfilePackageUnmask(results.ProfilesResult, results.Warning):
+    """The profile's files include a package.unmask (or similar) entry which
+    negates a non-existent mask, i.e. it undoes a mask which doesn't exist in
+    the parent profile.
+
+    No atoms matching this entry were found in the parent profile to unmask."""
+
+    def __init__(self, path, atom):
+        super().__init__()
+        self.path = path
+        self.atom = str(atom)
+
+    @property
+    def desc(self):
+        return f'{self.path!r}: unmask of not masked package: {self.atom!r}'
+
+
 class UnknownProfilePackageUse(results.ProfilesResult, results.Warning):
     """Profile files include entries with USE flags that aren't used on any 
matching packages."""
 
@@ -129,7 +146,8 @@ class ProfilesCheck(Check):
     _source = sources.ProfilesRepoSource
     required_addons = (addons.UseAddon, addons.KeywordsAddon)
     known_results = frozenset([
-        UnknownProfilePackage, UnknownProfilePackageUse, UnknownProfileUse,
+        UnknownProfilePackage, UnmatchedProfilePackageUnmask,
+        UnknownProfilePackageUse, UnknownProfileUse,
         UnknownProfilePackageKeywords, UnknownProfileUseExpand,
         ProfileWarning, ProfileError,
     ])
@@ -145,11 +163,19 @@ class ProfilesCheck(Check):
         self.profiles_dir = repo.config.profiles_base
         self.use_expand_groups = frozenset(x.upper() for x in 
repo.config.use_expand_desc)
 
-        local_iuse = {use for pkg, (use, desc) in repo.config.use_local_desc}
+        local_iuse = {use for _pkg, (use, _desc) in repo.config.use_local_desc}
         self.available_iuse = frozenset(
             local_iuse | use_addon.global_iuse |
             use_addon.global_iuse_expand | use_addon.global_iuse_implicit)
 
+    @staticmethod
+    def traverse_parents_tree(profile):
+        def _traverse(node):
+            for parent in node.parents:
+                yield parent
+                yield from _traverse(parent)
+        return set(_traverse(profile))
+
     @verify_files(('parent', 'parents'),
                   ('eapi', 'eapi'))
     def _pull_attr(self, *args):
@@ -160,7 +186,7 @@ class ProfilesCheck(Check):
     def _deprecated(self, filename, node, vals):
         # make sure replacement profile exists
         if vals is not None:
-            replacement, msg = vals
+            replacement, _msg = vals
             try:
                 addons.profiles.ProfileNode(pjoin(self.profiles_dir, 
replacement))
             except profiles_mod.ProfileError:
@@ -195,7 +221,6 @@ class ProfilesCheck(Check):
                         pjoin(node.name, filename), unknown_enabled)
 
     @verify_files(('packages', 'packages'),
-                  ('package.mask', 'masks'),
                   ('package.unmask', 'unmasks'),
                   ('package.deprecated', 'pkg_deprecated'))
     def _pkg_atoms(self, filename, node, vals):
@@ -203,6 +228,22 @@ class ProfilesCheck(Check):
             if not self.search_repo.match(x):
                 yield UnknownProfilePackage(pjoin(node.name, filename), x)
 
+    @verify_files(('package.mask', 'masks'),)
+    def _pkg_masks(self, filename, node, vals):
+        all_parents = self.traverse_parents_tree(node)
+        all_masked = set().union(*(masked[1]
+            for p in all_parents if (masked := p.masks)))
+
+        unmasked, masked = vals
+        for x in masked:
+            if not self.search_repo.match(x):
+                yield UnknownProfilePackage(pjoin(node.name, filename), x)
+        for x in unmasked:
+            if not self.search_repo.match(x):
+                yield UnknownProfilePackage(pjoin(node.name, filename), x)
+            elif x not in all_masked:
+                yield UnmatchedProfilePackageUnmask(pjoin(node.name, 
filename), x)
+
     @verify_files(('package.use', 'pkg_use'),
                   ('package.use.force', 'pkg_use_force'),
                   ('package.use.stable.force', 'pkg_use_stable_force'),

diff --git 
a/testdata/data/repos/profiledir/ProfilesCheck/UnmatchedProfilePackageUnmask/expected.json
 
b/testdata/data/repos/profiledir/ProfilesCheck/UnmatchedProfilePackageUnmask/expected.json
new file mode 100644
index 00000000..2f162524
--- /dev/null
+++ 
b/testdata/data/repos/profiledir/ProfilesCheck/UnmatchedProfilePackageUnmask/expected.json
@@ -0,0 +1 @@
+{"__class__": "UnmatchedProfilePackageUnmask", "path": 
"unmatched_unmasks/package.mask", "atom": "cat/pkg4"}

diff --git 
a/testdata/data/repos/profiledir/ProfilesCheck/UnmatchedProfilePackageUnmask/fix.patch
 
b/testdata/data/repos/profiledir/ProfilesCheck/UnmatchedProfilePackageUnmask/fix.patch
new file mode 100644
index 00000000..5c385d94
--- /dev/null
+++ 
b/testdata/data/repos/profiledir/ProfilesCheck/UnmatchedProfilePackageUnmask/fix.patch
@@ -0,0 +1,7 @@
+diff -Naur profiledir/profiles/unmatched_unmasks/package.mask 
fixed/profiles/unmatched_unmasks/package.mask
+index fc6201bc..73b38bc7 100644
+--- profiledir/profiles/unmatched_unmasks/package.mask
++++ fixed/profiles/unmatched_unmasks/package.mask
+@@ -1,2 +1 @@
+--cat/pkg4
+ -cat/pkg3

diff --git a/testdata/repos/profiledir/profiles/profiles.desc 
b/testdata/repos/profiledir/profiles/profiles.desc
index 0cdb97be..ea649fd9 100644
--- a/testdata/repos/profiledir/profiles/profiles.desc
+++ b/testdata/repos/profiledir/profiles/profiles.desc
@@ -5,6 +5,7 @@ amd64 nonexistent exp
 
 amd64 unknown_pkgs exp
 amd64 unknown_kwds exp
+amd64 unmatched_unmasks exp
 
 amd64 unknown_use exp
 amd64 unknown_use/unknown_stable_use exp

diff --git a/testdata/repos/profiledir/profiles/unmatched_unmasks/eapi 
b/testdata/repos/profiledir/profiles/unmatched_unmasks/eapi
new file mode 100644
index 00000000..7f8f011e
--- /dev/null
+++ b/testdata/repos/profiledir/profiles/unmatched_unmasks/eapi
@@ -0,0 +1 @@
+7

diff --git a/testdata/repos/profiledir/profiles/unmatched_unmasks/package.mask 
b/testdata/repos/profiledir/profiles/unmatched_unmasks/package.mask
new file mode 100644
index 00000000..fc6201bc
--- /dev/null
+++ b/testdata/repos/profiledir/profiles/unmatched_unmasks/package.mask
@@ -0,0 +1,2 @@
+-cat/pkg4
+-cat/pkg3

diff --git a/testdata/repos/profiledir/profiles/unmatched_unmasks/parent 
b/testdata/repos/profiledir/profiles/unmatched_unmasks/parent
new file mode 100644
index 00000000..e4166365
--- /dev/null
+++ b/testdata/repos/profiledir/profiles/unmatched_unmasks/parent
@@ -0,0 +1 @@
+../unknown_pkgs

Reply via email to