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 27import re 28import sys 29import subprocess 30 31def git(*args, **kwargs): 32 return subprocess.check_output(['git'] + list(args), **kwargs) 33 34def get_changed_paths(filter): 35 output = git('diff', '--cached', '--name-only', '-z', '--diff-filter='+filter) 36 return output.split('\0')[:-1] # remove trailing '' 37 38def 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 47against = get_against() 48 49success = True 50 51def 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 60def 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 75def 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 83guard_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 88def 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 95def check_changed_files(): 96 for path in get_changed_paths('AM'): 97 check_external_guards(open(path)) 98 99def main(): 100 check_filenames() 101 check_changed_files() 102 check_whitespace() 103 if not success: 104 exit(1) 105 106if __name__ == '__main__': 107 main() 108