public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-07-15  2:08 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-07-15  2:08 UTC (permalink / raw
  To: gentoo-commits

commit:     bddc8dfbb5103d1ea6cb25a97127480ca9daba34
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 00:04:32 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sat Jul 15 02:08:27 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=bddc8dfb

repoman: Move errors data to repo metadata/repoman/linechecks.yaml

 repoman/pym/repoman/modules/scan/ebuild/errors.py | 53 -----------------------
 1 file changed, 53 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/errors.py b/repoman/pym/repoman/modules/scan/ebuild/errors.py
deleted file mode 100644
index 22547f4d5..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/errors.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Error Messages
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from __future__ import unicode_literals
-
-COPYRIGHT_ERROR = (
-	'Invalid Gentoo Copyright on line: %d')
-LICENSE_ERROR = (
-	'Invalid Gentoo/GPL License on line: %d')
-ID_HEADER_ERROR = (
-	'Stale CVS header on line: %d')
-NO_BLANK_LINE_ERROR = (
-	'Non-blank line after header on line: %d')
-LEADING_SPACES_ERROR = (
-	'Ebuild contains leading spaces on line: %d')
-TRAILING_WHITESPACE_ERROR = (
-	'Trailing whitespace error on line: %d')
-READONLY_ASSIGNMENT_ERROR = (
-	'Ebuild contains assignment to read-only variable on line: %d')
-MISSING_QUOTES_ERROR = (
-	'Unquoted Variable on line: %d')
-NESTED_DIE_ERROR = (
-	'Ebuild calls die in a subshell on line: %d')
-PATCHES_ERROR = (
-	'PATCHES is not a bash array on line: %d')
-REDUNDANT_CD_S_ERROR = (
-	'Ebuild has redundant cd ${S} statement on line: %d')
-EMAKE_PARALLEL_DISABLED = (
-	'Upstream parallel compilation bug (ebuild calls emake -j1 on line: %d)')
-EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS = (
-	'Upstream parallel compilation bug (MAKEOPTS=-j1 on line: %d)')
-DEPRECATED_BINDNOW_FLAGS = (
-	'Deprecated bindnow-flags call on line: %d')
-EAPI_DEFINED_AFTER_INHERIT = (
-	'EAPI defined after inherit on line: %d')
-NO_AS_NEEDED = (
-	'Upstream asneeded linking bug (no-as-needed on line: %d)')
-PRESERVE_OLD_LIB = (
-	'Ebuild calls deprecated preserve_old_lib on line: %d')
-BUILT_WITH_USE = (
-	'built_with_use on line: %d')
-NO_OFFSET_WITH_HELPERS = (
-	"Helper function is used with D, ROOT, ED, EROOT or EPREFIX on line :%d")
-SANDBOX_ADDPREDICT = (
-	'Ebuild calls addpredict on line: %d')
-USEQ_ERROR = (
-	'Ebuild calls deprecated useq function on line: %d')
-HASQ_ERROR = (
-	'Ebuild calls deprecated hasq function on line: %d')
-URI_HTTPS = (
-	'Ebuild uses http:// but should use https:// on line: %d')


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-07-15  2:08 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-07-15  2:08 UTC (permalink / raw
  To: gentoo-commits

commit:     f256db51d9b260223b2bfb2c542826cff2b4ffb9
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sat Jul 15 02:08:28 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=f256db51

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1039 ---------------------
 1 file changed, 1039 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index e6e5d78ba..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1039 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-07-15  2:29 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-07-15  2:29 UTC (permalink / raw
  To: gentoo-commits

commit:     18a8f9d992bb108e4456d7797f2872884e3dc160
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 00:04:32 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sat Jul 15 02:25:43 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=18a8f9d9

repoman: Move errors data to repo metadata/repoman/linechecks.yaml

 repoman/pym/repoman/modules/scan/ebuild/errors.py | 53 -----------------------
 1 file changed, 53 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/errors.py b/repoman/pym/repoman/modules/scan/ebuild/errors.py
deleted file mode 100644
index 22547f4d5..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/errors.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Error Messages
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from __future__ import unicode_literals
-
-COPYRIGHT_ERROR = (
-	'Invalid Gentoo Copyright on line: %d')
-LICENSE_ERROR = (
-	'Invalid Gentoo/GPL License on line: %d')
-ID_HEADER_ERROR = (
-	'Stale CVS header on line: %d')
-NO_BLANK_LINE_ERROR = (
-	'Non-blank line after header on line: %d')
-LEADING_SPACES_ERROR = (
-	'Ebuild contains leading spaces on line: %d')
-TRAILING_WHITESPACE_ERROR = (
-	'Trailing whitespace error on line: %d')
-READONLY_ASSIGNMENT_ERROR = (
-	'Ebuild contains assignment to read-only variable on line: %d')
-MISSING_QUOTES_ERROR = (
-	'Unquoted Variable on line: %d')
-NESTED_DIE_ERROR = (
-	'Ebuild calls die in a subshell on line: %d')
-PATCHES_ERROR = (
-	'PATCHES is not a bash array on line: %d')
-REDUNDANT_CD_S_ERROR = (
-	'Ebuild has redundant cd ${S} statement on line: %d')
-EMAKE_PARALLEL_DISABLED = (
-	'Upstream parallel compilation bug (ebuild calls emake -j1 on line: %d)')
-EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS = (
-	'Upstream parallel compilation bug (MAKEOPTS=-j1 on line: %d)')
-DEPRECATED_BINDNOW_FLAGS = (
-	'Deprecated bindnow-flags call on line: %d')
-EAPI_DEFINED_AFTER_INHERIT = (
-	'EAPI defined after inherit on line: %d')
-NO_AS_NEEDED = (
-	'Upstream asneeded linking bug (no-as-needed on line: %d)')
-PRESERVE_OLD_LIB = (
-	'Ebuild calls deprecated preserve_old_lib on line: %d')
-BUILT_WITH_USE = (
-	'built_with_use on line: %d')
-NO_OFFSET_WITH_HELPERS = (
-	"Helper function is used with D, ROOT, ED, EROOT or EPREFIX on line :%d")
-SANDBOX_ADDPREDICT = (
-	'Ebuild calls addpredict on line: %d')
-USEQ_ERROR = (
-	'Ebuild calls deprecated useq function on line: %d')
-HASQ_ERROR = (
-	'Ebuild calls deprecated hasq function on line: %d')
-URI_HTTPS = (
-	'Ebuild uses http:// but should use https:// on line: %d')


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-07-15  2:29 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-07-15  2:29 UTC (permalink / raw
  To: gentoo-commits

commit:     5c167468437229a68d6d5fc84dd5e9f9dc2c9c1c
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sat Jul 15 02:28:03 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=5c167468

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-09-11 21:43 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-09-11 21:43 UTC (permalink / raw
  To: gentoo-commits

commit:     f68c6bb2e4239e9fb041c2eb6c133fd7ab2ccd3e
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Mon Sep 11 16:13:17 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=f68c6bb2

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-11-26 17:46 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-11-26 17:46 UTC (permalink / raw
  To: gentoo-commits

commit:     c6c72edf59e98cac6d5d51d3b7348b29c1f4057c
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sun Nov 26 17:32:20 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=c6c72edf

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-12-05 18:32 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-12-05 18:32 UTC (permalink / raw
  To: gentoo-commits

commit:     dbae0587378b86266955f16849280d4674590063
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Tue Dec  5 18:24:49 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=dbae0587

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2017-12-06  0:16 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2017-12-06  0:16 UTC (permalink / raw
  To: gentoo-commits

commit:     6b501c4c9e2fd759d8b4a0b15ff1a47a0d7b0f9d
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Wed Dec  6 00:13:28 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=6b501c4c

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2018-03-29 21:35 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2018-03-29 21:35 UTC (permalink / raw
  To: gentoo-commits

commit:     85df91ccfa0b13ab9ec856b28e92a4c76bcfe08d
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Thu Mar 29 20:43:40 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=85df91cc

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2018-03-30  0:48 Brian Dolbec
  0 siblings, 0 replies; 11+ messages in thread
From: Brian Dolbec @ 2018-03-30  0:48 UTC (permalink / raw
  To: gentoo-commits

commit:     e2e41bbd71c024ab34a87d5f6d9edea2e43fc713
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Fri Mar 30 00:43:46 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=e2e41bbd

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/
@ 2018-03-30  5:20 Zac Medico
  0 siblings, 0 replies; 11+ messages in thread
From: Zac Medico @ 2018-03-30  5:20 UTC (permalink / raw
  To: gentoo-commits

commit:     ac86784b164c8705c45f79d3418d783e59d99a9a
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Jul 15 01:10:13 2017 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Fri Mar 30 03:51:20 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=ac86784b

repoman: Remove the no longer used modules/scan/ebuild/checks.py

 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1044 ---------------------
 1 file changed, 1044 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py b/repoman/pym/repoman/modules/scan/ebuild/checks.py
deleted file mode 100644
index de03bedd2..000000000
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-from __future__ import unicode_literals
-
-from itertools import chain
-import operator
-import re
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage.eapi import (
-	eapi_supports_prefix, eapi_has_implicit_rdepend,
-	eapi_has_src_prepare_and_src_configure, eapi_has_dosed_dohard,
-	eapi_exports_AA, eapi_has_pkg_pretend)
-
-from . import errors
-
-
-class LineCheck(object):
-	"""Run a check on a line of an ebuild."""
-	"""A regular expression to determine whether to ignore the line"""
-	ignore_line = False
-	"""True if lines containing nothing more than comments with optional
-	leading whitespace should be ignored"""
-	ignore_comment = True
-
-	def new(self, pkg):
-		pass
-
-	def check_eapi(self, eapi):
-		"""Returns if check should be run in the given EAPI (default: True)"""
-		return True
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		if self.re.match(line):
-			return self.error
-
-	def end(self):
-		pass
-
-
-class PhaseCheck(LineCheck):
-	""" basic class for function detection """
-
-	func_end_re = re.compile(r'^\}$')
-	phases_re = re.compile('(%s)' % '|'.join((
-		'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare',
-		'src_configure', 'src_compile', 'src_test', 'src_install',
-		'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm',
-		'pkg_config')))
-	in_phase = ''
-
-	def check(self, num, line):
-		m = self.phases_re.match(line)
-		if m is not None:
-			self.in_phase = m.group(1)
-		if self.in_phase != '' and self.func_end_re.match(line) is not None:
-			self.in_phase = ''
-
-		return self.phase_check(num, line)
-
-	def phase_check(self, num, line):
-		""" override this function for your checks """
-		pass
-
-
-class EbuildHeader(LineCheck):
-	"""Ensure ebuilds have proper headers
-		Copyright header errors
-		CVS header errors
-		License header errors
-
-	Args:
-		modification_year - Year the ebuild was last modified
-	"""
-
-	repoman_check_name = 'ebuild.badheader'
-
-	gentoo_copyright = r'^# Copyright ((1999|2\d\d\d)-)?%s Gentoo Foundation$'
-	gentoo_license = (
-		'# Distributed under the terms'
-		' of the GNU General Public License v2')
-	id_header_re = re.compile(r'.*\$(Id|Header)(:.*)?\$.*')
-	blank_line_re = re.compile(r'^$')
-	ignore_comment = False
-
-	def new(self, pkg):
-		if pkg.mtime is None:
-			self.modification_year = r'2\d\d\d'
-		else:
-			self.modification_year = str(time.gmtime(pkg.mtime)[0])
-		self.gentoo_copyright_re = re.compile(
-			self.gentoo_copyright % self.modification_year)
-
-	def check(self, num, line):
-		if num > 2:
-			return
-		elif num == 0:
-			if not self.gentoo_copyright_re.match(line):
-				return errors.COPYRIGHT_ERROR
-		elif num == 1 and line.rstrip('\n') != self.gentoo_license:
-			return errors.LICENSE_ERROR
-		elif num == 2 and self.id_header_re.match(line):
-			return errors.ID_HEADER_ERROR
-		elif num == 2 and not self.blank_line_re.match(line):
-			return errors.NO_BLANK_LINE_ERROR
-
-
-class EbuildWhitespace(LineCheck):
-	"""Ensure ebuilds have proper whitespacing"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-
-	ignore_line = re.compile(r'(^$)|(^(\t)*#)')
-	ignore_comment = False
-	leading_spaces = re.compile(r'^[\S\t]')
-	trailing_whitespace = re.compile(r'.*([\S]$)')
-
-	def check(self, num, line):
-		if self.leading_spaces.match(line) is None:
-			return errors.LEADING_SPACES_ERROR
-		if self.trailing_whitespace.match(line) is None:
-			return errors.TRAILING_WHITESPACE_ERROR
-
-
-class EbuildBlankLine(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	ignore_comment = False
-	blank_line = re.compile(r'^$')
-
-	def new(self, pkg):
-		self.line_is_blank = False
-
-	def check(self, num, line):
-		if self.line_is_blank and self.blank_line.match(line):
-			return 'Useless blank line on line: %d'
-		if self.blank_line.match(line):
-			self.line_is_blank = True
-		else:
-			self.line_is_blank = False
-
-	def end(self):
-		if self.line_is_blank:
-			yield 'Useless blank line on last line'
-
-
-class EbuildQuote(LineCheck):
-	"""Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	_message_commands = [
-		"die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
-	_message_re = re.compile(
-		r'\s(' + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
-	_ignored_commands = ["local", "export"] + _message_commands
-	ignore_line = re.compile(
-		r'(^$)|(^\s*#.*)|(^\s*\w+=.*)' +
-		r'|(^\s*(' + "|".join(_ignored_commands) + r')\s+)')
-	ignore_comment = False
-	var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "WORKDIR"]
-
-	# EAPI=3/Prefix vars
-	var_names += ["ED", "EPREFIX", "EROOT"]
-
-	# variables for games.eclass
-	var_names += [
-		"Ddir", "GAMES_PREFIX_OPT", "GAMES_DATADIR",
-		"GAMES_DATADIR_BASE", "GAMES_SYSCONFDIR", "GAMES_STATEDIR",
-		"GAMES_LOGDIR", "GAMES_BINDIR"]
-
-	# variables for multibuild.eclass
-	var_names += ["BUILD_DIR"]
-
-	var_names = "(%s)" % "|".join(var_names)
-	var_reference = re.compile(
-		r'\$(\{%s\}|%s\W)' % (var_names, var_names))
-	missing_quotes = re.compile(
-		r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
-	cond_begin = re.compile(r'(^|\s+)\[\[($|\\$|\s+)')
-	cond_end = re.compile(r'(^|\s+)\]\]($|\\$|\s+)')
-
-	def check(self, num, line):
-		if self.var_reference.search(line) is None:
-			return
-		# There can be multiple matches / violations on a single line. We
-		# have to make sure none of the matches are violators. Once we've
-		# found one violator, any remaining matches on the same line can
-		# be ignored.
-		pos = 0
-		while pos <= len(line) - 1:
-			missing_quotes = self.missing_quotes.search(line, pos)
-			if not missing_quotes:
-				break
-			# If the last character of the previous match is a whitespace
-			# character, that character may be needed for the next
-			# missing_quotes match, so search overlaps by 1 character.
-			group = missing_quotes.group()
-			pos = missing_quotes.end() - 1
-
-			# Filter out some false positives that can
-			# get through the missing_quotes regex.
-			if self.var_reference.search(group) is None:
-				continue
-
-			# Filter matches that appear to be an
-			# argument to a message command.
-			# For example: false || ewarn "foo $WORKDIR/bar baz"
-			message_match = self._message_re.search(line)
-			if message_match is not None and \
-				message_match.start() < pos and \
-				message_match.end() > pos:
-				break
-
-			# This is an attempt to avoid false positives without getting
-			# too complex, while possibly allowing some (hopefully
-			# unlikely) violations to slip through. We just assume
-			# everything is correct if the there is a ' [[ ' or a ' ]] '
-			# anywhere in the whole line (possibly continued over one
-			# line).
-			if self.cond_begin.search(line) is not None:
-				continue
-			if self.cond_end.search(line) is not None:
-				continue
-
-			# Any remaining matches on the same line can be ignored.
-			return errors.MISSING_QUOTES_ERROR
-
-
-class EbuildAssignment(LineCheck):
-	"""Ensure ebuilds don't assign to readonly variables."""
-
-	repoman_check_name = 'variable.readonly'
-	read_only_vars = 'A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE'
-	readonly_assignment = re.compile(r'^\s*(export\s+)?(%s)=' % read_only_vars)
-
-	def check(self, num, line):
-		match = self.readonly_assignment.match(line)
-		e = None
-		if match is not None:
-			e = errors.READONLY_ASSIGNMENT_ERROR
-		return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
-	"""Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
-	readonly_assignment = re.compile(r'\s*(export\s+)?(ED|EPREFIX|EROOT)=')
-
-	def check_eapi(self, eapi):
-		return eapi_supports_prefix(eapi)
-
-
-class EbuildNestedDie(LineCheck):
-	"""Check ebuild for nested die statements (die statements in subshells)"""
-
-	repoman_check_name = 'ebuild.nesteddie'
-	nesteddie_re = re.compile(r'^[^#]*\s\(\s[^)]*\bdie\b')
-
-	def check(self, num, line):
-		if self.nesteddie_re.match(line):
-			return errors.NESTED_DIE_ERROR
-
-
-class EbuildUselessDodoc(LineCheck):
-	"""Check ebuild for useless files in dodoc arguments."""
-	repoman_check_name = 'ebuild.minorsyn'
-	uselessdodoc_re = re.compile(
-		r'^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)')
-
-	def check(self, num, line):
-		match = self.uselessdodoc_re.match(line)
-		if match:
-			return "Useless dodoc '%s'" % (match.group(2), ) + " on line: %d"
-
-
-class EbuildUselessCdS(LineCheck):
-	"""Check for redundant cd ${S} statements"""
-	repoman_check_name = 'ebuild.minorsyn'
-	_src_phases = r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)'
-	method_re = re.compile(_src_phases)
-	cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
-	def __init__(self):
-		self.check_next_line = False
-
-	def check(self, num, line):
-		if self.check_next_line:
-			self.check_next_line = False
-			if self.cds_re.match(line):
-				return errors.REDUNDANT_CD_S_ERROR
-		elif self.method_re.match(line):
-			self.check_next_line = True
-
-
-class EapiDefinition(LineCheck):
-	"""
-	Check that EAPI assignment conforms to PMS section 7.3.1
-	(first non-comment, non-blank line).
-	"""
-	repoman_check_name = 'EAPI.definition'
-	ignore_comment = True
-	_eapi_re = portage._pms_eapi_re
-
-	def new(self, pkg):
-		self._cached_eapi = pkg.eapi
-		self._parsed_eapi = None
-		self._eapi_line_num = None
-
-	def check(self, num, line):
-		if self._eapi_line_num is None and line.strip():
-			self._eapi_line_num = num + 1
-			m = self._eapi_re.match(line)
-			if m is not None:
-				self._parsed_eapi = m.group(2)
-
-	def end(self):
-		if self._parsed_eapi is None:
-			if self._cached_eapi != "0":
-				yield "valid EAPI assignment must occur on or before line: %s" % \
-					self._eapi_line_num
-		elif self._parsed_eapi != self._cached_eapi:
-			yield (
-				"bash returned EAPI '%s' which does not match "
-				"assignment on line: %s" %
-				(self._cached_eapi, self._eapi_line_num))
-
-
-class EbuildPatches(LineCheck):
-	"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-	repoman_check_name = 'ebuild.patches'
-	re = re.compile(r'^\s*PATCHES=[^\(]')
-	error = errors.PATCHES_ERROR
-
-	def check_eapi(self, eapi):
-		return eapi in ("0", "1", "2", "3", "4", "4-python",
-			"4-slot-abi", "5", "5-hdepend", "5-progress")
-
-
-class EbuildQuotedA(LineCheck):
-	"""Ensure ebuilds have no quoting around ${A}"""
-
-	repoman_check_name = 'ebuild.minorsyn'
-	a_quoted = re.compile(r'.*\"\$(\{A\}|A)\"')
-
-	def check(self, num, line):
-		match = self.a_quoted.match(line)
-		if match:
-			return "Quoted \"${A}\" on line: %d"
-
-
-class NoOffsetWithHelpers(LineCheck):
-	""" Check that the image location, the alternate root offset, and the
-	offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
-	helpers """
-
-	repoman_check_name = 'variable.usedwithhelpers'
-	# Ignore matches in quoted strings like this:
-	# elog "installed into ${ROOT}usr/share/php5/apc/."
-	_install_funcs = (
-		'docinto|do(compress|dir|hard)'
-		'|exeinto|fowners|fperms|insinto|into')
-	_quoted_vars = 'D|ROOT|ED|EROOT|EPREFIX'
-	re = re.compile(
-		r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' %
-		(_install_funcs, _quoted_vars))
-	error = errors.NO_OFFSET_WITH_HELPERS
-
-
-class ImplicitRuntimeDeps(LineCheck):
-	"""
-	Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
-	since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
-	"""
-
-	repoman_check_name = 'RDEPEND.implicit'
-	_assignment_re = re.compile(r'^\s*(R?DEPEND)\+?=')
-
-	def new(self, pkg):
-		self._rdepend = False
-		self._depend = False
-
-	def check_eapi(self, eapi):
-		# Beginning with EAPI 4, there is no
-		# implicit RDEPEND=$DEPEND assignment
-		# to be concerned with.
-		return eapi_has_implicit_rdepend(eapi)
-
-	def check(self, num, line):
-		if not self._rdepend:
-			m = self._assignment_re.match(line)
-			if m is None:
-				pass
-			elif m.group(1) == "RDEPEND":
-				self._rdepend = True
-			elif m.group(1) == "DEPEND":
-				self._depend = True
-
-	def end(self):
-		if self._depend and not self._rdepend:
-			yield 'RDEPEND is not explicitly assigned'
-
-
-class InheritDeprecated(LineCheck):
-	"""Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
-	repoman_check_name = 'inherit.deprecated'
-
-	# deprecated eclass : new eclass (False if no new eclass)
-	deprecated_eclasses = {
-		"autotools-multilib": "multilib-minimal",
-		"autotools-utils": False,
-		"base": False,
-		"bash-completion": "bash-completion-r1",
-		"boost-utils": False,
-		"clutter": "gnome2",
-		"confutils": False,
-		"distutils": "distutils-r1",
-		"fdo-mime": "xdg-utils",
-		"games": False,
-		"gems": "ruby-fakegem",
-		"git-2": "git-r3",
-		"gpe": False,
-		"gst-plugins-bad": "gstreamer",
-		"gst-plugins-base": "gstreamer",
-		"gst-plugins-good": "gstreamer",
-		"gst-plugins-ugly": "gstreamer",
-		"gst-plugins10": "gstreamer",
-		"mono": "mono-env",
-		"python": "python-r1 / python-single-r1 / python-any-r1",
-		"ruby": "ruby-ng",
-		"x-modular": "xorg-2",
-		"xfconf": False,
-	}
-
-	_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-
-	def new(self, pkg):
-		self._errors = []
-
-	def check(self, num, line):
-		direct_inherits = None
-		m = self._inherit_re.match(line)
-		if m is not None:
-			direct_inherits = m.group(1)
-			if direct_inherits:
-				direct_inherits = direct_inherits.split()
-
-		if not direct_inherits:
-			return
-
-		for eclass in direct_inherits:
-			replacement = self.deprecated_eclasses.get(eclass)
-			if replacement is None:
-				pass
-			elif replacement is False:
-				self._errors.append(
-					"please migrate from "
-					"'%s' (no replacement) on line: %d" % (eclass, num + 1))
-			else:
-				self._errors.append(
-					"please migrate from "
-					"'%s' to '%s' on line: %d" % (eclass, replacement, num + 1))
-
-	def end(self):
-		for error in self._errors:
-			yield error
-		del self._errors
-
-
-
-class InheritEclass(LineCheck):
-	"""
-	Base class for checking for missing inherits, as well as excess inherits.
-
-	Args:
-		eclass: Set to the name of your eclass.
-		funcs: A tuple of functions that this eclass provides.
-		comprehensive: Is the list of functions complete?
-		exempt_eclasses: If these eclasses are inherited, disable the missing
-			inherit check.
-	"""
-
-	def __init__(
-		self, eclass, funcs=None, comprehensive=False,
-		exempt_eclasses=None, ignore_missing=False, **kwargs):
-		self._eclass = eclass
-		self._comprehensive = comprehensive
-		self._exempt_eclasses = exempt_eclasses
-		self._ignore_missing = ignore_missing
-		inherit_re = eclass
-		self._inherit_re = re.compile(
-			r'^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)' % inherit_re)
-		# Match when the function is preceded only by leading whitespace, a
-		# shell operator such as (, {, |, ||, or &&, or optional variable
-		# setting(s). This prevents false positives in things like elog
-		# messages, as reported in bug #413285.
-		self._func_re = re.compile(
-			r'(^|[|&{(])\s*(\w+=.*)?\b(' + '|'.join(funcs) + r')\b')
-
-	def new(self, pkg):
-		self.repoman_check_name = 'inherit.missing'
-		# We can't use pkg.inherited because that tells us all the eclasses that
-		# have been inherited and not just the ones we inherit directly.
-		self._inherit = False
-		self._func_call = False
-		if self._exempt_eclasses is not None:
-			inherited = pkg.inherited
-			self._disabled = any(x in inherited for x in self._exempt_eclasses)
-		else:
-			self._disabled = False
-		self._eapi = pkg.eapi
-
-	def check(self, num, line):
-		if not self._inherit:
-			self._inherit = self._inherit_re.match(line)
-		if not self._inherit:
-			if self._disabled or self._ignore_missing:
-				return
-			s = self._func_re.search(line)
-			if s is not None:
-				func_name = s.group(3)
-				eapi_func = _eclass_eapi_functions.get(func_name)
-				if eapi_func is None or not eapi_func(self._eapi):
-					self._func_call = True
-					return (
-						'%s.eclass is not inherited, '
-						'but "%s" found at line: %s' %
-						(self._eclass, func_name, '%d'))
-		elif not self._func_call:
-			self._func_call = self._func_re.search(line)
-
-	def end(self):
-		if not self._disabled and self._comprehensive and self._inherit \
-			and not self._func_call:
-			self.repoman_check_name = 'inherit.unused'
-			yield 'no function called from %s.eclass; please drop' % self._eclass
-
-_usex_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
-_in_iuse_supported_eapis = ("0", "1", "2", "3", "4", "4-python", "4-slot-abi",
-		"5", "5-hdepend", "5-progress")
-_get_libdir_supported_eapis = _in_iuse_supported_eapis
-_eclass_eapi_functions = {
-	"usex": lambda eapi: eapi not in _usex_supported_eapis,
-	"in_iuse": lambda eapi: eapi not in _in_iuse_supported_eapis,
-	"get_libdir": lambda eapi: eapi not in _get_libdir_supported_eapis,
-}
-
-# eclasses that export ${ECLASS}_src_(compile|configure|install)
-_eclass_export_functions = (
-	'ant-tasks', 'apache-2', 'apache-module', 'aspell-dict',
-	'autotools-utils', 'base', 'bsdmk', 'cannadic',
-	'clutter', 'cmake-utils', 'db', 'distutils', 'elisp',
-	'embassy', 'emboss', 'emul-linux-x86', 'enlightenment',
-	'font-ebdftopcf', 'font', 'fox', 'freebsd', 'freedict',
-	'games', 'games-ggz', 'games-mods', 'gdesklets',
-	'gems', 'gkrellm-plugin', 'gnatbuild', 'gnat', 'gnome2',
-	'gnome-python-common', 'gnustep-base', 'go-mono', 'gpe',
-	'gst-plugins-bad', 'gst-plugins-base', 'gst-plugins-good',
-	'gst-plugins-ugly', 'gtk-sharp-module', 'haskell-cabal',
-	'horde', 'java-ant-2', 'java-pkg-2', 'java-pkg-simple',
-	'java-virtuals-2', 'kde4-base', 'kde4-meta', 'kernel-2',
-	'latex-package', 'linux-mod', 'mozlinguas', 'myspell',
-	'myspell-r2', 'mysql', 'mysql-v2', 'mythtv-plugins',
-	'oasis', 'obs-service', 'office-ext', 'perl-app',
-	'perl-module', 'php-ext-base-r1', 'php-ext-pecl-r2',
-	'php-ext-source-r2', 'php-lib-r1', 'php-pear-lib-r1',
-	'php-pear-r1', 'python-distutils-ng', 'python',
-	'qt4-build', 'qt4-r2', 'rox-0install', 'rox', 'ruby',
-	'ruby-ng', 'scsh', 'selinux-policy-2', 'sgml-catalog',
-	'stardict', 'sword-module', 'tetex-3', 'tetex',
-	'texlive-module', 'toolchain-binutils', 'toolchain',
-	'twisted', 'vdr-plugin-2', 'vdr-plugin', 'vim',
-	'vim-plugin', 'vim-spell', 'virtuoso', 'vmware',
-	'vmware-mod', 'waf-utils', 'webapp', 'xemacs-elisp',
-	'xemacs-packages', 'xfconf', 'x-modular', 'xorg-2',
-	'zproduct'
-)
-
-_eclass_info = {
-	'autotools': {
-		'funcs': (
-			'eaclocal', 'eautoconf', 'eautoheader',
-			'eautomake', 'eautoreconf', '_elibtoolize',
-			'eautopoint'
-		),
-		'comprehensive': True,
-
-		# Exempt eclasses:
-		# git - An EGIT_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		# subversion - An ESVN_BOOTSTRAP variable may be used to call one of
-		#       the autotools functions.
-		'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-	},
-
-	'eutils': {
-		'funcs': (
-			'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
-			'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
-			'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex'
-		),
-		'comprehensive': False,
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions,
-	},
-
-	'flag-o-matic': {
-		'funcs': (
-			'filter-(ld)?flags', 'strip-flags', 'strip-unsupported-flags',
-			'append-((ld|c(pp|xx)?))?flags', 'append-libs',
-		),
-		'comprehensive': False
-	},
-
-	'libtool': {
-		'funcs': (
-			'elibtoolize',
-		),
-		'comprehensive': True,
-		'exempt_eclasses': ('autotools',)
-	},
-
-	'multilib': {
-		'funcs': (
-			'get_libdir',
-		),
-
-		# These are "eclasses are the whole ebuild" type thing.
-		'exempt_eclasses': _eclass_export_functions + (
-			'autotools', 'libtool', 'multilib-minimal'),
-
-		'comprehensive': False
-	},
-
-	'multiprocessing': {
-		'funcs': (
-			'makeopts_jobs',
-		),
-		'comprehensive': False
-	},
-
-	'prefix': {
-		'funcs': (
-			'eprefixify',
-		),
-		'comprehensive': True
-	},
-
-	'toolchain-funcs': {
-		'funcs': (
-			'gen_usr_ldscript',
-		),
-		'comprehensive': False
-	},
-
-	'user': {
-		'funcs': (
-			'enewuser', 'enewgroup',
-			'egetent', 'egethome', 'egetshell', 'esethome'
-		),
-		'comprehensive': True
-	}
-}
-
-
-class EMakeParallelDisabled(PhaseCheck):
-	"""Check for emake -j1 calls which disable parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*emake\s+.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile' or self.in_phase == 'src_install':
-			if self.re.match(line):
-				return self.error
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
-	"""Check for MAKEOPTS=-j1 that disables parallelization."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
-	error = errors.EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS
-
-
-class UriUseHttps(LineCheck):
-	"""Check that we use https:// for known good sites."""
-	repoman_check_name = 'uri.https'
-	_SITES = (
-		'([-._a-zA-Z0-9]*\.)?apache\.org',
-		'((alioth|packages(\.qa)?|people|www)\.)?debian\.org',
-		# Most FDO sites support https, but not all (like tango).
-		# List the most common ones here for now.
-		'((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org',
-		'((bugs|dev|wiki|www)\.)?gentoo\.org',
-		'((wiki)\.)?github\.(io|com)',
-		'savannah\.(non)?gnu\.org',
-		'((gcc|www)\.)?gnu\.org',
-		'curl\.haxx\.se',
-		'((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org',
-		'((bugs|wiki|www)\.)?linuxfoundation\.org',
-		'((docs|pypi|www)\.)?python\.org',
-		'(sf|sourceforge)\.net',
-		'(www\.)?(enlightenment|sourceware|x)\.org',
-	)
-	# Try to anchor the end of the URL so we don't get false positives
-	# with http://github.com.foo.bar.com/.  Unlikely, but possible.
-	re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r'|'.join(_SITES))
-	error = errors.URI_HTTPS
-
-
-class NoAsNeeded(LineCheck):
-	"""Check for calls to the no-as-needed function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'.*\$\(no-as-needed\)')
-	error = errors.NO_AS_NEEDED
-
-
-class PreserveOldLib(LineCheck):
-	"""Check for calls to the deprecated preserve_old_lib function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*preserve_old_lib')
-	error = errors.PRESERVE_OLD_LIB
-
-
-class SandboxAddpredict(LineCheck):
-	"""Check for calls to the addpredict function."""
-	repoman_check_name = 'upstream.workaround'
-	re = re.compile(r'(^|\s)addpredict\b')
-	error = errors.SANDBOX_ADDPREDICT
-
-
-class DeprecatedBindnowFlags(LineCheck):
-	"""Check for calls to the deprecated bindnow-flags function."""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'.*\$\(bindnow-flags\)')
-	error = errors.DEPRECATED_BINDNOW_FLAGS
-
-
-class WantAutoDefaultValue(LineCheck):
-	"""Check setting WANT_AUTO* to latest (default value)."""
-	repoman_check_name = 'ebuild.minorsyn'
-	_re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
-	def check(self, num, line):
-		m = self._re.match(line)
-		if m is not None:
-			return 'WANT_AUTO' + m.group(1) + \
-				' redundantly set to default value "latest" on line: %d'
-
-
-class SrcCompileEconf(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	configure_re = re.compile(r'\s(econf|./configure)')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_compile':
-			m = self.configure_re.match(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_configure from line: %d"
-
-
-class SrcUnpackPatches(PhaseCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s')
-
-	def check_eapi(self, eapi):
-		return eapi_has_src_prepare_and_src_configure(eapi)
-
-	def phase_check(self, num, line):
-		if self.in_phase == 'src_unpack':
-			m = self.src_prepare_tools_re.search(line)
-			if m is not None:
-				return ("'%s'" % m.group(1)) + \
-					" call should be moved to src_prepare from line: %d"
-
-
-class BuiltWithUse(LineCheck):
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)built_with_use\b')
-	error = errors.BUILT_WITH_USE
-
-
-class DeprecatedUseq(LineCheck):
-	"""Checks for use of the deprecated useq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)useq\b')
-	error = errors.USEQ_ERROR
-
-
-class DeprecatedHasq(LineCheck):
-	"""Checks for use of the deprecated hasq function"""
-	repoman_check_name = 'ebuild.minorsyn'
-	re = re.compile(r'(^|.*\b)hasq\b')
-	error = errors.HASQ_ERROR
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	src_configprepare_re = re.compile(r'\s*(src_configure|src_prepare)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_src_prepare_and_src_configure(eapi)
-
-	def check(self, num, line):
-		m = self.src_configprepare_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 2 on line: %d"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
-	repoman_check_name = 'EAPI.deprecated'
-	deprecated_commands_re = re.compile(r'^\s*(check_license)\b')
-
-	def check_eapi(self, eapi):
-		return eapi not in ('0', '1', '2')
-
-	def check(self, num, line):
-		m = self.deprecated_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been deprecated in EAPI=3 on line: %d"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	pkg_pretend_re = re.compile(r'\s*(pkg_pretend)\s*\(\)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_pkg_pretend(eapi)
-
-	def check(self, num, line):
-		m = self.pkg_pretend_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" phase is not defined in EAPI < 4 on line: %d"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	banned_commands_re = re.compile(r'^\s*(dosed|dohard)')
-
-	def check_eapi(self, eapi):
-		return not eapi_has_dosed_dohard(eapi)
-
-	def check(self, num, line):
-		m = self.banned_commands_re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(1)) + \
-				" has been banned in EAPI=4 on line: %d"
-
-
-class Eapi4GoneVars(LineCheck):
-	repoman_check_name = 'EAPI.incompatible'
-	undefined_vars_re = re.compile(
-		r'.*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))')
-
-	def check_eapi(self, eapi):
-		# AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
-		return not eapi_exports_AA(eapi)
-
-	def check(self, num, line):
-		m = self.undefined_vars_re.match(line)
-		if m is not None:
-			return ("variable '$%s'" % m.group(1)) + \
-				" is gone in EAPI=4 on line: %d"
-
-
-class PortageInternal(LineCheck):
-	repoman_check_name = 'portage.internal'
-	ignore_comment = True
-	# Match when the command is preceded only by leading whitespace or a shell
-	# operator such as (, {, |, ||, or &&. This prevents false positives in
-	# things like elog messages, as reported in bug #413285.
-
-	internal_portage_func_or_var = (
-		'ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib')
-	re = re.compile(
-		r'^(\s*|.*[|&{(]+\s*)\b(%s)\b' % internal_portage_func_or_var)
-
-	def check(self, num, line):
-		"""Run the check on line and return error if there is one"""
-		m = self.re.match(line)
-		if m is not None:
-			return ("'%s'" % m.group(2)) + " called on line: %d"
-
-
-class PortageInternalVariableAssignment(LineCheck):
-	repoman_check_name = 'portage.internal'
-	internal_assignment = re.compile(
-		r'\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=')
-
-	def check(self, num, line):
-		match = self.internal_assignment.match(line)
-		e = None
-		if match is not None:
-			e = 'Assignment to variable %s' % match.group(2)
-			e += ' on line: %d'
-		return e
-
-
-class EbuildNonRelativeDosym(LineCheck):
-	"""Check ebuild for dosym using absolute paths instead of relative."""
-	repoman_check_name = 'ebuild.absdosym'
-	regex = re.compile(
-		r'^\s*dosym\s+["\']?(/(bin|etc|lib|opt|sbin|srv|usr|var)\S*)')
-
-	def check(self, num, line):
-		match = self.regex.match(line)
-		if match:
-			return "dosym '%s'... could use relative path" % (match.group(1), ) + " on line: %d"
-
-
-_base_check_classes = (InheritEclass, LineCheck, PhaseCheck)
-_constant_checks = None
-
-
-def checks_init(experimental_inherit=False):
-
-	global _constant_checks, _eclass_info
-
-	if not experimental_inherit:
-		# Emulate the old eprefixify.defined and inherit.autotools checks.
-		_eclass_info = {
-			'autotools': {
-				'funcs': (
-					'eaclocal', 'eautoconf', 'eautoheader',
-					'eautomake', 'eautoreconf', '_elibtoolize',
-					'eautopoint'
-				),
-				'comprehensive': True,
-				'ignore_missing': True,
-				'exempt_eclasses': ('git', 'git-2', 'subversion', 'autotools-utils')
-			},
-
-			'prefix': {
-				'funcs': (
-					'eprefixify',
-				),
-				'comprehensive': False
-			}
-		}
-
-	_constant_checks = tuple(
-		chain((
-			v() for k, v in globals().items()
-			if (
-				isinstance(v, type)
-				and issubclass(v, LineCheck)
-				and v not in _base_check_classes)), (
-			InheritEclass(k, **kwargs)
-			for k, kwargs in _eclass_info.items())))
-
-
-_here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
-_ignore_comment_re = re.compile(r'^\s*#')
-_continuation_re = re.compile(r'(\\)*$')
-
-
-def run_checks(contents, pkg):
-	if _constant_checks is None:
-		checks_init()
-	checks = _constant_checks
-	here_doc_delim = None
-	multiline = None
-
-	for lc in checks:
-		lc.new(pkg)
-
-	multinum = 0
-	for num, line in enumerate(contents):
-
-		# Check if we're inside a here-document.
-		if here_doc_delim is not None:
-			if here_doc_delim.match(line):
-				here_doc_delim = None
-		if here_doc_delim is None:
-			here_doc = _here_doc_re.match(line)
-			if here_doc is not None:
-				here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
-		if here_doc_delim is not None:
-			continue
-
-		# Unroll multiline escaped strings so that we can check things:
-		# 	inherit foo bar \
-		# 		moo \
-		# 		cow
-		# This will merge these lines like so:
-		# 	inherit foo bar moo cow
-		# A line ending with an even number of backslashes does not count,
-		# because the last backslash is escaped. Therefore, search for an
-		# odd number of backslashes.
-		line_escaped = operator.sub(*_continuation_re.search(line).span()) % 2 == 1
-		if multiline:
-			# Chop off the \ and \n bytes from the previous line.
-			multiline = multiline[:-2] + line
-			if not line_escaped:
-				line = multiline
-				num = multinum
-				multiline = None
-			else:
-				continue
-		else:
-			if line_escaped:
-				multinum = num
-				multiline = line
-				continue
-
-		if not line.endswith("#nowarn\n"):
-			# Finally we have a full line to parse.
-			is_comment = _ignore_comment_re.match(line) is not None
-			for lc in checks:
-				if is_comment and lc.ignore_comment:
-					continue
-				if lc.check_eapi(pkg.eapi):
-					ignore = lc.ignore_line
-					if not ignore or not ignore.match(line):
-						e = lc.check(num, line)
-						if e:
-							yield lc.repoman_check_name, e % (num + 1)
-
-	for lc in checks:
-		i = lc.end()
-		if i is not None:
-			for e in i:
-				yield lc.repoman_check_name, e


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-03-30  5:21 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-15  2:29 [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/modules/scan/ebuild/ Brian Dolbec
  -- strict thread matches above, loose matches on Subject: below --
2018-03-30  5:20 Zac Medico
2018-03-30  0:48 Brian Dolbec
2018-03-29 21:35 Brian Dolbec
2017-12-06  0:16 Brian Dolbec
2017-12-05 18:32 Brian Dolbec
2017-11-26 17:46 Brian Dolbec
2017-09-11 21:43 Brian Dolbec
2017-07-15  2:29 Brian Dolbec
2017-07-15  2:08 Brian Dolbec
2017-07-15  2:08 Brian Dolbec

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox