diff options
-rw-r--r-- | pym/repoman/__init__.py | 0 | ||||
-rw-r--r-- | pym/repoman/checks.py | 177 | ||||
-rw-r--r-- | pym/repoman/errors.py | 12 |
3 files changed, 189 insertions, 0 deletions
diff --git a/pym/repoman/__init__.py b/pym/repoman/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pym/repoman/__init__.py diff --git a/pym/repoman/checks.py b/pym/repoman/checks.py new file mode 100644 index 000000000..89f041d8e --- /dev/null +++ b/pym/repoman/checks.py @@ -0,0 +1,177 @@ +# repoman: Checks +# Copyright 2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +import time +import re +import os + +from repoman.errors import COPYRIGHT_ERROR, LICENSE_ERROR, CVS_HEADER_ERROR, \ + LEADING_SPACES_ERROR, READONLY_ASSIGNMENT_ERROR, TRAILING_WHITESPACE_ERROR, \ + MISSING_QUOTES_ERROR + + +class ContentCheckException(Exception): + """Parent class for exceptions relating to invalid content""" + + def __init__(self, str): + Exception.__init__(self, str) + + +class ContentCheck(object): + """Given a file-like object, run checks over it's content + + Args: + contents - A file-like object, preferably a StringIO instance + + Raises: + ContentCheckException or a subclass + """ + repoman_check_name = None + + def __init__(self, contents): + self.contents = contents + pass + + def Run(self): + """Run the check against the contents, return a sequence of errors + of the form ((line, error),...) + """ + pass + + +class EbuildHeaderCheck(ContentCheck): + """Ensure ebuilds have proper headers + + Args: + modification_year - Year the ebuild was last modified + """ + + repoman_check_name = 'ebuild.badheader' + + gentoo_copyright = r'^# Copyright ((1999|200\d)-)?%s Gentoo Foundation$' + # Why a regex here, use a string match + # gentoo_license = re.compile(r'^# Distributed under the terms of the GNU General Public License v2$') + gentoo_license = r'# Distributed under the terms of the GNU General Public License v2' + cvs_header = re.compile(r'^#\s*\$Header.*\$$') + + def __init__(self, contents, modification_year): + ContentCheck.__init__(self, contents) + self.modification_year = modification_year + self.gentoo_copyright_re = re.compile(self.gentoo_copyright % self.modification_year) + + def Run(self): + """Locate simple header mistakes in an ebuild + Copyright header errors + CVS header errors + License header errors + """ + errors = [] + for num, line in enumerate(self.contents): + if num == 0: + match = self.gentoo_copyright_re.match(line) + if not match: + errors.append((num + 1, COPYRIGHT_ERROR)) + if num == 1 and line.strip() != self.gentoo_license: + errors.append((num + 1, LICENSE_ERROR)) + if num == 2: + match = self.cvs_header.match(line) + if not match: + errors.append((num + 1, CVS_HEADER_ERROR)) + if num > 2: + return errors + return errors + + +class EbuildWhitespaceCheck(ContentCheck): + """Ensure ebuilds have proper whitespacing""" + + repoman_check_name = 'ebuild.minorsyn' + + ignore_line = re.compile(r'(^$)|(^(\t)*#)') + leading_spaces = re.compile(r'^[\S\t]') + trailing_whitespace = re.compile(r'.*([\S]$)') + + def __init__(self, contents): + ContentCheck.__init__(self, contents) + + def Run(self): + """Locate simple whitespace errors + Lines with leading spaces or trailing whitespace + """ + errors = [] + for num, line in enumerate(self.contents): + match = self.ignore_line.match(line) + if match: + continue + match = self.leading_spaces.match(line) + if not match: + errors.append((num + 1, LEADING_SPACES_ERROR)) + match = self.trailing_whitespace.match(line) + if not match: + errors.append((num + 1, TRAILING_WHITESPACE_ERROR)) + return errors + + +class EbuildQuoteCheck(ContentCheck): + """Ensure ebuilds have valid quoting around things like D,FILESDIR, etc...""" + + repoman_check_name = 'ebuild.minorsyn' + + missing_quotes = re.compile(r'[^"]\${?(D|S|T|ROOT|FILESDIR|WORKDIR)}?\W') + missing_quotes_exclude = re.compile(r'\[\[.*[^"]\${?(D|S|T|ROOT|FILESDIR|WORKDIR)}?\W.*\]\]') + ignore_line = re.compile(r'(^$)|(^(\t)*#)') + + def __init__(self, contents): + ContentCheck.__init__(self, contents) + + def Run(self): + """Locate simple errors in ebuilds: + Missing quotes around variables that may contain spaces + """ + + errors = [] + for num, line in enumerate(self.contents): + match = self.ignore_line.match(line) + if match: + continue + missing_quotes_line = self.missing_quotes.search(line) + if missing_quotes_line: + for group in missing_quotes_line.group(): + match = self.missing_quotes_exclude.search(group) + if not match: + errors.append((num + 1, MISSING_QUOTES_ERROR)) + break + return errors + + +class EbuildAssignmentCheck(ContentCheck): + """Ensure ebuilds don't assign to readonly variables.""" + + repoman_check_name = 'ebuild.majorsyn' + + readonly_assignment = re.compile(r'^\s*(export\s+)?(A|CATEGORY|P|PV|PN|PR|PVR|PF|D|WORKDIR|FILESDIR|FEATURES|USE)=') + line_continuation = re.compile(r'([^#]*\S)(\s+|\t)\\$') + ignore_line = re.compile(r'(^$)|(^(\t)*#)') + + def __init__(self, contents): + ContentCheck.__init__(self, contents) + + def Run(self): + """Locate simple errors in ebuilds: + Assigning to read-only variables. + """ + + errors = [] + previous_line = None + # enumerate is 0 indexed, so add one when necesseary + for num, line in enumerate(self.contents): + match = self.ignore_line.match(line) + if match: + continue + match = self.readonly_assignment.match(line) + if match and (not previous_line or not self.line_continuation.match(previous_line)): + errors.append((num + 1, READONLY_ASSIGNMENT_ERROR)) + previous_line = line + return errors diff --git a/pym/repoman/errors.py b/pym/repoman/errors.py new file mode 100644 index 000000000..c8734ff4d --- /dev/null +++ b/pym/repoman/errors.py @@ -0,0 +1,12 @@ +# repoman: Error Messages +# Copyright 2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +COPYRIGHT_ERROR = 'Invalid Gentoo Copyright on line: %d' +LICENSE_ERROR = 'Invalid Gentoo/GPL License on line: %d' +CVS_HEADER_ERROR = 'Malformed CVS 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'
\ No newline at end of file |