head	1.10;
access;
symbols
	GENTOO_1_4_SNAP_2003010800:1.8;
locks; strict;
comment	@# @;


1.10
date	2003.02.14.22.04.53;	author vapier;	state dead;
branches;
next	1.9;

1.9
date	2003.02.14.22.03.48;	author vapier;	state Exp;
branches;
next	1.8;

1.8
date	2002.06.24.23.02.32;	author karltk;	state Exp;
branches;
next	1.7;

1.7
date	2002.05.14.23.31.37;	author karltk;	state Exp;
branches;
next	1.6;

1.6
date	2002.05.12.23.07.21;	author karltk;	state Exp;
branches;
next	1.5;

1.5
date	2002.05.01.14.50.00;	author karltk;	state Exp;
branches;
next	1.4;

1.4
date	2002.05.01.14.48.31;	author karltk;	state Exp;
branches;
next	1.3;

1.3
date	2002.05.01.14.48.06;	author karltk;	state Exp;
branches;
next	1.2;

1.2
date	2002.04.29.22.58.58;	author karltk;	state Exp;
branches;
next	1.1;

1.1
date	2002.01.24.20.45.57;	author karltk;	state Exp;
branches;
next	;


desc
@@


1.10
log
@moved to own package
@
text
@#!/usr/bin/python
# Copyright 1999-2003 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2
# $Header: /home/cvsroot/gentoo-x86/app-admin/gentoolkit/files/lintool/lintool,v 1.9 2003/02/14 22:03:48 vapier Exp $
# Author Karl Trygve Kalleberg <karltk@@gentoo.org>
#
# About:
# lintool checks if a set of ebuilds conforms to the ebuild style guide.
# This is not (yet) an exhaustive test, so your ebuild might be broken even 
# if lintool thinks it's okay.
#
# Usage: lintool /usr/portage/*/*/*.ebuild
# Options: 
#  --no-summary     : Do not show total summary
#  --show-separate  : Show short summary of tests for each ebuild checked
#  --show-details   : Show full details of tests for each ebuild checked
#
# TODO
#
# - Make HTMLFormatter
#
#

import sys
import re
import getopt

class TextFormatter:
  def section(self, s):
    print "\n" + "-"*79
    print " " + s + "\n"
  def bullet(self, s):
    print "* " + s
  def sub(self, s):
    print "- " + s
  def subwarn(self, s):
    print "- (W) " + s
  def suberr(self, s):
    print "- (E) " + s
  def subsub(self, s):
    print " |" + s
  def subsubwarn(self, s):
    print " (W) |" + s
  def subsuberr(self, s):
    print " (E) |" + s
  def div(self, left, right):
    l = len(left)
    r = len(right)
    print left + " " * (79-l-r) + right

class Test:
  def __init__(self, formatter):
    self.formatter = formatter
    self.errors = []
    self.warnings = []
  def reset(self):
    self.errors = []
    self.warnings = []
  def hasWarnings(self):
    return len(self.warnings)
  def hasErrors(self):
    return len(self.errors)
  def getDesc(self):
    return self.desc
  def getStatus(self):
    if self.hasErrors():
      return "failed"
    else:
      return "passed"

class TestSpaces(Test):
  def __init__(self, formatter):
    Test.__init__(self, formatter)
    self.desc = "Testing for illegal space characters, weird backslash formatting"
    self.re_spaces = re.compile("^([ ][ ]*)([a-zA-Z\.].*)")
    self.re_backslash = re.compile("([^#]*\S)((\s\s+|\t))\\\\")
    self.spaces = []
    self.backslashes = []
    
  def checkLine(self, s):
    k = self.re_spaces.match(s)
    if k:
      spcs = k.groups()[0]
      rest = k.groups()[1]
      self.spaces.append(spcs.replace(" ", "%") + rest)
    else:
      k = self.re_backslash.match(s)
      if k:
        head = k.group(1)
        spcs = k.group(2)
        tail = "\\"
        self.backslashes.append(head + len(spcs) * "%" + tail)

  def hasErrors(self):
    return 0
  def hasWarning(self):
    return len(self.spaces) + len(self.backslashes)
  
  def report(self):
    if len(self.spaces):
      self.formatter.subwarn("Has illegal space characters (marked by %):")
      for i in self.spaces:
        self.formatter.subsub(i)
    if len(self.backslashes):
      self.formatter.subwarn("Has illegal white space (marked by %), only one space character allowed:")
      for i in self.backslashes:
        self.formatter.subsub(i)

