Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: presubmit_support.py

Issue 119365: Add InputApi.AffectedSourceFile() and custom filtering support. (Closed)
Patch Set: comment Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « presubmit_canned_checks.py ('k') | tests/presubmit_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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))
OLDNEW
« no previous file with comments | « presubmit_canned_checks.py ('k') | tests/presubmit_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698