Home | History | Annotate | Download | only in src_util
      1 #!/usr/bin/env python
      2 # -*- coding: utf-8 -*-
      3 
      4 #-------------------------------------------------------------------------
      5 # drawElements Quality Program utilities
      6 # --------------------------------------
      7 #
      8 # Copyright 2015 The Android Open Source Project
      9 #
     10 # Licensed under the Apache License, Version 2.0 (the "License");
     11 # you may not use this file except in compliance with the License.
     12 # You may obtain a copy of the License at
     13 #
     14 #      http://www.apache.org/licenses/LICENSE-2.0
     15 #
     16 # Unless required by applicable law or agreed to in writing, software
     17 # distributed under the License is distributed on an "AS IS" BASIS,
     18 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     19 # See the License for the specific language governing permissions and
     20 # limitations under the License.
     21 #
     22 #-------------------------------------------------------------------------
     23 
     24 # Check that the input file has no external include guards.
     25 # Returns with 0 exit code on success, 1 otherwise.
     26 
     27 import re
     28 import sys
     29 import subprocess
     30 
     31 def git(*args, **kwargs):
     32     return subprocess.check_output(['git'] + list(args), **kwargs)
     33 
     34 def get_changed_paths(filter):
     35     output = git('diff', '--cached', '--name-only', '-z', '--diff-filter='+filter)
     36     return output.split('\0')[:-1] # remove trailing ''
     37 
     38 def get_against():
     39     try:
     40         head = git('rev-parse', '--verify', 'HEAD', stderr=None)
     41     except subprocess.CalledProcessError:
     42         # Initial commit: diff against an empty tree object
     43         return '4b825dc642cb6eb9a060e54bf8d69288fbee4904'
     44     else:
     45         return 'HEAD'
     46 
     47 against = get_against()
     48 
     49 success = True
     50 
     51 def croak(path, line, msg, *args):
     52     global success
     53     success = False
     54     if path is not None:
     55         sys.stderr.write("%s:%d: " % (path, line or 0))
     56     sys.stderr.write(msg % args if args else msg)
     57     if msg[-1] != '\n':
     58         sys.stderr.write('\n')
     59 
     60 def check_filenames():
     61     try:
     62         allownonascii = git('config', '--get', '--bool', 'hooks.allownonascii')
     63     except subprocess.CalledProcessError:
     64         pass
     65     else:
     66         if allownonascii == 'true':
     67             return
     68 
     69     for path in get_changed_paths('ACR'):
     70         try:
     71             path.decode('ascii')
     72         except UnicodeDecodeError:
     73             croak(path, 0, "Non-ASCII file name")
     74 
     75 def check_whitespace():
     76     try:
     77         git('diff-index', '--check', '--cached', against, stderr=None)
     78     except subprocess.CalledProcessError as e:
     79         sys.stderr.write(e.output)
     80         global success
     81         success = False
     82 
     83 guard_re = re.compile('^[ \t]*#\s*ifndef\s+_.*?_H(PP)?\n'
     84                       '\s*#\s*include\s+(".*?")\s*\n'
     85                       '\s*#\s*endif.*?$',
     86                       re.MULTILINE)
     87 
     88 def check_external_guards (infile):
     89     contents = infile.read()
     90     for m in guard_re.finditer(contents):
     91         lineno = 1 + contents[:m.start()].count('\n')
     92         croak(infile.name, lineno, "External include guard")
     93         croak(None, None, m.group(0))
     94 
     95 def check_changed_files():
     96     for path in get_changed_paths('AM'):
     97         check_external_guards(open(path))
     98 
     99 def main():
    100     check_filenames()
    101     check_changed_files()
    102     check_whitespace()
    103     if not success:
    104         exit(1)
    105 
    106 if __name__ == '__main__':
    107     main()
    108