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

Side by Side Diff: presubmit_support.py

Issue 119101: Fix ListRelevantPresubmitFiles(). (Closed)
Patch Set: . 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 | « no previous file | 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.1' 9 __version__ = '1.1'
10 10
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 return depot_path 223 return depot_path
224 224
225 def AffectedFiles(self, include_dirs=False, include_deletes=True): 225 def AffectedFiles(self, include_dirs=False, include_deletes=True):
226 """Same as input_api.change.AffectedFiles() except only lists files 226 """Same as input_api.change.AffectedFiles() except only lists files
227 (and optionally directories) in the same directory as the current presubmit 227 (and optionally directories) in the same directory as the current presubmit
228 script, or subdirectories thereof. 228 script, or subdirectories thereof.
229 """ 229 """
230 dir_with_slash = normpath("%s/" % self.PresubmitLocalPath()) 230 dir_with_slash = normpath("%s/" % self.PresubmitLocalPath())
231 if len(dir_with_slash) == 1: 231 if len(dir_with_slash) == 1:
232 dir_with_slash = '' 232 dir_with_slash = ''
233 return filter(lambda x: normpath(x.LocalPath()).startswith(dir_with_slash), 233 return filter(
234 self.change.AffectedFiles(include_dirs, include_deletes)) 234 lambda x: normpath(x.AbsoluteLocalPath()).startswith(dir_with_slash),
235 self.change.AffectedFiles(include_dirs, include_deletes))
235 236
236 def LocalPaths(self, include_dirs=False): 237 def LocalPaths(self, include_dirs=False):
237 """Returns local paths of input_api.AffectedFiles().""" 238 """Returns local paths of input_api.AffectedFiles()."""
238 return [af.LocalPath() for af in self.AffectedFiles(include_dirs)] 239 return [af.LocalPath() for af in self.AffectedFiles(include_dirs)]
239 240
240 def AbsoluteLocalPaths(self, include_dirs=False): 241 def AbsoluteLocalPaths(self, include_dirs=False):
241 """Returns absolute local paths of input_api.AffectedFiles().""" 242 """Returns absolute local paths of input_api.AffectedFiles()."""
242 return [af.AbsoluteLocalPath() for af in self.AffectedFiles(include_dirs)] 243 return [af.AbsoluteLocalPath() for af in self.AffectedFiles(include_dirs)]
243 244
244 def ServerPaths(self, include_dirs=False): 245 def ServerPaths(self, include_dirs=False):
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 a 3 tuple: 542 a 3 tuple:
542 the AffectedFile instance of the current file; 543 the AffectedFile instance of the current file;
543 integer line number (1-based); and 544 integer line number (1-based); and
544 the contents of the line as a string. 545 the contents of the line as a string.
545 """ 546 """
546 return InputApi._RightHandSideLinesImpl( 547 return InputApi._RightHandSideLinesImpl(
547 filter(lambda x: x.IsTextFile(), 548 filter(lambda x: x.IsTextFile(),
548 self.AffectedFiles(include_deletes=False))) 549 self.AffectedFiles(include_deletes=False)))
549 550
550 551
551 def ListRelevantPresubmitFiles(files): 552 def ListRelevantPresubmitFiles(files, root):
552 """Finds all presubmit files that apply to a given set of source files. 553 """Finds all presubmit files that apply to a given set of source files.
553 554
554 Args: 555 Args:
555 files: An iterable container containing file paths. 556 files: An iterable container containing file paths.
557 root: Path where to stop searching.
556 558
557 Return: 559 Return:
558 ['foo/blat/PRESUBMIT.py', 'mat/gat/PRESUBMIT.py'] 560 List of absolute paths of the existing PRESUBMIT.py scripts.
559 """ 561 """
560 checked_dirs = {} # Keys are directory paths, values are ignored. 562 entries = []
561 source_dirs = [os.path.dirname(f) for f in files] 563 for f in files:
562 presubmit_files = [] 564 f = normpath(os.path.join(root, f))
563 for dir in source_dirs: 565 while f:
564 while (True): 566 f = os.path.dirname(f)
565 if dir in checked_dirs: 567 if f in entries:
566 break # We've already walked up from this directory.
567
568 test_path = os.path.join(dir, 'PRESUBMIT.py')
569 if os.path.isfile(test_path):
570 presubmit_files.append(normpath(test_path))
571
572 checked_dirs[dir] = ''
573 if dir in ['', '.']:
574 break 568 break
575 else: 569 entries.append(f)
576 dir = os.path.dirname(dir) 570 if f == root:
577 return presubmit_files 571 break
572 entries.sort()
573 entries = map(lambda x: os.path.join(x, 'PRESUBMIT.py'), entries)
574 return filter(lambda x: os.path.isfile(x), entries)
578 575
579 576
580 class PresubmitExecuter(object): 577 class PresubmitExecuter(object):
581 def __init__(self, change_info, committing): 578 def __init__(self, change_info, committing):
582 """ 579 """
583 Args: 580 Args:
584 change_info: The ChangeInfo object for the change. 581 change_info: The ChangeInfo object for the change.
585 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 582 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
586 """ 583 """
587 # TODO(maruel): Determine the SCM. 584 # TODO(maruel): Determine the SCM.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 change_info: The ChangeInfo object for the change. 643 change_info: The ChangeInfo object for the change.
647 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 644 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
648 verbose: Prints debug info. 645 verbose: Prints debug info.
649 output_stream: A stream to write output from presubmit tests to. 646 output_stream: A stream to write output from presubmit tests to.
650 input_stream: A stream to read input from the user. 647 input_stream: A stream to read input from the user.
651 default_presubmit: A default presubmit script to execute in any case. 648 default_presubmit: A default presubmit script to execute in any case.
652 649
653 Return: 650 Return:
654 True if execution can continue, False if not. 651 True if execution can continue, False if not.
655 """ 652 """
656 presubmit_files = ListRelevantPresubmitFiles(change_info.FileList()) 653 checkout_root = gcl.GetRepositoryRoot()
654 presubmit_files = ListRelevantPresubmitFiles(change_info.FileList(),
655 checkout_root)
657 if not presubmit_files and verbose: 656 if not presubmit_files and verbose:
658 output_stream.write("Warning, no presubmit.py found.\n") 657 output_stream.write("Warning, no presubmit.py found.\n")
659 results = [] 658 results = []
660 executer = PresubmitExecuter(change_info, committing) 659 executer = PresubmitExecuter(change_info, committing)
661 if default_presubmit: 660 if default_presubmit:
662 if verbose: 661 if verbose:
663 output_stream.write("Running default presubmit script.\n") 662 output_stream.write("Running default presubmit script.\n")
664 results += executer.ExecPresubmitScript(default_presubmit, 'PRESUBMIT.py') 663 fake_path = os.path.join(checkout_root, 'PRESUBMIT.py')
664 results += executer.ExecPresubmitScript(default_presubmit, fake_path)
665 for filename in presubmit_files: 665 for filename in presubmit_files:
666 filename = os.path.abspath(filename) 666 filename = os.path.abspath(filename)
667 if verbose: 667 if verbose:
668 output_stream.write("Running %s\n" % filename) 668 output_stream.write("Running %s\n" % filename)
669 # Accept CRLF presubmit script. 669 # Accept CRLF presubmit script.
670 presubmit_script = gcl.ReadFile(filename, 'rU') 670 presubmit_script = gcl.ReadFile(filename, 'rU')
671 results += executer.ExecPresubmitScript(presubmit_script, filename) 671 results += executer.ExecPresubmitScript(presubmit_script, filename)
672 672
673 errors = [] 673 errors = []
674 notifications = [] 674 notifications = []
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), 738 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files),
739 options.commit, 739 options.commit,
740 options.verbose, 740 options.verbose,
741 sys.stdout, 741 sys.stdout,
742 sys.stdin, 742 sys.stdin,
743 default_presubmit=None) 743 default_presubmit=None)
744 744
745 745
746 if __name__ == '__main__': 746 if __name__ == '__main__':
747 sys.exit(Main(sys.argv)) 747 sys.exit(Main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | tests/presubmit_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698