OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-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 """Generic presubmit checks that can be reused by other presubmit checks.""" | 6 """Generic presubmit checks that can be reused by other presubmit checks.""" |
7 | 7 |
8 | 8 |
| 9 ### Description checks |
| 10 |
9 def CheckChangeHasTestField(input_api, output_api): | 11 def CheckChangeHasTestField(input_api, output_api): |
10 """Requires that the changelist have a TEST= field.""" | 12 """Requires that the changelist have a TEST= field.""" |
11 if input_api.change.TEST: | 13 if input_api.change.TEST: |
12 return [] | 14 return [] |
13 else: | 15 else: |
14 return [output_api.PresubmitNotifyResult( | 16 return [output_api.PresubmitNotifyResult( |
15 "Changelist should have a TEST= field. TEST=none is allowed.")] | 17 "Changelist should have a TEST= field. TEST=none is allowed.")] |
16 | 18 |
17 | 19 |
18 def CheckChangeHasBugField(input_api, output_api): | 20 def CheckChangeHasBugField(input_api, output_api): |
(...skipping 25 matching lines...) Expand all Loading... |
44 """Checks that the user didn't add 'DO NOT ' + 'SUBMIT' to the CL description. | 46 """Checks that the user didn't add 'DO NOT ' + 'SUBMIT' to the CL description. |
45 """ | 47 """ |
46 keyword = 'DO NOT ' + 'SUBMIT' | 48 keyword = 'DO NOT ' + 'SUBMIT' |
47 if keyword in input_api.change.DescriptionText(): | 49 if keyword in input_api.change.DescriptionText(): |
48 return [output_api.PresubmitError( | 50 return [output_api.PresubmitError( |
49 keyword + " is present in the changelist description.")] | 51 keyword + " is present in the changelist description.")] |
50 else: | 52 else: |
51 return [] | 53 return [] |
52 | 54 |
53 | 55 |
| 56 ### Content checks |
| 57 |
54 def CheckDoNotSubmitInFiles(input_api, output_api): | 58 def CheckDoNotSubmitInFiles(input_api, output_api): |
55 """Checks that the user didn't add 'DO NOT ' + 'SUBMIT' to any files.""" | 59 """Checks that the user didn't add 'DO NOT ' + 'SUBMIT' to any files.""" |
56 keyword = 'DO NOT ' + 'SUBMIT' | 60 keyword = 'DO NOT ' + 'SUBMIT' |
57 for f, line_num, line in input_api.RightHandSideLines(): | 61 # We want to check every text files, not just source files. |
| 62 for f, line_num, line in input_api.RightHandSideLines(lambda x: x): |
58 if keyword in line: | 63 if keyword in line: |
59 text = 'Found ' + keyword + ' in %s, line %s' % (f.LocalPath(), line_num) | 64 text = 'Found ' + keyword + ' in %s, line %s' % (f.LocalPath(), line_num) |
60 return [output_api.PresubmitError(text)] | 65 return [output_api.PresubmitError(text)] |
61 return [] | 66 return [] |
62 | 67 |
63 | 68 |
64 def CheckDoNotSubmit(input_api, output_api): | 69 def CheckChangeHasNoCR(input_api, output_api, source_file_filter=None): |
65 return ( | |
66 CheckDoNotSubmitInDescription(input_api, output_api) + | |
67 CheckDoNotSubmitInFiles(input_api, output_api) | |
68 ) | |
69 | |
70 | |
71 def CheckChangeHasNoCR(input_api, output_api): | |
72 """Checks that there are no \r, \r\n (CR or CRLF) characters in any of the | 70 """Checks that there are no \r, \r\n (CR or CRLF) characters in any of the |
73 text files to be submitted. | 71 source files to be submitted. |
74 """ | 72 """ |
75 outputs = [] | 73 outputs = [] |
76 for f in input_api.AffectedTextFiles(): | 74 for f in input_api.AffectedSourceFiles(source_file_filter): |
77 if '\r' in input_api.ReadFile(f, 'rb'): | 75 if '\r' in input_api.ReadFile(f, 'rb'): |
78 outputs.append(output_api.PresubmitPromptWarning( | 76 outputs.append(output_api.PresubmitPromptWarning( |
79 "Found a CR character in %s" % f.LocalPath())) | 77 "Found a CR character in %s" % f.LocalPath())) |
80 return outputs | 78 return outputs |
81 | 79 |
82 | 80 |
83 def CheckChangeHasNoTabs(input_api, output_api): | 81 def CheckChangeHasNoTabs(input_api, output_api, source_file_filter=None): |
84 """Checks that there are no tab characters in any of the text files to be | 82 """Checks that there are no tab characters in any of the text files to be |
85 submitted. | 83 submitted. |
86 """ | 84 """ |
87 for f, line_num, line in input_api.RightHandSideLines(): | 85 for f, line_num, line in input_api.RightHandSideLines(source_file_filter): |
88 if '\t' in line: | 86 if '\t' in line: |
89 return [output_api.PresubmitPromptWarning( | 87 return [output_api.PresubmitPromptWarning( |
90 "Found a tab character in %s, line %s" % | 88 "Found a tab character in %s, line %s" % |
91 (f.LocalPath(), line_num))] | 89 (f.LocalPath(), line_num))] |
92 return [] | 90 return [] |
93 | 91 |
94 | 92 |
95 def CheckLongLines(input_api, output_api, maxlen=80): | 93 def CheckLongLines(input_api, output_api, maxlen=80, source_file_filter=None): |
96 """Checks that there aren't any lines longer than maxlen characters in any of | 94 """Checks that there aren't any lines longer than maxlen characters in any of |
97 the text files to be submitted. | 95 the text files to be submitted. |
98 """ | 96 """ |
99 bad = [] | 97 bad = [] |
100 for f, line_num, line in input_api.RightHandSideLines(): | 98 for f, line_num, line in input_api.RightHandSideLines(source_file_filter): |
101 # Allow lines with http://, https:// and #define/#pragma/#include/#if/#endif | 99 # Allow lines with http://, https:// and #define/#pragma/#include/#if/#endif |
102 # to exceed the maxlen rule. | 100 # to exceed the maxlen rule. |
103 if (len(line) > maxlen and | 101 if (len(line) > maxlen and |
104 not 'http://' in line and | 102 not 'http://' in line and |
105 not 'https://' in line and | 103 not 'https://' in line and |
106 not line.startswith('#define') and | 104 not line.startswith('#define') and |
107 not line.startswith('#include') and | 105 not line.startswith('#include') and |
108 not line.startswith('#pragma') and | 106 not line.startswith('#pragma') and |
109 not line.startswith('#if') and | 107 not line.startswith('#if') and |
110 not line.startswith('#endif')): | 108 not line.startswith('#endif')): |
111 bad.append( | 109 bad.append( |
112 '%s, line %s, %s chars' % | 110 '%s, line %s, %s chars' % |
113 (f.LocalPath(), line_num, len(line))) | 111 (f.LocalPath(), line_num, len(line))) |
114 if len(bad) == 5: # Just show the first 5 errors. | 112 if len(bad) == 5: # Just show the first 5 errors. |
115 break | 113 break |
116 | 114 |
117 if bad: | 115 if bad: |
118 msg = "Found lines longer than %s characters (first 5 shown)." % maxlen | 116 msg = "Found lines longer than %s characters (first 5 shown)." % maxlen |
119 return [output_api.PresubmitPromptWarning(msg, items=bad)] | 117 return [output_api.PresubmitPromptWarning(msg, items=bad)] |
120 else: | 118 else: |
121 return [] | 119 return [] |
122 | 120 |
123 | 121 |
| 122 ### Other checks |
| 123 |
| 124 def CheckDoNotSubmit(input_api, output_api): |
| 125 return ( |
| 126 CheckDoNotSubmitInDescription(input_api, output_api) + |
| 127 CheckDoNotSubmitInFiles(input_api, output_api) |
| 128 ) |
| 129 |
| 130 |
124 def CheckTreeIsOpen(input_api, output_api, url, closed): | 131 def CheckTreeIsOpen(input_api, output_api, url, closed): |
125 """Checks that an url's content doesn't match a regexp that would mean that | 132 """Checks that an url's content doesn't match a regexp that would mean that |
126 the tree is closed.""" | 133 the tree is closed.""" |
127 assert(input_api.is_committing) | 134 assert(input_api.is_committing) |
128 try: | 135 try: |
129 connection = input_api.urllib2.urlopen(url) | 136 connection = input_api.urllib2.urlopen(url) |
130 status = connection.read() | 137 status = connection.read() |
131 connection.close() | 138 connection.close() |
132 if input_api.re.match(closed, status): | 139 if input_api.re.match(closed, status): |
133 long_text = status + '\n' + url | 140 long_text = status + '\n' + url |
134 return [output_api.PresubmitPromptWarning("The tree is closed.", | 141 return [output_api.PresubmitPromptWarning("The tree is closed.", |
135 long_text=long_text)] | 142 long_text=long_text)] |
136 except IOError: | 143 except IOError: |
137 pass | 144 pass |
138 return [] | 145 return [] |
139 | 146 |
140 | 147 |
141 def _RunPythonUnitTests_LoadTests(input_api, module_name): | 148 def _RunPythonUnitTests_LoadTests(input_api, module_name): |
142 """Meant to be stubbed out during unit testing.""" | 149 """Meant to be stubbed out during unit testing.""" |
143 module = __import__(module_name) | 150 module = __import__(module_name) |
144 for part in module_name.split('.')[1:]: | 151 for part in module_name.split('.')[1:]: |
145 module = getattr(module, part) | 152 module = getattr(module, part) |
146 return input_api.unittest.TestLoader().loadTestsFromModule(module)._tests | 153 return input_api.unittest.TestLoader().loadTestsFromModule(module)._tests |
147 | 154 |
| 155 |
148 def RunPythonUnitTests(input_api, output_api, unit_tests): | 156 def RunPythonUnitTests(input_api, output_api, unit_tests): |
149 """Imports the unit_tests modules and run them.""" | 157 """Imports the unit_tests modules and run them.""" |
150 # We don't want to hinder users from uploading incomplete patches. | 158 # We don't want to hinder users from uploading incomplete patches. |
151 if input_api.is_committing: | 159 if input_api.is_committing: |
152 message_type = output_api.PresubmitError | 160 message_type = output_api.PresubmitError |
153 else: | 161 else: |
154 message_type = output_api.PresubmitNotifyResult | 162 message_type = output_api.PresubmitNotifyResult |
155 tests_suite = [] | 163 tests_suite = [] |
156 outputs = [] | 164 outputs = [] |
157 for unit_test in unit_tests: | 165 for unit_test in unit_tests: |
158 try: | 166 try: |
159 tests_suite.extend(_RunPythonUnitTests_LoadTests(input_api, unit_test)) | 167 tests_suite.extend(_RunPythonUnitTests_LoadTests(input_api, unit_test)) |
160 except ImportError: | 168 except ImportError: |
161 outputs.append(message_type("Failed to load %s" % unit_test, | 169 outputs.append(message_type("Failed to load %s" % unit_test, |
162 long_text=input_api.traceback.format_exc())) | 170 long_text=input_api.traceback.format_exc())) |
163 | 171 |
164 results = input_api.unittest.TextTestRunner(verbosity=0).run( | 172 results = input_api.unittest.TextTestRunner(verbosity=0).run( |
165 input_api.unittest.TestSuite(tests_suite)) | 173 input_api.unittest.TestSuite(tests_suite)) |
166 if not results.wasSuccessful(): | 174 if not results.wasSuccessful(): |
167 outputs.append(message_type("%d unit tests failed." % | 175 outputs.append(message_type("%d unit tests failed." % |
168 (len(results.failures) + len(results.errors)))) | 176 (len(results.failures) + len(results.errors)))) |
169 return outputs | 177 return outputs |
OLD | NEW |