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

Side by Side Diff: tools/presubmit.py

Issue 2523993003: [test] Let presubmit only run over affected files. (Closed)
Patch Set: .. Created 4 years 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.py ('k') | no next file » | 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/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2012 the V8 project authors. All rights reserved. 3 # Copyright 2012 the V8 project authors. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 -build/namespaces 64 -build/namespaces
65 -readability/check 65 -readability/check
66 -readability/fn_size 66 -readability/fn_size
67 +readability/streams 67 +readability/streams
68 -runtime/references 68 -runtime/references
69 """.split() 69 """.split()
70 70
71 LINT_OUTPUT_PATTERN = re.compile(r'^.+[:(]\d+[:)]|^Done processing') 71 LINT_OUTPUT_PATTERN = re.compile(r'^.+[:(]\d+[:)]|^Done processing')
72 FLAGS_LINE = re.compile("//\s*Flags:.*--([A-z0-9-])+_[A-z0-9].*\n") 72 FLAGS_LINE = re.compile("//\s*Flags:.*--([A-z0-9-])+_[A-z0-9].*\n")
73 73
74 TOOLS_PATH = dirname(abspath(__file__))
75
74 def CppLintWorker(command): 76 def CppLintWorker(command):
75 try: 77 try:
76 process = subprocess.Popen(command, stderr=subprocess.PIPE) 78 process = subprocess.Popen(command, stderr=subprocess.PIPE)
77 process.wait() 79 process.wait()
78 out_lines = "" 80 out_lines = ""
79 error_count = -1 81 error_count = -1
80 while True: 82 while True:
81 out_line = process.stderr.readline() 83 out_line = process.stderr.readline()
82 if out_line == '' and process.poll() != None: 84 if out_line == '' and process.poll() != None:
83 if error_count == -1: 85 if error_count == -1:
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 if file in self.sums: 151 if file in self.sums:
150 self.sums.pop(file) 152 self.sums.pop(file)
151 153
152 154
153 class SourceFileProcessor(object): 155 class SourceFileProcessor(object):
154 """ 156 """
155 Utility class that can run through a directory structure, find all relevant 157 Utility class that can run through a directory structure, find all relevant
156 files and invoke a custom check on the files. 158 files and invoke a custom check on the files.
157 """ 159 """
158 160
159 def Run(self, path): 161 def RunOnPath(self, path):
162 """Runs processor on all files under the given path."""
163
160 all_files = [] 164 all_files = []
161 for file in self.GetPathsToSearch(): 165 for file in self.GetPathsToSearch():
162 all_files += self.FindFilesIn(join(path, file)) 166 all_files += self.FindFilesIn(join(path, file))
163 if not self.ProcessFiles(all_files, path): 167 return self.ProcessFiles(all_files)
164 return False 168
165 return True 169 def RunOnFiles(self, files):
170 """Runs processor only on affected files."""
171
172 # Helper for getting directory pieces.
173 dirs = lambda f: dirname(f).split(os.sep)
174
175 # Path offsets where to look (to be in sync with RunOnPath).
176 # Normalize '.' to check for it with str.startswith.
177 search_paths = [('' if p == '.' else p) for p in self.GetPathsToSearch()]
178
179 all_files = [
180 f.AbsoluteLocalPath()
181 for f in files
182 if (not self.IgnoreFile(f.LocalPath()) and
183 self.IsRelevant(f.LocalPath()) and
184 all(not self.IgnoreDir(d) for d in dirs(f.LocalPath())) and
185 any(map(f.LocalPath().startswith, search_paths)))
186 ]
187
188 return self.ProcessFiles(all_files)
166 189
167 def IgnoreDir(self, name): 190 def IgnoreDir(self, name):
168 return (name.startswith('.') or 191 return (name.startswith('.') or
169 name in ('buildtools', 'data', 'gmock', 'gtest', 'kraken', 192 name in ('buildtools', 'data', 'gmock', 'gtest', 'kraken',
170 'octane', 'sunspider')) 193 'octane', 'sunspider'))
171 194
172 def IgnoreFile(self, name): 195 def IgnoreFile(self, name):
173 return name.startswith('.') 196 return name.startswith('.')
174 197
175 def FindFilesIn(self, path): 198 def FindFilesIn(self, path):
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 230
208 def GetCpplintScript(self, prio_path): 231 def GetCpplintScript(self, prio_path):
209 for path in [prio_path] + os.environ["PATH"].split(os.pathsep): 232 for path in [prio_path] + os.environ["PATH"].split(os.pathsep):
210 path = path.strip('"') 233 path = path.strip('"')
211 cpplint = os.path.join(path, "cpplint.py") 234 cpplint = os.path.join(path, "cpplint.py")
212 if os.path.isfile(cpplint): 235 if os.path.isfile(cpplint):
213 return cpplint 236 return cpplint
214 237
215 return None 238 return None
216 239
217 def ProcessFiles(self, files, path): 240 def ProcessFiles(self, files):
218 good_files_cache = FileContentsCache('.cpplint-cache') 241 good_files_cache = FileContentsCache('.cpplint-cache')
219 good_files_cache.Load() 242 good_files_cache.Load()
220 files = good_files_cache.FilterUnchangedFiles(files) 243 files = good_files_cache.FilterUnchangedFiles(files)
221 if len(files) == 0: 244 if len(files) == 0:
222 print 'No changes in files detected. Skipping cpplint check.' 245 print 'No changes in files detected. Skipping cpplint check.'
223 return True 246 return True
224 247
225 filters = ",".join([n for n in LINT_RULES]) 248 filters = ",".join([n for n in LINT_RULES])
226 command = [sys.executable, 'cpplint.py', '--filter', filters] 249 command = [sys.executable, 'cpplint.py', '--filter', filters]
227 cpplint = self.GetCpplintScript(join(path, "tools")) 250 cpplint = self.GetCpplintScript(TOOLS_PATH)
228 if cpplint is None: 251 if cpplint is None:
229 print('Could not find cpplint.py. Make sure ' 252 print('Could not find cpplint.py. Make sure '
230 'depot_tools is installed and in the path.') 253 'depot_tools is installed and in the path.')
231 sys.exit(1) 254 sys.exit(1)
232 255
233 command = [sys.executable, cpplint, '--filter', filters] 256 command = [sys.executable, cpplint, '--filter', filters]
234 257
235 commands = join([command + [file] for file in files]) 258 commands = join([command + [file] for file in files])
236 count = multiprocessing.cpu_count() 259 count = multiprocessing.cpu_count()
237 pool = multiprocessing.Pool(count) 260 pool = multiprocessing.Pool(count)
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 print "%s does not end with a single new line." % name 397 print "%s does not end with a single new line." % name
375 result = False 398 result = False
376 # Sanitize flags for fuzzer. 399 # Sanitize flags for fuzzer.
377 if "mjsunit" in name: 400 if "mjsunit" in name:
378 match = FLAGS_LINE.search(contents) 401 match = FLAGS_LINE.search(contents)
379 if match: 402 if match:
380 print "%s Flags should use '-' (not '_')" % name 403 print "%s Flags should use '-' (not '_')" % name
381 result = False 404 result = False
382 return result 405 return result
383 406
384 def ProcessFiles(self, files, path): 407 def ProcessFiles(self, files):
385 success = True 408 success = True
386 violations = 0 409 violations = 0
387 for file in files: 410 for file in files:
388 try: 411 try:
389 handle = open(file) 412 handle = open(file)
390 contents = handle.read() 413 contents = handle.read()
391 if not self.ProcessContents(file, contents): 414 if not self.ProcessContents(file, contents):
392 success = False 415 success = False
393 violations += 1 416 violations += 1
394 finally: 417 finally:
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 keys = {} 454 keys = {}
432 for key, value in pairs: 455 for key, value in pairs:
433 if key in keys: 456 if key in keys:
434 print("%s: Error: duplicate key %s" % (filepath, key)) 457 print("%s: Error: duplicate key %s" % (filepath, key))
435 status["success"] = False 458 status["success"] = False
436 keys[key] = True 459 keys[key] = True
437 460
438 json.loads(contents, object_pairs_hook=check_pairs) 461 json.loads(contents, object_pairs_hook=check_pairs)
439 return status["success"] 462 return status["success"]
440 463
441 def CheckStatusFiles(workspace): 464 def CheckStatusFiles(workspace):
Michael Achenbach 2016/11/23 20:18:25 Will also change this one in a follow up CL. Proba
442 success = True 465 success = True
443 suite_paths = utils.GetSuitePaths(join(workspace, "test")) 466 suite_paths = utils.GetSuitePaths(join(workspace, "test"))
444 for root in suite_paths: 467 for root in suite_paths:
445 suite_path = join(workspace, "test", root) 468 suite_path = join(workspace, "test", root)
446 status_file_path = join(suite_path, root + ".status") 469 status_file_path = join(suite_path, root + ".status")
447 suite = testsuite.TestSuite.LoadTestSuite(suite_path) 470 suite = testsuite.TestSuite.LoadTestSuite(suite_path)
448 if suite and exists(status_file_path): 471 if suite and exists(status_file_path):
449 success &= statusfile.PresubmitCheck(status_file_path) 472 success &= statusfile.PresubmitCheck(status_file_path)
450 success &= _CheckStatusFileForDuplicateKeys(status_file_path) 473 success &= _CheckStatusFileForDuplicateKeys(status_file_path)
451 return success 474 return success
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 return result 508 return result
486 509
487 510
488 def Main(): 511 def Main():
489 workspace = abspath(join(dirname(sys.argv[0]), '..')) 512 workspace = abspath(join(dirname(sys.argv[0]), '..'))
490 parser = GetOptions() 513 parser = GetOptions()
491 (options, args) = parser.parse_args() 514 (options, args) = parser.parse_args()
492 success = True 515 success = True
493 print "Running C++ lint check..." 516 print "Running C++ lint check..."
494 if not options.no_lint: 517 if not options.no_lint:
495 success &= CppLintProcessor().Run(workspace) 518 success &= CppLintProcessor().RunOnPath(workspace)
496 print "Running copyright header, trailing whitespaces and " \ 519 print "Running copyright header, trailing whitespaces and " \
497 "two empty lines between declarations check..." 520 "two empty lines between declarations check..."
498 success &= SourceProcessor().Run(workspace) 521 success &= SourceProcessor().RunOnPath(workspace)
499 success &= CheckStatusFiles(workspace) 522 success &= CheckStatusFiles(workspace)
500 if success: 523 if success:
501 return 0 524 return 0
502 else: 525 else:
503 return 1 526 return 1
504 527
505 528
506 if __name__ == '__main__': 529 if __name__ == '__main__':
507 sys.exit(Main()) 530 sys.exit(Main())
OLDNEW
« no previous file with comments | « PRESUBMIT.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698