| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Top-level presubmit script for Chromium. | 6 """Top-level presubmit script for Chromium. |
| 7 | 7 |
| 8 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for | 8 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for |
| 9 details on the presubmit API built into gcl. | 9 details on the presubmit API built into gcl. |
| 10 """ | 10 """ |
| 11 | 11 |
| 12 # Files with these extensions are considered source files. | 12 EXCLUDED_PATHS = ( |
| 13 SOURCE_FILE_EXTENSIONS = [ | |
| 14 '.c', '.cc', '.cpp', '.h', '.m', '.mm', '.py', '.mk', '.am', '.json', | |
| 15 ] | |
| 16 EXCLUDED_PATHS = [ | |
| 17 r"breakpad[\\\/].*", | 13 r"breakpad[\\\/].*", |
| 18 r"chrome[\\\/]Debug[\\\/].*", | |
| 19 r"chrome[\\\/]Release[\\\/].*", | |
| 20 r"sconsbuild[\\\/].*", | |
| 21 r"xcodebuild[\\\/].*", | |
| 22 r"skia[\\\/].*", | 14 r"skia[\\\/].*", |
| 23 r".*third_party[\\\/].*", | |
| 24 r"v8[\\\/].*", | 15 r"v8[\\\/].*", |
| 25 ] | 16 ) |
| 26 | 17 |
| 27 | 18 |
| 28 def CheckChangeOnUpload(input_api, output_api): | 19 def CheckChangeOnUpload(input_api, output_api): |
| 29 # TODO(maruel): max_cols is temporarily disabled. Reenable once the source | |
| 30 # tree is in better shape. | |
| 31 results = [] | 20 results = [] |
| 32 results.extend(LocalChecks(input_api, output_api, max_cols=0)) | 21 # What does this code do? |
| 22 # It loads the default black list (e.g. third_party, experimental, etc) and |
| 23 # add our black list (breakpad, skia and v8 are still not following |
| 24 # google style and are not really living this repository). |
| 25 # See presubmit_support.py InputApi.FilterSourceFile for the (simple) usage. |
| 26 black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS |
| 27 sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list) |
| 28 |
| 29 results.extend(input_api.canned_checks.CheckLongLines(input_api, |
| 30 output_api, |
| 31 sources)) |
| 32 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(input_api, |
| 33 output_api, |
| 34 sources)) |
| 33 results.extend(input_api.canned_checks.CheckChangeHasBugField(input_api, | 35 results.extend(input_api.canned_checks.CheckChangeHasBugField(input_api, |
| 34 output_api)) | 36 output_api)) |
| 35 results.extend(input_api.canned_checks.CheckChangeHasTestField(input_api, | 37 results.extend(input_api.canned_checks.CheckChangeHasTestField(input_api, |
| 36 output_api)) | 38 output_api)) |
| 39 results.extend(input_api.canned_checks.CheckChangeSvnEolStyle(input_api, |
| 40 output_api, |
| 41 sources)) |
| 37 return results | 42 return results |
| 38 | 43 |
| 39 | 44 |
| 40 def CheckChangeOnCommit(input_api, output_api): | 45 def CheckChangeOnCommit(input_api, output_api): |
| 41 results = [] | 46 results = [] |
| 42 # TODO(maruel): max_cols is temporarily disabled. Reenable once the source | 47 black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS |
| 43 # tree is in better shape. | 48 sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list) |
| 44 results.extend(LocalChecks(input_api, output_api, max_cols=0)) | 49 results.extend(input_api.canned_checks.CheckLongLines(input_api, |
| 50 output_api, |
| 51 sources)) |
| 52 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(input_api, |
| 53 output_api, |
| 54 sources)) |
| 45 results.extend(input_api.canned_checks.CheckChangeHasBugField(input_api, | 55 results.extend(input_api.canned_checks.CheckChangeHasBugField(input_api, |
| 46 output_api)) | 56 output_api)) |
| 47 results.extend(input_api.canned_checks.CheckChangeHasTestField(input_api, | 57 results.extend(input_api.canned_checks.CheckChangeHasTestField(input_api, |
| 48 output_api)) | 58 output_api)) |
| 59 results.extend(input_api.canned_checks.CheckChangeSvnEolStyle(input_api, |
| 60 output_api, |
| 61 sources)) |
| 49 # Make sure the tree is 'open'. | 62 # Make sure the tree is 'open'. |
| 63 # TODO(maruel): Run it in a separate thread to parallelize checks? |
| 50 results.extend(input_api.canned_checks.CheckTreeIsOpen( | 64 results.extend(input_api.canned_checks.CheckTreeIsOpen( |
| 51 input_api, output_api, | 65 input_api, output_api, |
| 52 'http://chromium-status.appspot.com/status', '0' | 66 'http://chromium-status.appspot.com/status', '0' |
| 53 )) | 67 )) |
| 54 results.extend(CheckTryJobExecution(input_api, output_api)) | 68 results.extend(CheckTryJobExecution(input_api, output_api)) |
| 55 return results | 69 return results |
| 56 | 70 |
| 57 | 71 |
| 58 def LocalChecks(input_api, output_api, max_cols=80): | |
| 59 """Reports an error if for any source file in SOURCE_FILE_EXTENSIONS: | |
| 60 - uses CR (or CRLF) | |
| 61 - contains a TAB | |
| 62 - has a line that ends with whitespace | |
| 63 - contains a line >|max_cols| cols unless |max_cols| is 0. | |
| 64 - File does not end in a newline, or ends in more than one. | |
| 65 | |
| 66 Note that the whole file is checked, not only the changes. | |
| 67 """ | |
| 68 C_SOURCE_FILE_EXTENSIONS = ('.c', '.cc', '.cpp', '.h', '.inl') | |
| 69 cr_files = [] | |
| 70 eof_files = [] | |
| 71 results = [] | |
| 72 excluded_paths = [input_api.re.compile(x) for x in EXCLUDED_PATHS] | |
| 73 files = input_api.AffectedFiles(include_deletes=False) | |
| 74 for f in files: | |
| 75 path = f.LocalPath() | |
| 76 root, ext = input_api.os_path.splitext(path) | |
| 77 # Look for unsupported extensions. | |
| 78 if not ext in SOURCE_FILE_EXTENSIONS: | |
| 79 continue | |
| 80 # Look for excluded paths. | |
| 81 found = False | |
| 82 for item in excluded_paths: | |
| 83 if item.match(path): | |
| 84 found = True | |
| 85 break | |
| 86 if found: | |
| 87 continue | |
| 88 | |
| 89 # Need to read the file ourselves since AffectedFile.NewContents() | |
| 90 # will normalize line endings. | |
| 91 contents = input_api.ReadFile(f) | |
| 92 if '\r' in contents: | |
| 93 cr_files.append(path) | |
| 94 | |
| 95 # Check that the file ends in one and only one newline character. | |
| 96 if len(contents) > 0 and (contents[-1:] != "\n" or contents[-2:-1] == "\n"): | |
| 97 eof_files.append(path) | |
| 98 | |
| 99 local_errors = [] | |
| 100 # Remove end of line character. | |
| 101 lines = contents.splitlines() | |
| 102 line_num = 1 | |
| 103 for line in lines: | |
| 104 if line.endswith(' '): | |
| 105 local_errors.append(output_api.PresubmitError( | |
| 106 '%s, line %s ends with whitespaces.' % | |
| 107 (path, line_num))) | |
| 108 # Accept lines with http://, https:// and C #define/#pragma/#include to | |
| 109 # exceed the max_cols rule. | |
| 110 if (max_cols and | |
| 111 len(line) > max_cols and | |
| 112 not 'http://' in line and | |
| 113 not 'https://' in line and | |
| 114 not (line[0] == '#' and ext in C_SOURCE_FILE_EXTENSIONS)): | |
| 115 local_errors.append(output_api.PresubmitError( | |
| 116 '%s, line %s has %s chars, please reduce to %d chars.' % | |
| 117 (path, line_num, len(line), max_cols))) | |
| 118 if '\t' in line: | |
| 119 local_errors.append(output_api.PresubmitError( | |
| 120 "%s, line %s contains a tab character." % | |
| 121 (path, line_num))) | |
| 122 line_num += 1 | |
| 123 # Just show the first 5 errors. | |
| 124 if len(local_errors) == 6: | |
| 125 local_errors.pop() | |
| 126 local_errors.append(output_api.PresubmitError("... and more.")) | |
| 127 break | |
| 128 results.extend(local_errors) | |
| 129 | |
| 130 if cr_files: | |
| 131 results.append(output_api.PresubmitError( | |
| 132 'Found CR (or CRLF) line ending in these files, please use only LF:', | |
| 133 items=cr_files)) | |
| 134 if eof_files: | |
| 135 results.append(output_api.PresubmitError( | |
| 136 'These files should end in one (and only one) newline character:', | |
| 137 items=eof_files)) | |
| 138 return results | |
| 139 | |
| 140 | |
| 141 def CheckTryJobExecution(input_api, output_api): | 72 def CheckTryJobExecution(input_api, output_api): |
| 73 outputs = [] |
| 74 if not input_api.change.issue or not input_api.change.patchset: |
| 75 return outputs |
| 142 url = "http://codereview.chromium.org/%d/get_build_results/%d" % ( | 76 url = "http://codereview.chromium.org/%d/get_build_results/%d" % ( |
| 143 input_api.change.issue, input_api.change.patchset) | 77 input_api.change.issue, input_api.change.patchset) |
| 144 outputs = [] | |
| 145 try: | 78 try: |
| 146 connection = input_api.urllib2.urlopen(url) | 79 connection = input_api.urllib2.urlopen(url) |
| 147 # platform|status|url | 80 # platform|status|url |
| 148 values = [item.split('|', 2) for item in connection.read().splitlines()] | 81 values = [item.split('|', 2) for item in connection.read().splitlines()] |
| 149 connection.close() | 82 connection.close() |
| 150 statuses = map(lambda x: x[1], values) | 83 statuses = map(lambda x: x[1], values) |
| 151 if 'failure' in statuses: | 84 if 'failure' in statuses: |
| 152 failures = filter(lambda x: x[1] != 'success', values) | 85 failures = filter(lambda x: x[1] != 'success', values) |
| 153 long_text = '\n'.join("% 5s: % 7s %s" % (item[0], item[1], item[2]) | 86 long_text = '\n'.join("% 5s: % 7s %s" % (item[0], item[1], item[2]) |
| 154 for item in failures) | 87 for item in failures) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 172 # stable enough and it seems to work fine. | 105 # stable enough and it seems to work fine. |
| 173 outputs.append(output_api.PresubmitNotifyResult( | 106 outputs.append(output_api.PresubmitNotifyResult( |
| 174 'You should try the patch first.')) | 107 'You should try the patch first.')) |
| 175 else: | 108 else: |
| 176 # Another HTTP error happened, warn the user. | 109 # Another HTTP error happened, warn the user. |
| 177 # TODO(maruel): Change to a PresubmitPromptWarning once it deemed to work | 110 # TODO(maruel): Change to a PresubmitPromptWarning once it deemed to work |
| 178 # fine. | 111 # fine. |
| 179 outputs.append(output_api.PresubmitNotifyResult( | 112 outputs.append(output_api.PresubmitNotifyResult( |
| 180 'Got %s while looking for try job status.' % str(e))) | 113 'Got %s while looking for try job status.' % str(e))) |
| 181 return outputs | 114 return outputs |
| OLD | NEW |