| 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 |