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