| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/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 """Enables directory-specific presubmit checks to run at upload and/or commit. | 6 """Enables directory-specific presubmit checks to run at upload and/or commit. |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 __version__ = '1.3.1' | 9 __version__ = '1.3.1' |
| 10 | 10 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 """A warning that should be included in the review request email.""" | 130 """A warning that should be included in the review request email.""" |
| 131 def __init__(self, *args, **kwargs): | 131 def __init__(self, *args, **kwargs): |
| 132 raise NotImplementedException() # TODO(joi) Implement. | 132 raise NotImplementedException() # TODO(joi) Implement. |
| 133 | 133 |
| 134 | 134 |
| 135 class InputApi(object): | 135 class InputApi(object): |
| 136 """An instance of this object is passed to presubmit scripts so they can | 136 """An instance of this object is passed to presubmit scripts so they can |
| 137 know stuff about the change they're looking at. | 137 know stuff about the change they're looking at. |
| 138 """ | 138 """ |
| 139 | 139 |
| 140 # File extensions that are considered source files from a style guide |
| 141 # perspective. Don't modify this list from a presubmit script! |
| 142 DEFAULT_WHITE_LIST = [ |
| 143 # C++ and friends |
| 144 r".*\.c", r".*\.cc", r".*\.cpp", r".*\.h", r".*\.m", r".*\.mm", |
| 145 r".*\.inl", r".*\.asm", r".*\.hxx", r".*\.hpp", |
| 146 # Scripts |
| 147 r".*\.js", r".*\.py", r".*\.json", r".*\.sh", r".*\.rb", |
| 148 # No extension at all |
| 149 r"(^|.*[\\\/])[^.]+$", |
| 150 # Other |
| 151 r".*\.java", r".*\.mk", r".*\.am", |
| 152 ] |
| 153 |
| 154 # Path regexp that should be excluded from being considered containing source |
| 155 # files. Don't modify this list from a presubmit script! |
| 156 DEFAULT_BLACK_LIST = [ |
| 157 r".*\bexperimental[\\\/].*", |
| 158 r".*\bthird_party[\\\/].*", |
| 159 # Output directories (just in case) |
| 160 r".*\bDebug[\\\/].*", |
| 161 r".*\bRelease[\\\/].*", |
| 162 r".*\bxcodebuild[\\\/].*", |
| 163 r".*\bsconsbuild[\\\/].*", |
| 164 # All caps files like README and LICENCE. |
| 165 r".*\b[A-Z0-9_]+", |
| 166 # SCM (can happen in dual SCM configuration) |
| 167 r".*\b\.git[\\\/].*", |
| 168 r".*\b\.svn[\\\/].*", |
| 169 ] |
| 170 |
| 140 def __init__(self, change, presubmit_path, is_committing): | 171 def __init__(self, change, presubmit_path, is_committing): |
| 141 """Builds an InputApi object. | 172 """Builds an InputApi object. |
| 142 | 173 |
| 143 Args: | 174 Args: |
| 144 change: A presubmit.GclChange object. | 175 change: A presubmit.GclChange object. |
| 145 presubmit_path: The path to the presubmit script being processed. | 176 presubmit_path: The path to the presubmit script being processed. |
| 146 is_committing: True if the change is about to be committed. | 177 is_committing: True if the change is about to be committed. |
| 147 """ | 178 """ |
| 148 # Version number of the presubmit_support script. | 179 # Version number of the presubmit_support script. |
| 149 self.version = [int(x) for x in __version__.split('.')] | 180 self.version = [int(x) for x in __version__.split('.')] |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 thereof. | 274 thereof. |
| 244 """ | 275 """ |
| 245 if include_deletes is not None: | 276 if include_deletes is not None: |
| 246 warnings.warn("AffectedTextFiles(include_deletes=%s)" | 277 warnings.warn("AffectedTextFiles(include_deletes=%s)" |
| 247 " is deprecated and ignored" % str(include_deletes), | 278 " is deprecated and ignored" % str(include_deletes), |
| 248 category=DeprecationWarning, | 279 category=DeprecationWarning, |
| 249 stacklevel=2) | 280 stacklevel=2) |
| 250 return filter(lambda x: x.IsTextFile(), | 281 return filter(lambda x: x.IsTextFile(), |
| 251 self.AffectedFiles(include_dirs=False, include_deletes=False)) | 282 self.AffectedFiles(include_dirs=False, include_deletes=False)) |
| 252 | 283 |
| 253 def RightHandSideLines(self): | 284 def FilterSourceFile(self, affected_file, white_list=None, black_list=None): |
| 285 """Filters out files that aren't considered "source file". |
| 286 |
| 287 If white_list or black_list is None, InputApi.DEFAULT_WHITE_LIST |
| 288 and InputApi.DEFAULT_BLACK_LIST is used respectively. |
| 289 |
| 290 The lists will be compiled as regular expression and |
| 291 AffectedFile.LocalPath() needs to pass both list. |
| 292 |
| 293 Note: Copy-paste this function to suit your needs or use a lambda function. |
| 294 """ |
| 295 def Find(affected_file, list): |
| 296 for item in list: |
| 297 if self.re.match(item, affected_file.LocalPath()): |
| 298 return True |
| 299 return False |
| 300 return (Find(affected_file, white_list or self.DEFAULT_WHITE_LIST) and |
| 301 not Find(affected_file, black_list or self.DEFAULT_BLACK_LIST)) |
| 302 |
| 303 def AffectedSourceFiles(self, source_file): |
| 304 """Filter the list of AffectedTextFiles by the function source_file. |
| 305 |
| 306 If source_file is None, InputApi.FilterSourceFile() is used. |
| 307 """ |
| 308 if not source_file: |
| 309 source_file = self.FilterSourceFile |
| 310 return filter(source_file, self.AffectedTextFiles()) |
| 311 |
| 312 def RightHandSideLines(self, source_file_filter=None): |
| 254 """An iterator over all text lines in "new" version of changed files. | 313 """An iterator over all text lines in "new" version of changed files. |
| 255 | 314 |
| 256 Only lists lines from new or modified text files in the change that are | 315 Only lists lines from new or modified text files in the change that are |
| 257 contained by the directory of the currently executing presubmit script. | 316 contained by the directory of the currently executing presubmit script. |
| 258 | 317 |
| 259 This is useful for doing line-by-line regex checks, like checking for | 318 This is useful for doing line-by-line regex checks, like checking for |
| 260 trailing whitespace. | 319 trailing whitespace. |
| 261 | 320 |
| 262 Yields: | 321 Yields: |
| 263 a 3 tuple: | 322 a 3 tuple: |
| 264 the AffectedFile instance of the current file; | 323 the AffectedFile instance of the current file; |
| 265 integer line number (1-based); and | 324 integer line number (1-based); and |
| 266 the contents of the line as a string. | 325 the contents of the line as a string. |
| 267 | 326 |
| 268 Note: The cariage return (LF or CR) is stripped off. | 327 Note: The cariage return (LF or CR) is stripped off. |
| 269 """ | 328 """ |
| 270 return InputApi._RightHandSideLinesImpl( | 329 files = self.AffectedSourceFiles(source_file_filter) |
| 271 filter(lambda x: x.IsTextFile(), | 330 return InputApi._RightHandSideLinesImpl(files) |
| 272 self.AffectedFiles(include_deletes=False))) | |
| 273 | 331 |
| 274 def ReadFile(self, file, mode='r'): | 332 def ReadFile(self, file, mode='r'): |
| 275 """Reads an arbitrary file. | 333 """Reads an arbitrary file. |
| 276 | 334 |
| 277 Deny reading anything outside the repository. | 335 Deny reading anything outside the repository. |
| 278 """ | 336 """ |
| 279 if isinstance(file, AffectedFile): | 337 if isinstance(file, AffectedFile): |
| 280 file = file.AbsoluteLocalPath() | 338 file = file.AbsoluteLocalPath() |
| 281 if not file.startswith(self.change.RepositoryRoot()): | 339 if not file.startswith(self.change.RepositoryRoot()): |
| 282 raise IOError('Access outside the repository root is denied.') | 340 raise IOError('Access outside the repository root is denied.') |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 return not DoPresubmitChecks(gcl.ChangeInfo('No name', 0, 0, '', files), | 803 return not DoPresubmitChecks(gcl.ChangeInfo('No name', 0, 0, '', files), |
| 746 options.commit, | 804 options.commit, |
| 747 options.verbose, | 805 options.verbose, |
| 748 sys.stdout, | 806 sys.stdout, |
| 749 sys.stdin, | 807 sys.stdin, |
| 750 default_presubmit=None) | 808 default_presubmit=None) |
| 751 | 809 |
| 752 | 810 |
| 753 if __name__ == '__main__': | 811 if __name__ == '__main__': |
| 754 sys.exit(Main(sys.argv)) | 812 sys.exit(Main(sys.argv)) |
| OLD | NEW |