class TestHeaders(Test):

  def __init__(self, formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for malformed headers"
    self.re = [ (1, # append result of regex match
                 re.compile("^(# Copyright 1999-(2000|2001).*)"),
                 "Suspect copyright year"), 
                (1,
                 re.compile("^(# /home.*)"),
                 "Suspect path in header"),
                (0, # don't append result of regex match
                 re.compile("^(# Author.*)"),
                 "Use of Author field in the header is deprecated. Put name in ChangeLog"),
                (0,
                 re.compile("^(# Maintainer.*)"),
                 "Use of Maintainer field in the header is deprecated. Put name in ChangeLog"),
                (1,
                 re.compile("^(# /space.*)"),
                 "Suspect path in header")]

  def checkLine(self, s):
    for i in self.re:
      k = i[1].match(s)
      if k and i[0]:
        self.warnings.append(i[2] + ": " + k.groups()[0] )
      elif k and not i[0]:
        self.warnings.append(i[2])
        
  def report(self):
    if len(self.warnings):
      self.formatter.subwarn("Has illegal or suspect headers:")
      for i in self.warnings:
        self.formatter.subsub(i)

class TestTry(Test):

  def __init__(self,formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for occurence of deprecated try"
    self.re = [ re.compile("^([ \t][ \t]*try.*)"),
                re.compile("(.*=.* try .*)") ]

  def checkLine(self, s):
    for i in self.re:
      k = i.match(s)
      if k:
        self.errors.append(k.groups()[0])

  def report(self):
    if len(self.errors):
      self.formatter.suberr("Uses try, which is deprecated")
      for i in self.errors:
        self.formatter.subsub(i)

class TestA(Test):

  def __init__(self, formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for superfluous A=${P}.tar.gz"
    self.re = re.compile("(A=\$\{P\}.tar.gz)")

  def checkLine(self, s):
    k = self.re.match(s)
    if k:
      self.errors.append(k.groups()[0])

  def report(self):
    if len(self.errors):
      self.formatter.suberr("Contains superfluous " + self.lines[0])
        
class TestDepend(Test):

  def __init__(self, formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for empty DEPEND"
    self.re = re.compile("DEPEND=\"\"")

  def checkLine(self, s):
    k = self.re.match(s)
    if k:
      self.warnings.append("")

  def report(self):
    if len(self.warnings):
      self.formatter.subwarn("DEPEND is suspiciously empty")

class TestHomepage(Test):

  def __init__(self, formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for empty HOMEPAGE"
    self.re = re.compile("HOMEPAGE=\"\"")

  def checkLine(self, s):
    k = self.re.match(s)
    if k:
      self.warnings.append("")

  def report(self):
    if len(self.warnings):
      self.formatter.subwarn("Is HOMEPAGE really supposed to be empty ?")

class TestDescription(Test):

  def __init__(self, formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for empty DESCRIPTION"
    self.re = re.compile("DESCRIPTION=\"\"")

  def checkLine(self, s):
    k = self.re.match(s)
    if k:
      self.errors.append("")

  def report(self):
    if len(self.errors):
      self.formatter.suberr("DESCRIPTION must not be empty")

class TestEnvVarPresence(Test):

  def __init__(self, formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for presence of env vars"
    self.re = []
    self.found = []
    self.required = [ "SRC_URI=",
                      "DESCRIPTION=",
                      "HOMEPAGE=",
                      "DEPEND=",
                      "RDEPEND=",
                      "LICENSE="
                      ]
    self.desired = [ "SLOT=",
                     "S="]

    for i in self.required:
      self.re.append(re.compile("^(" + i + ")"))
    for i in self.desired:
      self.re.append(re.compile("^(" + i + ")"))
      
  def checkLine(self, s):
    for i in self.re:
      k = i.match(s)
      if k:
        self.found.append(k.group(1))

  def report(self):
    for i in self.required:
      if i not in self.found:
        self.formatter.suberr("Missing " + i)
    for i in self.desired:
      if i not in self.found:
        self.formatter.subwarn("Missing " + i)

  def hasWarnings(self):
    for i in self.desired:
      if i not in self.found:
        return 1

  def hasErrors(self):
    for i in self.required:
      if i not in self.found:
        return 1

class TestUseFlags(Test):
  def __init__(self, formatter):
    Test.__init__(self,formatter)
    self.desc = "Testing for sane USE flag usage"
    self.re = re.compile("[^#]*use ([a-z0-9]+).*")
    self.useflags = self.loadUseFlags()

  def loadUseFlags(self):
    ins = open("/usr/portage/profiles/use.desc")
    rex = re.compile("^([a-z0-9]+)[ \t]+-.*");
    useflags = []
    for i in ins.readlines():
      k = rex.match(i)
      if k:
        useflags.append(k.group(1))
    return useflags
    
  def checkLine(self, s):
    k = self.re.match(s)
    if k:
      flag = k.group(1)
      if flag not in self.useflags:
        l = k.start(1)
        # We want to try and figure pretty exactly if we've hit a real instnce
        # of the use command or just some random mumbling inside a string
        numApostrophes = 0
        numBackticks = 0
        numTicks = 0
        for i in xrange(l,0,-1):
          if s[i] == '\"' and (i == 0 or (i > 0 and s[i-1] != '\\')):
            numApostrophes += 1
          if s[i] == '\'' and (i == 0 or (i > 0 and s[i-1] != '\\')):
            numTicks += 1
          if s[i] == '`' and (i == 0 or (i > 0 and s[i-1] != '\\')):
            numBackticks += 1

        if numApostrophes % 2 == 0:
          foundError = 1
        elif numBackticks % 2 and numTicks % 2 == 0:
          foundError = 1
        else:
          foundError = 0

        if foundError:
          self.errors.append("Unknown USE flag '" + flag + "'")

  def report(self):
    for i in self.errors:
      self.formatter.suberr(i)
       
def extractFilename(path):
  return path

def runTests(tests,results,ins):
  for j in tests:
    j.reset()

  for i in ins.readlines():
    for j in tests:
      j.checkLine(i)

  hasWarning = 0
  hasError = 0
  for j in xrange(len(tests)):
    if tests[j].hasErrors():
      results[j][0] += 1
      hasError = 1
    if tests[j].hasWarnings():
      results[j][1] += 1
      hasWarning = 1
  return (hasError, hasWarning)
        
def showStatus(options,tests,formatter,file):
  if options['showDetails'] or options['showSeparate']:
    formatter.section("Status for " + file)
    for j in tests:
      if options['showSeparate'] or options['showDetails']:
        l = len(j.getDesc())
        formatter.bullet(j.getDesc() + " " * (70 - l) + ": " + j.getStatus())
        if options['showDetails']:
          j.report()
  elif options['showShort']:
    allOK = 1
    for j in tests:
      if j.hasErrors():
        allOK = 0
        break
    if allOK:
      formatter.div(file, ": OK")
    else:
      formatter.div(file, ": Not OK")
    # else fall through the bottom    
    
def usage(opts):
  print sys.argv[0], "[options] ebuild [ebuild ebuild ... ]"
  print

  print "Where [options] include:"
  for (short,long_,desc) in opts:
    short_ = ''
    for s in short:
      short_ = short_ + '-' + s + ','
    long_ = '--' + long_
    opt = short_ + long_
    opt = opt.rjust(18)
    print opt + '  ' + desc
  print

def parse_opts(argv):
  options = { 'showSeparate': 0,
              'showTotal': 1,
              'showDetails': 0,
              'showShort': 1,
              'listTests': 0,
	      'desiredTests': 0
            }

  opts = (('', 'show-separate',
           'Show short summary of tests for each ebuild checked'),

          ('', 'no-summary',
           'Do not show total summary'),

          ('', 'show-details',
           'Show full details of tests for each ebuild checked'),

          ('', 'tests=',
           'Specify which tests to run'),

          ('', 'list-tests',
           'List available tests'),

          ('', 'ebuilds=<file>',
           'Read ebuilds from <file>'),
          
          ('?h', 'help',
           'Show this help'),
         )

  short_options = ''
  long_options = []
  for (short,long_,desc) in opts:
    short_options = short_options + short
    if '=' in long_:
      long_ = long_.split('=', 1)[0] + '='
    long_options.append(long_)

  try:
    (option_list,args) = getopt.getopt(sys.argv[1:], short_options, long_options)
  except getopt.GetoptError, details:
    print 'Error parsing command line:',str(details)
    sys.exit(1)

  for (option,value) in option_list:
    if option in [ '--show-details' ]:
      options['showShort'] = 0
      options['showDetails'] = 1
    elif option in [ '--show-separate' ]:
      options['showShort'] = 0
      options['showSeparate'] = 1
    elif option in [ '--no-summary']:
      options['showTotal'] = 0
    elif option in [ '--from-file' ]:
      lines = open(value, 'r').readlines()
      lines = [o.strip() for o in lines]
      args = lines + args
    elif option in [ '--tests' ]:
      options['desiredTests'] = value.split(",")
    elif option in [ '--list-tests' ]:
      options['listTests'] = 1
    elif option in [ '--ebuild' ]:
      options['testmode'] = 'ebuild'
    elif option in [ '--changelog' ]:
      options['testmode'] = 'changelog'
    elif option in [ '-h', '-?', '--help' ]:
      usage(opts)
      sys.exit(0)
    else:
      # shouldn't ever happen. better to be safe
      print "Unknown option - '%s'!" % (option)
      sys.exit(1)

  return (options,args)

def main():
    (options,args) = parse_opts(sys.argv[1:])

    
    formatter = TextFormatter()
    available_tests = [ TestSpaces(formatter),
                        TestHeaders(formatter),
                        TestTry(formatter),
                        TestA(formatter),
                        TestDepend(formatter),
                        TestHomepage(formatter),
                        TestDescription(formatter),
                        TestEnvVarPresence(formatter),
                        TestUseFlags(formatter) ]
    
    if options['listTests']:
      maxlen = 0
      for i in available_tests:
        maxlen = max(len(i.__class__.__name__), maxlen)
      for i in available_tests:
        n = i.__class__.__name__
        print n + " " * (maxlen - len(n)) + " - " + i.getDesc()

    if len(args) == 0:
      sys.exit(1)
      
    tests = []
    notTests = []
    if options['desiredTests']:
      for i in options['desiredTests']:
        for j in available_tests:
          if len(i) and i[0] == "-":
            notTests.append(i[1:])
          if j.__class__.__name__ == i:
            tests.append(j)
    else:
      tests = available_tests

    if len(notTests):
      for i in available_tests:
        if i.__class__.__name__ not in notTests:
          tests.append(i)
      
    results = [[0, 0] for x in range(len(tests))]
    
    numFiles = 0
    totalErrors = 0
    totalWarnings = 0
    
    for i in args:
      fn = extractFilename(i)
      ins = open(i, "r")
      numFiles += 1
      (hasError, hasWarning) = runTests(tests,results,ins)
      totalErrors += hasError
      totalWarnings += hasWarning
      showStatus(options,tests,formatter,fn)
    
    if options['showTotal']:
      print "\n" + "-"*79
      s = " Summary for all " + str(numFiles) + " ebuild(s) checked"
      print s + " " * (65 - len(s)) + "# errors/warns"
      print "-"*79
      for i in xrange(len(tests)):
        l = len(tests[i].getDesc())
        print tests[i].getDesc() + " " * (66 - l) + ": " + \
              str(results[i][0]) + " / " + str(results[i][1])
      print
      print "Total number of ebuilds with errors                               : " + str(totalErrors) + \
            " (" + str(totalErrors*100/numFiles) + "%)"
      print "Total number of ebuilds with warnings                             : " + str(totalWarnings) + \
            " (" + str(totalWarnings*100/numFiles) + "%)"

      if totalErrors:
        sys.exit(1)

if __name__ == "__main__":
  main()

@


1.9
log
@update copyright info
@
text
@d4 1
a4 1
# $Header: $
@


1.8
log
@Fixes #2900.
@
text
@d1 4
a4 4
#! /usr/bin/python
#
# Copyright 2002 Gentoo Technologies, Inc
# Distributed under the terms of the GNU General Public License v2.0
@


1.7
log
@Fixes #2714 and a few other minor details.
@
text
@d436 1
a436 1
    elif option in [ '--ebuilds' ]:
d444 4
d530 4
a533 1
        
@


1.6
log
@Fixed --list-tests
@
text
@a20 1
# - Check LICENSE against known licenses
d36 4
d42 4
a67 2
    elif self.hasWarnings():
      return "passed (with warnings)"
d95 2
d101 1
a101 1
      self.formatter.sub("Has illegal space characters (marked by %):")
d105 1
a105 1
      self.formatter.sub("Has illegal white space (marked by %), only one space character allowed:")
d114 2
a115 1
    self.re = [ (re.compile("^(# Copyright 1999-(2000|2001).*)"),
d117 2
a118 1
                (re.compile("^(# /home.*)"),
d120 8
a127 5
                (re.compile("^(# Authors:.*)"),
                 "Should use two Author: lines instead"),
                (re.compile("^(# Maintainerss:.*)"),
                 "Should use two Maintainer: lines instead"),
                (re.compile("^(# /space.*)"),
d132 6
a137 4
      k = i[0].match(s)
      if k:
        self.warnings.append(i[1] + ": " + k.groups()[0] )

d140 1
a140 1
      self.formatter.sub("Has illegal or suspect headers:")
d160 1
a160 1
      self.formatter.sub("Uses try, which is deprecated")
d178 1
a178 1
      self.formatter.sub("Contains superfluous " + self.lines[0])
d194 1
a194 1
      self.formatter.sub("DEPEND is suspiciously empty")
d210 1
a210 1
      self.formatter.sub("Is HOMEPAGE really supposed to be empty ?")
d226 1
a226 1
      self.formatter.sub("DESCRIPTION must not be empty")
d232 1
a232 1
    self.desc = "Testing for presence of SRC_URI, HOMEPAGE, .."
d242 1
a242 3
    self.desired = [ "# Author:",
                     "# Maintainer:",
                     "SLOT=",
d259 1
a259 1
        self.formatter.sub("Missing " + i)
d262 1
a262 1
        self.formatter.sub("Missing " + i)
d296 23
a318 1
        self.errors.append("Unknown USE flag '" + flag + "'")
d322 1
a322 1
      self.formatter.sub(i)
d335 2
d340 1
d343 2
d347 1
a347 1
  if options['showFullStatus'] or options['showSeparate']:
d350 1
a350 1
      if options['showSeparate']:
d353 1
a353 1
        if options['showFullStatus']:
d385 1
a385 1
              'showFullStatus': 0,
d430 1
a430 1
      options['showFullStatus'] = 1
d481 1
d485 2
d491 5
d499 4
a502 1
    num_files = 0
d506 4
a509 2
      num_files += 1
      runTests(tests,results,ins)
d514 1
a514 1
      s = " Summary for all " + str(num_files) + " ebuild(s) checked"
d521 5
@


1.5
log
@Whoops3
@
text
@d403 1
a403 1
    elif option in [ '--listTests' ]:
@


1.4
log
@Whoops2
@
text
@d230 1
a230 1
                     "SLOT="
@


1.3
log
@Whoops
@
text
@d348 1
a348 1
              'listTests': 0
@


1.2
log
@New lintool
@
text
@d349 1
@


1.1
log
@Initial import of Gentoolkit
@
text
@d12 1
a12 1
# Usage: ebuildchecker.py /usr/portage/*/*/*.ebuild
a19 2
# - New checks:
#    - presence of all required env vars (HOMEPAGE, SRC_URI, S, DESCRIPTION)
d21 1
a21 1
# - Sort errors into errors and warnings
d27 1
d30 13
a42 13
    def section(self, s):
        print "\n" + "-"*79
        print " " + s + "\n"
    def bullet(self, s):
        print "* " + s
    def sub(self, s):
        print "- " + s
    def subsub(self, s):
        print " |" + s
    def div(self, left, right):
        l = len(left)
        r = len(right)
        print left + " " * (79-l-r) + right
d45 21
a65 12
    def __init__(self, formatter):
        self.formatter = formatter
    def reset(self):
        self.lines = []
    def isOK(self):
        return len(self.lines) == 0
    def getDesc(self):
        return self.desc
    def getStatus(self):
        if self.isOK(): return "passed"
        else: return "failed"
        
d67 34
a100 19

    def __init__(self, formatter):
        Test.__init__(self, formatter)
        self.desc = "Testing for illegal spaces at the start of the line"
        self.re = re.compile("^([ ][ ]*)([a-zA-Z\.].*)")
        self.lines = []

    def checkLine(self, s):
        k = self.re.match(s)
        if k:
            spcs = k.groups()[0]
            rest = k.groups()[1]
            self.lines.append(spcs.replace(" ", "%") + rest)

    def report(self):
        if len(self.lines):
            self.formatter.sub("Has illegal spaces (marked by %):")
            for i in self.lines:
                self.formatter.subsub(i)
d104 25
a128 18
    def __init__(self, formatter):
        Test.__init__(self,formatter)
        self.desc = "Testing for malformed headers"
        self.re = [ re.compile("^(# Copyright 1999-2000 Gentoo Technologies, Inc.)"),
                    re.compile("^(# /home.*)") ]
        self.lines = []

    def checkLine(self, s):
        for i in self.re:
            k = i.match(s)
            if k:
                self.lines.append(k.groups()[0])

    def report(self):
        if len(self.lines):
            self.formatter.sub("Has illegal or suspect headers:")
            for i in self.lines:
                self.formatter.subsub(i)
d132 17
a148 18
    def __init__(self,formatter):
        Test.__init__(self,formatter)
        self.desc = "Testing for occurence of deprecated try"
        self.re = [ re.compile("^([ \t][ \t]*try.*)"),
                    re.compile("(.*=.* try .*)") ]
        self.lines = []

    def checkLine(self, s):
        for i in self.re:
            k = i.match(s)
            if k:
                self.lines.append(k.groups()[0])

    def report(self):
        if len(self.lines):
            self.formatter.sub("Uses try, which is deprecated")
            for i in self.lines:
                self.formatter.subsub(i)
d152 13
a164 14
    def __init__(self, formatter):
        Test.__init__(self,formatter)
        self.desc = "Testing for unnecessary A=${P}.tar.gz"
        self.re = re.compile("(A=\$\{P\}.tar.gz)")
        self.lines = []

    def checkLine(self, s):
        k = self.re.match(s)
        if k:
            self.lines.append(k.groups()[0])

    def report(self):
        if len(self.lines):
            self.formatter.sub("Contains unnecessary " + self.lines[0])
d168 13
a180 14
    def __init__(self, formatter):
        Test.__init__(self,formatter)
        self.desc = "Testing for empty DEPEND"
        self.re = re.compile("DEPEND=\"\"")
        self.lines = []

    def checkLine(self, s):
        k = self.re.match(s)
        if k:
            self.lines.append("")

    def report(self):
        if len(self.lines):
            self.formatter.sub("Is DEPENDS supposed to be empty ?")
d184 13
a196 14
    def __init__(self, formatter):
        Test.__init__(self,formatter)
        self.desc = "Testing for empty HOMEPAGE"
        self.re = re.compile("HOMEPAGE=\"\"")
        self.lines = []

    def checkLine(self, s):
        k = self.re.match(s)
        if k:
            self.lines.append("")

    def report(self):
        if len(self.lines):
            self.formatter.sub("Is HOMEPAGE really supposed to be empty ?")
d200 13
a212 14
    def __init__(self, formatter):
        Test.__init__(self,formatter)
        self.desc = "Testing for empty DESCRIPTION"
        self.re = re.compile("DESCRIPTION=\"\"")
        self.lines = []

    def checkLine(self, s):
        k = self.re.match(s)
        if k:
            self.lines.append("")

    def report(self):
        if len(self.lines):
            self.formatter.sub("DESCRIPTION is empty")
d216 21
a236 12
   def __init__(self, formatter):
      Test.__init__(self,formatter)
      self.desc = "Testing for presence of SRC_URI, HOMEPAGE, .."
      self.re = []
      self.found = []
      self.required = ["SRC_URI=", "DESCRIPTION=", "HOMEPAGE=" ]
      self.desired = [ "# Author:", "# Maintainer:", "DEPEND=", "RDEPEND=", "S="]

      for i in self.required:
          self.re.append(re.compile("^(" + i + ")"))
      for i in self.desired:
          self.re.append(re.compile("^(" + i + ")"))
d238 51
a288 24
   def checkLine(self, s):
       for i in self.re:
           k = i.match(s)
           if k:
               self.found.append(k.group(1))

   def report(self):
       for i in self.required:
           if i not in self.found:
               self.formatter.sub("Missing " + i)
       for i in self.desired:
           if i not in self.found:
               self.formatter.sub("Missing " + i)

   def isOK(self):
       warn = error = 0
       for i in self.required:
           if i not in self.found:
               error = 1
       for i in self.desired:
           if i not in self.found:
               warn = 1
       return (warn + error) == 0
       
d291 5
a295 1
    return path
d297 1
a297 1
def runTests(ins):
d299 1
a299 1
        j.reset()
d301 5
a305 7
    for i in ins.readlines():
        for j in tests:
            j.checkLine(i)

    for j in xrange(len(tests)):
        if not tests[j].isOK():
            result[j] += 1
d307 17
a323 9
def showStatus(file):
    if showFullStatus or showSeparate:
        formatter.section("Status for " + file)
        for j in tests:
            if showSeparate:
                l = len(j.getDesc())
                formatter.bullet(j.getDesc() + " " * (70 - l) + ": " + j.getStatus())
            if showFullStatus:
                j.report()
d325 2
a326 9
        allOK = 1
        for j in tests:
            if not j.isOK():
                allOK = 0
                break
        if allOK:
            formatter.div(file, ": OK")
        else:
            formatter.div(file, ": Not OK")
d328 83
d412 1
a412 1
formatter = TextFormatter()
d414 32
a445 29
tests = [ TestSpaces(formatter),
          TestHeaders(formatter),
          TestTry(formatter),
          TestA(formatter),
          TestDepend(formatter),
          TestHomepage(formatter),
          TestDescription(formatter),
          TestEnvVarPresence(formatter) ]

result = range(len(tests))

showSeparate   = 0
showTotal      = 1
showFullStatus = 0
showShort      = 1

for i in xrange(len(result)): result[i] = 0


for i in sys.argv[1:]:
    if len(i) > 2 and i[0:2] == "--":
        if i == "--show-details":
            showShort = 0
            showFullStatus = 1
        if i == "--show-separate":
            showShort = 0
            showSeparate = 1
        if i == "--no-summary":
            showTotal = 0
d447 24
a470 5
        fn = extractFilename(i)
        ins = open(i, "r")
        runTests(ins)
        if showSeparate or showFullStatus or showShort:
            showStatus(fn)
a471 7
if showTotal:
    print "\n" + "-"*79
    print " Summary for all ebuilds checked" + " " * 39 + "# fails"
    print "-"*79
    for i in xrange(len(tests)):
        l = len(tests[i].getDesc())
        print tests[i].getDesc() + " " * (70 - l) + ": " + str(result[i])
@

