OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Generic presubmit checks that can be reused by other presubmit checks.""" | 5 """Generic presubmit checks that can be reused by other presubmit checks.""" |
6 | 6 |
7 import os as _os | 7 import os as _os |
8 _HERE = _os.path.dirname(_os.path.abspath(__file__)) | 8 _HERE = _os.path.dirname(_os.path.abspath(__file__)) |
9 | 9 |
10 | 10 |
(...skipping 28 matching lines...) Expand all Loading... |
39 | 39 |
40 def CheckChangeHasQaField(input_api, output_api): | 40 def CheckChangeHasQaField(input_api, output_api): |
41 """Requires that the changelist have a QA= field.""" | 41 """Requires that the changelist have a QA= field.""" |
42 if input_api.change.QA: | 42 if input_api.change.QA: |
43 return [] | 43 return [] |
44 else: | 44 else: |
45 return [output_api.PresubmitError('Changelist must have a QA= field.')] | 45 return [output_api.PresubmitError('Changelist must have a QA= field.')] |
46 | 46 |
47 | 47 |
48 def CheckDoNotSubmitInDescription(input_api, output_api): | 48 def CheckDoNotSubmitInDescription(input_api, output_api): |
49 """Checks that the user didn't add 'DO NOT ' + 'SUBMIT' to the CL description. | 49 """Checks that the user didn't add 'DO NOT ''SUBMIT' to the CL description. |
50 """ | 50 """ |
51 keyword = 'DO NOT ' + 'SUBMIT' | 51 keyword = 'DO NOT ''SUBMIT' |
52 if keyword in input_api.change.DescriptionText(): | 52 if keyword in input_api.change.DescriptionText(): |
53 return [output_api.PresubmitError( | 53 return [output_api.PresubmitError( |
54 keyword + ' is present in the changelist description.')] | 54 keyword + ' is present in the changelist description.')] |
55 else: | 55 else: |
56 return [] | 56 return [] |
57 | 57 |
58 | 58 |
59 def CheckChangeHasDescription(input_api, output_api): | 59 def CheckChangeHasDescription(input_api, output_api): |
60 """Checks the CL description is not empty.""" | 60 """Checks the CL description is not empty.""" |
61 text = input_api.change.DescriptionText() | 61 text = input_api.change.DescriptionText() |
62 if text.strip() == '': | 62 if text.strip() == '': |
63 if input_api.is_committing: | 63 if input_api.is_committing: |
64 return [output_api.PresubmitError('Add a description.')] | 64 return [output_api.PresubmitError('Add a description.')] |
65 else: | 65 else: |
66 return [output_api.PresubmitNotifyResult('Add a description.')] | 66 return [output_api.PresubmitNotifyResult('Add a description.')] |
67 return [] | 67 return [] |
68 | 68 |
69 | 69 |
| 70 def CheckChangeDescriptionNotCommitted(input_api, output_api): |
| 71 """Checks that the CL does not end with a Committed link.""" |
| 72 description = input_api.change.DescriptionText() |
| 73 if input_api.re.search('\nCommitted: \S+\s*$', description): |
| 74 return [output_api.PresubmitError( |
| 75 'The CL description appears to end with a committed link. If this issue\n' |
| 76 'has been previously used for a commit, please make a new issue number\n' |
| 77 'by typing "git cl issue 0" and reuploading your CL.')] |
| 78 return [] |
| 79 |
| 80 |
70 def CheckChangeWasUploaded(input_api, output_api): | 81 def CheckChangeWasUploaded(input_api, output_api): |
71 """Checks that the issue was uploaded before committing.""" | 82 """Checks that the issue was uploaded before committing.""" |
72 if input_api.is_committing and not input_api.change.issue: | 83 if input_api.is_committing and not input_api.change.issue: |
73 return [output_api.PresubmitError( | 84 return [output_api.PresubmitError( |
74 'Issue wasn\'t uploaded. Please upload first.')] | 85 'Issue wasn\'t uploaded. Please upload first.')] |
75 return [] | 86 return [] |
76 | 87 |
77 | 88 |
78 ### Content checks | 89 ### Content checks |
79 | 90 |
80 def CheckDoNotSubmitInFiles(input_api, output_api): | 91 def CheckDoNotSubmitInFiles(input_api, output_api): |
81 """Checks that the user didn't add 'DO NOT ' + 'SUBMIT' to any files.""" | 92 """Checks that the user didn't add 'DO NOT ''SUBMIT' to any files.""" |
82 # We want to check every text file, not just source files. | 93 # We want to check every text file, not just source files. |
83 file_filter = lambda x : x | 94 file_filter = lambda x : x |
84 keyword = 'DO NOT ' + 'SUBMIT' | 95 keyword = 'DO NOT ''SUBMIT' |
85 errors = _FindNewViolationsOfRule(lambda _, line : keyword not in line, | 96 errors = _FindNewViolationsOfRule(lambda _, line : keyword not in line, |
86 input_api, file_filter) | 97 input_api, file_filter) |
87 text = '\n'.join('Found %s in %s' % (keyword, loc) for loc in errors) | 98 text = '\n'.join('Found %s in %s' % (keyword, loc) for loc in errors) |
88 if text: | 99 if text: |
89 return [output_api.PresubmitError(text)] | 100 return [output_api.PresubmitError(text)] |
90 return [] | 101 return [] |
91 | 102 |
92 | 103 |
93 def CheckChangeLintsClean(input_api, output_api, source_file_filter=None): | 104 def CheckChangeLintsClean(input_api, output_api, source_file_filter=None): |
94 """Checks that all '.cc' and '.h' files pass cpplint.py.""" | 105 """Checks that all '.cc' and '.h' files pass cpplint.py.""" |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 | 295 |
285 if tabs: | 296 if tabs: |
286 return [output_api.PresubmitPromptWarning('Found a tab character in:', | 297 return [output_api.PresubmitPromptWarning('Found a tab character in:', |
287 long_text='\n'.join(tabs))] | 298 long_text='\n'.join(tabs))] |
288 return [] | 299 return [] |
289 | 300 |
290 | 301 |
291 def CheckChangeTodoHasOwner(input_api, output_api, source_file_filter=None): | 302 def CheckChangeTodoHasOwner(input_api, output_api, source_file_filter=None): |
292 """Checks that the user didn't add TODO(name) without an owner.""" | 303 """Checks that the user didn't add TODO(name) without an owner.""" |
293 | 304 |
294 unowned_todo = input_api.re.compile('TO' + 'DO[^(]') | 305 unowned_todo = input_api.re.compile('TO''DO[^(]') |
295 errors = _FindNewViolationsOfRule(lambda _, x : not unowned_todo.search(x), | 306 errors = _FindNewViolationsOfRule(lambda _, x : not unowned_todo.search(x), |
296 input_api, source_file_filter) | 307 input_api, source_file_filter) |
297 errors = ['Found TO' + 'DO with no owner in ' + x for x in errors] | 308 errors = ['Found TO''DO with no owner in ' + x for x in errors] |
298 if errors: | 309 if errors: |
299 return [output_api.PresubmitPromptWarning('\n'.join(errors))] | 310 return [output_api.PresubmitPromptWarning('\n'.join(errors))] |
300 return [] | 311 return [] |
301 | 312 |
302 | 313 |
303 def CheckChangeHasNoStrayWhitespace(input_api, output_api, | 314 def CheckChangeHasNoStrayWhitespace(input_api, output_api, |
304 source_file_filter=None): | 315 source_file_filter=None): |
305 """Checks that there is no stray whitespace at source lines end.""" | 316 """Checks that there is no stray whitespace at source lines end.""" |
306 errors = _FindNewViolationsOfRule(lambda _, line : line.rstrip() == line, | 317 errors = _FindNewViolationsOfRule(lambda _, line : line.rstrip() == line, |
307 input_api, source_file_filter) | 318 input_api, source_file_filter) |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 input_api, output_api, source_file_filter=text_files)) | 975 input_api, output_api, source_file_filter=text_files)) |
965 snapshot("checking svn mime types") | 976 snapshot("checking svn mime types") |
966 results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes( | 977 results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes( |
967 input_api, output_api)) | 978 input_api, output_api)) |
968 snapshot("checking license") | 979 snapshot("checking license") |
969 results.extend(input_api.canned_checks.CheckLicense( | 980 results.extend(input_api.canned_checks.CheckLicense( |
970 input_api, output_api, license_header, source_file_filter=sources)) | 981 input_api, output_api, license_header, source_file_filter=sources)) |
971 snapshot("checking was uploaded") | 982 snapshot("checking was uploaded") |
972 results.extend(input_api.canned_checks.CheckChangeWasUploaded( | 983 results.extend(input_api.canned_checks.CheckChangeWasUploaded( |
973 input_api, output_api)) | 984 input_api, output_api)) |
| 985 snapshot("checking description") |
| 986 results.extend(input_api.canned_checks.CheckChangeHasDescription( |
| 987 input_api, output_api)) |
| 988 results.extend(input_api.canned_checks.CheckDoNotSubmitInDescription( |
| 989 input_api, output_api)) |
| 990 results.extend(input_api.canned_checks.CheckChangeDescriptionNotCommitted( |
| 991 input_api, output_api)) |
| 992 snapshot("checking do not submit in files") |
| 993 results.extend(input_api.canned_checks.CheckDoNotSubmitInFiles( |
| 994 input_api, output_api)) |
974 snapshot("done") | 995 snapshot("done") |
975 return results | 996 return results |
OLD | NEW |