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

Side by Side Diff: presubmit_support.py

Issue 119442: A step closer to make presubmit SCM independent. (Closed)
Patch Set: oops 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 | « gcl.py ('k') | tests/gcl_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.2' 9 __version__ = '1.3.2'
10 10
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 497
498 Instance members: 498 Instance members:
499 tags: Dictionnary of KEY=VALUE pairs found in the change description. 499 tags: Dictionnary of KEY=VALUE pairs found in the change description.
500 self.KEY: equivalent to tags['KEY'] 500 self.KEY: equivalent to tags['KEY']
501 """ 501 """
502 502
503 # Matches key/value (or "tag") lines in changelist descriptions. 503 # Matches key/value (or "tag") lines in changelist descriptions.
504 _tag_line_re = re.compile( 504 _tag_line_re = re.compile(
505 '^\s*(?P<key>[A-Z][A-Z_0-9]*)\s*=\s*(?P<value>.*?)\s*$') 505 '^\s*(?P<key>[A-Z][A-Z_0-9]*)\s*=\s*(?P<value>.*?)\s*$')
506 506
507 def __init__(self, change_info, repository_root=''): 507 def __init__(self, change_info):
508 # Do not keep a reference to the original change_info. 508 # Do not keep a reference to the original change_info.
509 self._name = change_info.name 509 self._name = change_info.name
510 self._full_description = change_info.description 510 self._full_description = change_info.description
511 self._repository_root = repository_root 511 self._repository_root = change_info.GetLocalRoot()
512 self.issue = change_info.issue 512 self.issue = change_info.issue
513 self.patchset = change_info.patchset 513 self.patchset = change_info.patchset
514 514
515 # From the description text, build up a dictionary of key/value pairs 515 # From the description text, build up a dictionary of key/value pairs
516 # plus the description minus all key/value or "tag" lines. 516 # plus the description minus all key/value or "tag" lines.
517 self._description_without_tags = [] 517 self._description_without_tags = []
518 self.tags = {} 518 self.tags = {}
519 for line in change_info.description.splitlines(): 519 for line in change_info.description.splitlines():
520 m = self._tag_line_re.match(line) 520 m = self._tag_line_re.match(line)
521 if m: 521 if m:
522 self.tags[m.group('key')] = m.group('value') 522 self.tags[m.group('key')] = m.group('value')
523 else: 523 else:
524 self._description_without_tags.append(line) 524 self._description_without_tags.append(line)
525 525
526 # Change back to text and remove whitespace at end. 526 # Change back to text and remove whitespace at end.
527 self._description_without_tags = '\n'.join(self._description_without_tags) 527 self._description_without_tags = '\n'.join(self._description_without_tags)
528 self._description_without_tags = self._description_without_tags.rstrip() 528 self._description_without_tags = self._description_without_tags.rstrip()
529 529
530 self._affected_files = [ 530 self._affected_files = [
531 SvnAffectedFile(info[1], info[0].strip(), repository_root) 531 SvnAffectedFile(info[1], info[0].strip(), self._repository_root)
532 for info in change_info.files 532 for info in change_info.GetFiles()
533 ] 533 ]
534 534
535 def Name(self): 535 def Name(self):
536 """Returns the change name.""" 536 """Returns the change name."""
537 return self._name 537 return self._name
538 538
539 def DescriptionText(self): 539 def DescriptionText(self):
540 """Returns the user-entered changelist description, minus tags. 540 """Returns the user-entered changelist description, minus tags.
541 541
542 Any line in the user-provided description starting with e.g. "FOO=" 542 Any line in the user-provided description starting with e.g. "FOO="
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 break 644 break
645 entries.sort() 645 entries.sort()
646 entries = map(lambda x: os.path.join(x, 'PRESUBMIT.py'), entries) 646 entries = map(lambda x: os.path.join(x, 'PRESUBMIT.py'), entries)
647 return filter(lambda x: os.path.isfile(x), entries) 647 return filter(lambda x: os.path.isfile(x), entries)
648 648
649 649
650 class PresubmitExecuter(object): 650 class PresubmitExecuter(object):
651 def __init__(self, change_info, committing): 651 def __init__(self, change_info, committing):
652 """ 652 """
653 Args: 653 Args:
654 change_info: The ChangeInfo object for the change. 654 change_info: The gcl.ChangeInfo object for the change.
655 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 655 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
656 """ 656 """
657 # TODO(maruel): Determine the SCM. 657 # TODO(maruel): Determine the SCM.
658 self.change = GclChange(change_info, gcl.GetRepositoryRoot()) 658 self.change = GclChange(change_info)
659 self.committing = committing 659 self.committing = committing
660 660
661 def ExecPresubmitScript(self, script_text, presubmit_path): 661 def ExecPresubmitScript(self, script_text, presubmit_path):
662 """Executes a single presubmit script. 662 """Executes a single presubmit script.
663 663
664 Args: 664 Args:
665 script_text: The text of the presubmit script. 665 script_text: The text of the presubmit script.
666 presubmit_path: The path to the presubmit file (this will be reported via 666 presubmit_path: The path to the presubmit file (this will be reported via
667 input_api.PresubmitLocalPath()). 667 input_api.PresubmitLocalPath()).
668 668
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 """Runs all presubmit checks that apply to the files in the change. 707 """Runs all presubmit checks that apply to the files in the change.
708 708
709 This finds all PRESUBMIT.py files in directories enclosing the files in the 709 This finds all PRESUBMIT.py files in directories enclosing the files in the
710 change (up to the repository root) and calls the relevant entrypoint function 710 change (up to the repository root) and calls the relevant entrypoint function
711 depending on whether the change is being committed or uploaded. 711 depending on whether the change is being committed or uploaded.
712 712
713 Prints errors, warnings and notifications. Prompts the user for warnings 713 Prints errors, warnings and notifications. Prompts the user for warnings
714 when needed. 714 when needed.
715 715
716 Args: 716 Args:
717 change_info: The ChangeInfo object for the change. 717 change_info: The gcl.ChangeInfo object for the change.
718 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 718 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
719 verbose: Prints debug info. 719 verbose: Prints debug info.
720 output_stream: A stream to write output from presubmit tests to. 720 output_stream: A stream to write output from presubmit tests to.
721 input_stream: A stream to read input from the user. 721 input_stream: A stream to read input from the user.
722 default_presubmit: A default presubmit script to execute in any case. 722 default_presubmit: A default presubmit script to execute in any case.
723 may_prompt: Enable (y/n) questions on warning or error. 723 may_prompt: Enable (y/n) questions on warning or error.
724 724
725 Return: 725 Return:
726 True if execution can continue, False if not. 726 True if execution can continue, False if not.
727 """ 727 """
728 checkout_root = gcl.GetRepositoryRoot() 728 presubmit_files = ListRelevantPresubmitFiles(change_info.GetFileNames(),
729 presubmit_files = ListRelevantPresubmitFiles(change_info.FileList(), 729 change_info.local_root)
730 checkout_root)
731 if not presubmit_files and verbose: 730 if not presubmit_files and verbose:
732 output_stream.write("Warning, no presubmit.py found.\n") 731 output_stream.write("Warning, no presubmit.py found.\n")
733 results = [] 732 results = []
734 executer = PresubmitExecuter(change_info, committing) 733 executer = PresubmitExecuter(change_info, committing)
735 if default_presubmit: 734 if default_presubmit:
736 if verbose: 735 if verbose:
737 output_stream.write("Running default presubmit script.\n") 736 output_stream.write("Running default presubmit script.\n")
738 fake_path = os.path.join(checkout_root, 'PRESUBMIT.py') 737 fake_path = os.path.join(change_info.local_root, 'PRESUBMIT.py')
739 results += executer.ExecPresubmitScript(default_presubmit, fake_path) 738 results += executer.ExecPresubmitScript(default_presubmit, fake_path)
740 for filename in presubmit_files: 739 for filename in presubmit_files:
741 filename = os.path.abspath(filename) 740 filename = os.path.abspath(filename)
742 if verbose: 741 if verbose:
743 output_stream.write("Running %s\n" % filename) 742 output_stream.write("Running %s\n" % filename)
744 # Accept CRLF presubmit script. 743 # Accept CRLF presubmit script.
745 presubmit_script = gcl.ReadFile(filename, 'rU') 744 presubmit_script = gcl.ReadFile(filename, 'rU')
746 results += executer.ExecPresubmitScript(presubmit_script, filename) 745 results += executer.ExecPresubmitScript(presubmit_script, filename)
747 746
748 errors = [] 747 errors = []
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 options.commit, 813 options.commit,
815 options.verbose, 814 options.verbose,
816 sys.stdout, 815 sys.stdout,
817 sys.stdin, 816 sys.stdin,
818 None, 817 None,
819 False) 818 False)
820 819
821 820
822 if __name__ == '__main__': 821 if __name__ == '__main__':
823 sys.exit(Main(sys.argv)) 822 sys.exit(Main(sys.argv))
OLDNEW
« no previous file with comments | « gcl.py ('k') | tests/gcl_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698