@@ -28,6 +28,23 @@ def desc(self):
2828 return f'{ self .path !r} : unknown package: { self .atom !r} '
2929
3030
31+ class UnmatchedProfilePackageUnmask (results .ProfilesResult , results .Warning ):
32+ """The profile's files include a package.unmask (or similar) entry which
33+ negates a non-existent mask, i.e. it undoes a mask which doesn't exist in
34+ the parent profile.
35+
36+ No atoms matching this entry were found in the parent profile to unmask."""
37+
38+ def __init__ (self , path , atom ):
39+ super ().__init__ ()
40+ self .path = path
41+ self .atom = str (atom )
42+
43+ @property
44+ def desc (self ):
45+ return f'{ self .path !r} : unmask of not masked package: { self .atom !r} '
46+
47+
3148class UnknownProfilePackageUse (results .ProfilesResult , results .Warning ):
3249 """Profile files include entries with USE flags that aren't used on any matching packages."""
3350
@@ -129,7 +146,8 @@ class ProfilesCheck(Check):
129146 _source = sources .ProfilesRepoSource
130147 required_addons = (addons .UseAddon , addons .KeywordsAddon )
131148 known_results = frozenset ([
132- UnknownProfilePackage , UnknownProfilePackageUse , UnknownProfileUse ,
149+ UnknownProfilePackage , UnmatchedProfilePackageUnmask ,
150+ UnknownProfilePackageUse , UnknownProfileUse ,
133151 UnknownProfilePackageKeywords , UnknownProfileUseExpand ,
134152 ProfileWarning , ProfileError ,
135153 ])
@@ -145,11 +163,19 @@ def __init__(self, *args, use_addon, keywords_addon):
145163 self .profiles_dir = repo .config .profiles_base
146164 self .use_expand_groups = frozenset (x .upper () for x in repo .config .use_expand_desc )
147165
148- local_iuse = {use for pkg , (use , desc ) in repo .config .use_local_desc }
166+ local_iuse = {use for _pkg , (use , _desc ) in repo .config .use_local_desc }
149167 self .available_iuse = frozenset (
150168 local_iuse | use_addon .global_iuse |
151169 use_addon .global_iuse_expand | use_addon .global_iuse_implicit )
152170
171+ @staticmethod
172+ def traverse_parents_tree (profile ):
173+ def _traverse (node ):
174+ for parent in node .parents :
175+ yield parent
176+ yield from _traverse (parent )
177+ return set (_traverse (profile ))
178+
153179 @verify_files (('parent' , 'parents' ),
154180 ('eapi' , 'eapi' ))
155181 def _pull_attr (self , * args ):
@@ -160,7 +186,7 @@ def _pull_attr(self, *args):
160186 def _deprecated (self , filename , node , vals ):
161187 # make sure replacement profile exists
162188 if vals is not None :
163- replacement , msg = vals
189+ replacement , _msg = vals
164190 try :
165191 addons .profiles .ProfileNode (pjoin (self .profiles_dir , replacement ))
166192 except profiles_mod .ProfileError :
@@ -195,14 +221,29 @@ def _use(self, filename, node, vals):
195221 pjoin (node .name , filename ), unknown_enabled )
196222
197223 @verify_files (('packages' , 'packages' ),
198- ('package.mask' , 'masks' ),
199224 ('package.unmask' , 'unmasks' ),
200225 ('package.deprecated' , 'pkg_deprecated' ))
201226 def _pkg_atoms (self , filename , node , vals ):
202227 for x in iflatten_instance (vals , atom_cls ):
203228 if not self .search_repo .match (x ):
204229 yield UnknownProfilePackage (pjoin (node .name , filename ), x )
205230
231+ @verify_files (('package.mask' , 'masks' ),)
232+ def _pkg_masks (self , filename , node , vals ):
233+ all_parents = self .traverse_parents_tree (node )
234+ all_masked = set ().union (* (masked [1 ]
235+ for p in all_parents if (masked := p .masks )))
236+
237+ unmasked , masked = vals
238+ for x in masked :
239+ if not self .search_repo .match (x ):
240+ yield UnknownProfilePackage (pjoin (node .name , filename ), x )
241+ for x in unmasked :
242+ if not self .search_repo .match (x ):
243+ yield UnknownProfilePackage (pjoin (node .name , filename ), x )
244+ elif x not in all_masked :
245+ yield UnmatchedProfilePackageUnmask (pjoin (node .name , filename ), x )
246+
206247 @verify_files (('package.use' , 'pkg_use' ),
207248 ('package.use.force' , 'pkg_use_force' ),
208249 ('package.use.stable.force' , 'pkg_use_stable_force' ),
0 commit comments