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.2' | 9 __version__ = '1.3.3' |
10 | 10 |
11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow | 11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow |
12 # caching (between all different invocations of presubmit scripts for a given | 12 # caching (between all different invocations of presubmit scripts for a given |
13 # change). We should add it as our presubmit scripts start feeling slow. | 13 # change). We should add it as our presubmit scripts start feeling slow. |
14 | 14 |
15 import cPickle # Exposed through the API. | 15 import cPickle # Exposed through the API. |
16 import cStringIO # Exposed through the API. | 16 import cStringIO # Exposed through the API. |
17 import exceptions | 17 import exceptions |
18 import fnmatch | 18 import fnmatch |
19 import glob | 19 import glob |
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 if f in entries: | 737 if f in entries: |
738 break | 738 break |
739 entries.append(f) | 739 entries.append(f) |
740 if f == root: | 740 if f == root: |
741 break | 741 break |
742 entries.sort() | 742 entries.sort() |
743 entries = map(lambda x: os.path.join(x, 'PRESUBMIT.py'), entries) | 743 entries = map(lambda x: os.path.join(x, 'PRESUBMIT.py'), entries) |
744 return filter(lambda x: os.path.isfile(x), entries) | 744 return filter(lambda x: os.path.isfile(x), entries) |
745 | 745 |
746 | 746 |
| 747 class GetTrySlavesExecuter(object): |
| 748 def ExecPresubmitScript(self, script_text): |
| 749 """Executes GetPreferredTrySlaves() from a single presubmit script. |
| 750 |
| 751 Args: |
| 752 script_text: The text of the presubmit script. |
| 753 |
| 754 Return: |
| 755 A list of try slaves. |
| 756 """ |
| 757 context = {} |
| 758 exec script_text in context |
| 759 |
| 760 function_name = 'GetPreferredTrySlaves' |
| 761 if function_name in context: |
| 762 result = eval(function_name + '()', context) |
| 763 if not isinstance(result, types.ListType): |
| 764 raise exceptions.RuntimeError( |
| 765 'Presubmit functions must return a list, got a %s instead: %s' % |
| 766 (type(result), str(result))) |
| 767 for item in result: |
| 768 if not isinstance(item, basestring): |
| 769 raise exceptions.RuntimeError('All try slaves names must be strings.') |
| 770 if item != item.strip(): |
| 771 raise exceptions.RuntimeError('Try slave names cannot start/end' |
| 772 'with whitespace') |
| 773 else: |
| 774 result = [] |
| 775 return result |
| 776 |
| 777 |
| 778 def DoGetTrySlaves(changed_files, |
| 779 repository_root, |
| 780 default_presubmit, |
| 781 verbose, |
| 782 output_stream): |
| 783 """Get the list of try servers from the presubmit scripts. |
| 784 |
| 785 Args: |
| 786 changed_files: List of modified files. |
| 787 repository_root: The repository root. |
| 788 default_presubmit: A default presubmit script to execute in any case. |
| 789 verbose: Prints debug info. |
| 790 output_stream: A stream to write debug output to. |
| 791 |
| 792 Return: |
| 793 List of try slaves |
| 794 """ |
| 795 presubmit_files = ListRelevantPresubmitFiles(changed_files, repository_root) |
| 796 if not presubmit_files and verbose: |
| 797 output_stream.write("Warning, no presubmit.py found.\n") |
| 798 results = [] |
| 799 executer = GetTrySlavesExecuter() |
| 800 if default_presubmit: |
| 801 if verbose: |
| 802 output_stream.write("Running default presubmit script.\n") |
| 803 results += executer.ExecPresubmitScript(default_presubmit) |
| 804 for filename in presubmit_files: |
| 805 filename = os.path.abspath(filename) |
| 806 if verbose: |
| 807 output_stream.write("Running %s\n" % filename) |
| 808 # Accept CRLF presubmit script. |
| 809 presubmit_script = gcl.ReadFile(filename, 'rU') |
| 810 results += executer.ExecPresubmitScript(presubmit_script) |
| 811 |
| 812 slaves = list(set(results)) |
| 813 if slaves and verbose: |
| 814 output_stream.write(', '.join(slaves)) |
| 815 output_stream.write('\n') |
| 816 return slaves |
| 817 |
| 818 |
747 class PresubmitExecuter(object): | 819 class PresubmitExecuter(object): |
748 def __init__(self, change, committing): | 820 def __init__(self, change, committing): |
749 """ | 821 """ |
750 Args: | 822 Args: |
751 change: The Change object. | 823 change: The Change object. |
752 committing: True if 'gcl commit' is running, False if 'gcl upload' is. | 824 committing: True if 'gcl commit' is running, False if 'gcl upload' is. |
753 """ | 825 """ |
754 self.change = change | 826 self.change = change |
755 self.committing = committing | 827 self.committing = committing |
756 | 828 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 options.commit, | 1046 options.commit, |
975 options.verbose, | 1047 options.verbose, |
976 sys.stdout, | 1048 sys.stdout, |
977 sys.stdin, | 1049 sys.stdin, |
978 options.default_presubmit, | 1050 options.default_presubmit, |
979 options.may_prompt) | 1051 options.may_prompt) |
980 | 1052 |
981 | 1053 |
982 if __name__ == '__main__': | 1054 if __name__ == '__main__': |
983 sys.exit(Main(sys.argv)) | 1055 sys.exit(Main(sys.argv)) |
OLD | NEW |