Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/python
      2 
      3 """Parse and check syntax errors of a given OWNERS file."""
      4 
      5 import argparse
      6 import re
      7 import sys
      8 import urllib
      9 import urllib2
     10 
     11 parser = argparse.ArgumentParser(description='Check OWNERS file syntax')
     12 parser.add_argument('-v', '--verbose', dest='verbose',
     13                     action='store_true', default=False,
     14                     help='Verbose output to debug')
     15 parser.add_argument('-c', '--check_address', dest='check_address',
     16                     action='store_true', default=False,
     17                     help='Check email addresses')
     18 parser.add_argument(dest='owners', metavar='OWNERS', nargs='+',
     19                     help='Path to OWNERS file')
     20 args = parser.parse_args()
     21 
     22 gerrit_server = 'https://android-review.googlesource.com'
     23 checked_addresses = {}
     24 
     25 
     26 def echo(msg):
     27   if args.verbose:
     28     print msg
     29 
     30 
     31 def find_address(address):
     32   if address not in checked_addresses:
     33     request = (gerrit_server + '/accounts/?n=1&q=email:'
     34                + urllib.quote(address))
     35     echo('Checking email address: ' + address)
     36     result = urllib2.urlopen(request).read()
     37     checked_addresses[address] = result.find('"_account_id":') >= 0
     38     if checked_addresses[address]:
     39       echo('Found email address: ' + address)
     40   return checked_addresses[address]
     41 
     42 
     43 def check_address(fname, num, address):
     44   if find_address(address):
     45     return 0
     46   print '%s:%d: ERROR: unknown email address: %s' % (fname, num, address)
     47   return 1
     48 
     49 
     50 def main():
     51   # One regular expression to check all valid lines.
     52   noparent = 'set +noparent'
     53   email = '([^@ ]+@[^ @]+|\\*)'
     54   emails = '(%s( *, *%s)*)' % (email, email)
     55   file_directive = 'file: *([^ :]+ *: *)?[^ ]+'
     56   directive = '(%s|%s|%s)' % (emails, noparent, file_directive)
     57   glob = '[a-zA-Z0-9_\\.\\-\\*\\?]+'
     58   globs = '(%s( *, *%s)*)' % (glob, glob)
     59   perfile = 'per-file +' + globs + ' *= *' + directive
     60   include = 'include +([^ :]+ *: *)?[^ ]+'
     61   pats = '(|%s|%s|%s|%s|%s)$' % (noparent, email, perfile, include, file_directive)
     62   patterns = re.compile(pats)
     63   address_pattern = re.compile('([^@ ]+@[^ @]+)')
     64   perfile_pattern = re.compile('per-file +.*=(.*)')
     65 
     66   error = 0
     67   for fname in args.owners:
     68     echo('Checking file: ' + fname)
     69     num = 0
     70     for line in open(fname, 'r'):
     71       num += 1
     72       stripped_line = re.sub('#.*$', '', line).strip()
     73       if not patterns.match(stripped_line):
     74         error += 1
     75         print '%s:%d: ERROR: unknown line [%s]' % (fname, num, line.strip())
     76       elif args.check_address:
     77         if perfile_pattern.match(stripped_line):
     78           for addr in perfile_pattern.match(stripped_line).group(1).split(','):
     79             a = addr.strip()
     80             if a and a != '*':
     81               error += check_address(fname, num, addr.strip())
     82         elif address_pattern.match(stripped_line):
     83           error += check_address(fname, num, stripped_line)
     84   sys.exit(error)
     85 
     86 if __name__ == '__main__':
     87   main()
     88