blob: 1e9623906028a2593928b7ce1bca849db93d5ca8 [file] [log] [blame]
# -*- coding:utf-8 -*-
'''keywords.py
Perform KEYWORDS related checks
'''
from repoman.modules.scan.scanbase import ScanBase
class KeywordChecks(ScanBase):
'''Perform checks on the KEYWORDS of an ebuild'''
def __init__(self, **kwargs):
'''
@param qatracker: QATracker instance
@param options: argparse options instance
'''
super(KeywordChecks, self).__init__(**kwargs)
self.qatracker = kwargs.get('qatracker')
self.options = kwargs.get('options')
self.repo_metadata = kwargs.get('repo_metadata')
self.profiles = kwargs.get('profiles')
self.slot_keywords = {}
def prepare(self, **kwargs):
'''Prepare the checks for the next package.'''
self.slot_keywords = {}
self.dropped_keywords = {}
return False
def check(self, **kwargs):
'''Perform the check.
@param pkg: Package in which we check (object).
@param xpkg: Package in which we check (string).
@param ebuild: Ebuild which we check (object).
@param y_ebuild: Ebuild which we check (string).
@param ebuild_archs: Just the architectures (no prefixes) of the ebuild.
@param changed: Changes instance
@returns: dictionary
'''
pkg = kwargs.get('pkg').get()
xpkg =kwargs.get('xpkg')
ebuild = kwargs.get('ebuild').get()
y_ebuild = kwargs.get('y_ebuild')
changed = kwargs.get('changed')
if not self.options.straight_to_stable:
self._checkAddedWithStableKeywords(
xpkg, ebuild, y_ebuild, ebuild.keywords, changed)
self._checkForDroppedKeywords(pkg, ebuild, ebuild.archs)
self._checkForInvalidKeywords(ebuild, xpkg, y_ebuild)
self._checkForMaskLikeKeywords(xpkg, y_ebuild, ebuild.keywords)
self.slot_keywords[pkg.slot].update(ebuild.archs)
return False
def check_dropped_keywords(self, **kwargs):
'''Report on any dropped keywords for the latest ebuild in a slot
@returns: boolean
'''
for ebuild, arches in self.dropped_keywords.values():
if arches:
self.qatracker.add_error(
"KEYWORDS.dropped", "%s: %s" % (
ebuild,
" ".join(sorted(arches))))
return False
@staticmethod
def _isKeywordStable(keyword):
return not keyword.startswith("~") and not keyword.startswith("-")
def _checkAddedWithStableKeywords(
self, package, ebuild, y_ebuild, keywords, changed):
catdir, pkgdir = package.split("/")
stable_keywords = list(filter(self._isKeywordStable, keywords))
if stable_keywords:
if ebuild.ebuild_path in changed.new_ebuilds and catdir != "virtual":
stable_keywords.sort()
self.qatracker.add_error(
"KEYWORDS.stable",
"%s/%s.ebuild added with stable keywords: %s" %
(package, y_ebuild, " ".join(stable_keywords)))
def _checkForDroppedKeywords(
self, pkg, ebuild, ebuild_archs):
previous_keywords = self.slot_keywords.get(pkg.slot)
if previous_keywords is None:
self.slot_keywords[pkg.slot] = set()
elif ebuild_archs and "*" not in ebuild_archs and not ebuild.live_ebuild:
self.slot_keywords[pkg.slot].update(ebuild_archs)
dropped_keywords = previous_keywords.difference(ebuild_archs)
self.dropped_keywords[pkg.slot] = (ebuild.relative_path, { arch for arch in dropped_keywords})
def _checkForInvalidKeywords(self, ebuild, xpkg, y_ebuild):
myuse = ebuild.keywords
for mykey in myuse:
if mykey not in ("-*", "*", "~*"):
myskey = mykey
if not self._isKeywordStable(myskey[:1]):
myskey = myskey[1:]
if myskey not in self.repo_metadata['kwlist']:
self.qatracker.add_error("KEYWORDS.invalid",
"%s/%s.ebuild: %s" % (xpkg, y_ebuild, mykey))
elif myskey not in self.profiles:
self.qatracker.add_error(
"KEYWORDS.invalid",
"%s/%s.ebuild: %s (profile invalid)"
% (xpkg, y_ebuild, mykey))
def _checkForMaskLikeKeywords(self, xpkg, y_ebuild, keywords):
# KEYWORDS="-*" is a stupid replacement for package.mask
# and screws general KEYWORDS semantics
if "-*" in keywords:
haskeyword = False
for kw in keywords:
if kw[0] == "~":
kw = kw[1:]
if kw in self.repo_metadata['kwlist']:
haskeyword = True
if not haskeyword:
self.qatracker.add_error("KEYWORDS.stupid",
"%s/%s.ebuild" % (xpkg, y_ebuild))
@property
def runInPkgs(self):
'''Package level scans'''
return (True, [self.prepare])
@property
def runInEbuilds(self):
'''Ebuild level scans'''
return (True, [self.check])
@property
def runInFinal(self):
'''Final package level scans'''
return (True, [self.check_dropped_keywords])