[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 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 Chromium. |
| 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 | |
[email protected] | d5ed857 | 2009-03-15 19:45:53 | [diff] [blame] | 12 | # Files with these extensions will be considered source files. |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 13 | SOURCE_FILE_EXTENSIONS = [ |
| 14 | '.c', '.cc', '.cpp', '.h', '.m', '.mm', '.py', '.mk', '.am', '.json', |
| 15 | ] |
| 16 | EXCLUDED_PATHS = [ |
| 17 | r"breakpad[\\\/].*", |
| 18 | r"chrome[\\\/]Debug[\\\/].*", |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 19 | r"chrome[\\\/]Release[\\\/].*", |
[email protected] | 04a40f84 | 2009-04-01 20:13:04 | [diff] [blame] | 20 | r"sconsbuild[\\\/].*", |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 21 | r"xcodebuild[\\\/].*", |
| 22 | r"skia[\\\/].*", |
| 23 | r".*third_party[\\\/].*", |
| 24 | r"v8[\\\/].*", |
| 25 | ] |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 26 | |
| 27 | def ReadFile(path): |
| 28 | """Given a path, returns the full contents of the file. |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 29 | |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 30 | Reads files in binary format. |
| 31 | """ |
| 32 | fo = open(path, 'rb') |
| 33 | try: |
| 34 | contents = fo.read() |
| 35 | finally: |
| 36 | fo.close() |
| 37 | return contents |
| 38 | |
| 39 | |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 40 | def CheckChangeOnUpload(input_api, output_api): |
[email protected] | b4971ce | 2009-03-05 16:14:55 | [diff] [blame] | 41 | # TODO(maruel): max_cols is temporarily disabled. Reenable once the source |
| 42 | # tree is in better shape. |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame^] | 43 | results = [] |
| 44 | results.extend(LocalChecks(input_api, output_api, max_cols=0)) |
| 45 | results.extend(input_api.canned_checks.CheckChangeHasBugField(input_api, |
| 46 | output_api)) |
| 47 | results.extend(input_api.canned_checks.CheckChangeHasTestField(input_api, |
| 48 | output_api)) |
| 49 | return results |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 50 | |
| 51 | |
| 52 | def CheckChangeOnCommit(input_api, output_api): |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame^] | 53 | results = [] |
[email protected] | b4971ce | 2009-03-05 16:14:55 | [diff] [blame] | 54 | # TODO(maruel): max_cols is temporarily disabled. Reenable once the source |
| 55 | # tree is in better shape. |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame^] | 56 | results.extend(LocalChecks(input_api, output_api, max_cols=0)) |
| 57 | results.extend(input_api.canned_checks.CheckChangeHasBugField(input_api, |
| 58 | output_api)) |
| 59 | results.extend(input_api.canned_checks.CheckChangeHasTestField(input_api, |
| 60 | output_api)) |
| 61 | # Make sure the tree is 'open'. |
| 62 | results.extend(input_api.canned_checks.CheckTreeIsOpen( |
| 63 | input_api, output_api, |
| 64 | 'http://chromium-status.appspot.com/status', '0' |
| 65 | )) |
| 66 | return results |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 67 | |
| 68 | |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 69 | def LocalChecks(input_api, output_api, max_cols=80): |
| 70 | """Reports an error if for any source file in SOURCE_FILE_EXTENSIONS: |
| 71 | - uses CR (or CRLF) |
| 72 | - contains a TAB |
| 73 | - has a line that ends with whitespace |
| 74 | - contains a line >|max_cols| cols unless |max_cols| is 0. |
[email protected] | 2fcccc7 | 2009-03-10 13:55:09 | [diff] [blame] | 75 | - File does not end in a newline, or ends in more than one. |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 76 | |
| 77 | Note that the whole file is checked, not only the changes. |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 78 | """ |
[email protected] | db24f36 | 2009-03-10 17:13:42 | [diff] [blame] | 79 | C_SOURCE_FILE_EXTENSIONS = ('.c', '.cc', '.cpp', '.h', '.inl') |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 80 | cr_files = [] |
[email protected] | 2fcccc7 | 2009-03-10 13:55:09 | [diff] [blame] | 81 | eof_files = [] |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 82 | results = [] |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 83 | excluded_paths = [input_api.re.compile(x) for x in EXCLUDED_PATHS] |
[email protected] | 93372117 | 2009-03-13 04:35:37 | [diff] [blame] | 84 | files = input_api.AffectedFiles(include_deletes=False) |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 85 | for f in files: |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 86 | path = f.LocalPath() |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 87 | root, ext = input_api.os_path.splitext(path) |
| 88 | # Look for unsupported extensions. |
| 89 | if not ext in SOURCE_FILE_EXTENSIONS: |
| 90 | continue |
| 91 | # Look for excluded paths. |
| 92 | found = False |
| 93 | for item in excluded_paths: |
| 94 | if item.match(path): |
| 95 | found = True |
| 96 | break |
| 97 | if found: |
| 98 | continue |
| 99 | |
| 100 | # Need to read the file ourselves since AffectedFile.NewContents() |
| 101 | # will normalize line endings. |
[email protected] | 085bdc92 | 2009-06-04 00:00:42 | [diff] [blame] | 102 | contents = ReadFile(f.AbsoluteLocalPath()) |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 103 | if '\r' in contents: |
| 104 | cr_files.append(path) |
| 105 | |
[email protected] | 2fcccc7 | 2009-03-10 13:55:09 | [diff] [blame] | 106 | # Check that the file ends in one and only one newline character. |
| 107 | if len(contents) > 0 and (contents[-1:] != "\n" or contents[-2:-1] == "\n"): |
| 108 | eof_files.append(path) |
| 109 | |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 110 | local_errors = [] |
[email protected] | 9e93059 | 2009-04-26 01:36:48 | [diff] [blame] | 111 | # Remove end of line character. |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 112 | lines = contents.splitlines() |
| 113 | line_num = 1 |
| 114 | for line in lines: |
| 115 | if line.endswith(' '): |
| 116 | local_errors.append(output_api.PresubmitError( |
| 117 | '%s, line %s ends with whitespaces.' % |
| 118 | (path, line_num))) |
[email protected] | db24f36 | 2009-03-10 17:13:42 | [diff] [blame] | 119 | # Accept lines with http://, https:// and C #define/#pragma/#include to |
| 120 | # exceed the max_cols rule. |
| 121 | if (max_cols and |
| 122 | len(line) > max_cols and |
| 123 | not 'http://' in line and |
| 124 | not 'https://' in line and |
| 125 | not (line[0] == '#' and ext in C_SOURCE_FILE_EXTENSIONS)): |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 126 | local_errors.append(output_api.PresubmitError( |
| 127 | '%s, line %s has %s chars, please reduce to %d chars.' % |
| 128 | (path, line_num, len(line), max_cols))) |
| 129 | if '\t' in line: |
| 130 | local_errors.append(output_api.PresubmitError( |
| 131 | "%s, line %s contains a tab character." % |
| 132 | (path, line_num))) |
| 133 | line_num += 1 |
| 134 | # Just show the first 5 errors. |
| 135 | if len(local_errors) == 6: |
| 136 | local_errors.pop() |
| 137 | local_errors.append(output_api.PresubmitError("... and more.")) |
| 138 | break |
| 139 | results.extend(local_errors) |
| 140 | |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 141 | if cr_files: |
| 142 | results.append(output_api.PresubmitError( |
| 143 | 'Found CR (or CRLF) line ending in these files, please use only LF:', |
| 144 | items=cr_files)) |
[email protected] | 2fcccc7 | 2009-03-10 13:55:09 | [diff] [blame] | 145 | if eof_files: |
| 146 | results.append(output_api.PresubmitError( |
| 147 | 'These files should end in one (and only one) newline character:', |
| 148 | items=eof_files)) |
[email protected] | ca8d1984 | 2009-02-19 16:33:12 | [diff] [blame] | 149 | return results |