1 #!/usr/bin/python 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 """Top-level presubmit script for googleurl. 7 8 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for 9 details on the presubmit API built into gcl. 10 """ 11 12 # Files with these extensions will be considered source files 13 SOURCE_FILE_EXTENSIONS = [ 14 '.c', '.cc', '.cpp', '.h', '.m', '.mm', '.py', '.mk', '.am', '.json', 15 ] 16 EXCLUDED_PATHS = [ 17 r".*third_party[\\\/].*", 18 ] 19 20 def ReadFile(path): 21 """Given a path, returns the full contents of the file. 22 23 Reads files in binary format. 24 """ 25 fo = open(path, 'rb') 26 try: 27 contents = fo.read() 28 finally: 29 fo.close() 30 return contents 31 32 33 def CheckChangeOnUpload(input_api, output_api): 34 # TODO(brettw) Enforce 80 cols. 35 return LocalChecks(input_api, output_api, max_cols=0) 36 37 38 def CheckChangeOnCommit(input_api, output_api): 39 # TODO(brettw) Enforce 80 cols. 40 return (LocalChecks(input_api, output_api, max_cols=0) + 41 input_api.canned_checks.CheckDoNotSubmit(input_api, output_api)) 42 43 44 def LocalChecks(input_api, output_api, max_cols=80): 45 """Reports an error if for any source file in SOURCE_FILE_EXTENSIONS: 46 - uses CR (or CRLF) 47 - contains a TAB 48 - has a line that ends with whitespace 49 - contains a line >|max_cols| cols unless |max_cols| is 0. 50 51 Note that the whole file is checked, not only the changes. 52 """ 53 cr_files = [] 54 results = [] 55 excluded_paths = [input_api.re.compile(x) for x in EXCLUDED_PATHS] 56 files = input_api.AffectedFiles() 57 for f in files: 58 path = f.LocalPath() 59 root, ext = input_api.os_path.splitext(path) 60 # Look for unsupported extensions. 61 if not ext in SOURCE_FILE_EXTENSIONS: 62 continue 63 # Look for excluded paths. 64 found = False 65 for item in excluded_paths: 66 if item.match(path): 67 found = True 68 break 69 if found: 70 continue 71 72 # Need to read the file ourselves since AffectedFile.NewContents() 73 # will normalize line endings. 74 contents = ReadFile(path) 75 if '\r' in contents: 76 cr_files.append(path) 77 78 local_errors = [] 79 # Remove EOL character. 80 lines = contents.splitlines() 81 line_num = 1 82 for line in lines: 83 if line.endswith(' '): 84 local_errors.append(output_api.PresubmitError( 85 '%s, line %s ends with whitespaces.' % 86 (path, line_num))) 87 # Accept lines with http:// to exceed the max_cols rule. 88 if max_cols and len(line) > max_cols and not 'http://' in line: 89 local_errors.append(output_api.PresubmitError( 90 '%s, line %s has %s chars, please reduce to %d chars.' % 91 (path, line_num, len(line), max_cols))) 92 if '\t' in line: 93 local_errors.append(output_api.PresubmitError( 94 "%s, line %s contains a tab character." % 95 (path, line_num))) 96 line_num += 1 97 # Just show the first 5 errors. 98 if len(local_errors) == 6: 99 local_errors.pop() 100 local_errors.append(output_api.PresubmitError("... and more.")) 101 break 102 results.extend(local_errors) 103 104 if cr_files: 105 results.append(output_api.PresubmitError( 106 'Found CR (or CRLF) line ending in these files, please use only LF:', 107 items=cr_files)) 108 return results 109