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.4' | 9 __version__ = '1.3.5' |
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 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 _AFFECTED_FILES = GitAffectedFile | 733 _AFFECTED_FILES = GitAffectedFile |
734 | 734 |
735 def __init__(self, *args, **kwargs): | 735 def __init__(self, *args, **kwargs): |
736 Change.__init__(self, *args, **kwargs) | 736 Change.__init__(self, *args, **kwargs) |
737 self.scm = 'git' | 737 self.scm = 'git' |
738 | 738 |
739 | 739 |
740 def ListRelevantPresubmitFiles(files, root): | 740 def ListRelevantPresubmitFiles(files, root): |
741 """Finds all presubmit files that apply to a given set of source files. | 741 """Finds all presubmit files that apply to a given set of source files. |
742 | 742 |
| 743 If inherit-review-settings-ok is present right under root, looks for |
| 744 PRESUBMIT.py in directories enclosing root. |
| 745 |
743 Args: | 746 Args: |
744 files: An iterable container containing file paths. | 747 files: An iterable container containing file paths. |
745 root: Path where to stop searching. | 748 root: Path where to stop searching. |
746 | 749 |
747 Return: | 750 Return: |
748 List of absolute paths of the existing PRESUBMIT.py scripts. | 751 List of absolute paths of the existing PRESUBMIT.py scripts. |
749 """ | 752 """ |
750 entries = [] | 753 files = [normpath(os.path.join(root, f)) for f in files] |
751 for f in files: | 754 |
752 f = normpath(os.path.join(root, f)) | 755 # List all the individual directories containing files. |
753 while f: | 756 directories = set([os.path.dirname(f) for f in files]) |
754 f = os.path.dirname(f) | 757 |
755 if f in entries: | 758 # Ignore root if inherit-review-settings-ok is present. |
| 759 if os.path.isfile(os.path.join(root, 'inherit-review-settings-ok')): |
| 760 root = None |
| 761 |
| 762 # Collect all unique directories that may contain PRESUBMIT.py. |
| 763 candidates = set() |
| 764 for directory in directories: |
| 765 while True: |
| 766 if directory in candidates: |
756 break | 767 break |
757 entries.append(f) | 768 candidates.add(directory) |
758 if f == root: | 769 if directory == root: |
759 break | 770 break |
760 entries.sort() | 771 parent_dir = os.path.dirname(directory) |
761 entries = map(lambda x: os.path.join(x, 'PRESUBMIT.py'), entries) | 772 if parent_dir == directory: |
762 return filter(lambda x: os.path.isfile(x), entries) | 773 # We hit the system root directory. |
| 774 break |
| 775 directory = parent_dir |
| 776 |
| 777 # Look for PRESUBMIT.py in all candidate directories. |
| 778 results = [] |
| 779 for directory in sorted(list(candidates)): |
| 780 p = os.path.join(directory, 'PRESUBMIT.py') |
| 781 if os.path.isfile(p): |
| 782 results.append(p) |
| 783 |
| 784 return results |
763 | 785 |
764 | 786 |
765 class GetTrySlavesExecuter(object): | 787 class GetTrySlavesExecuter(object): |
766 def ExecPresubmitScript(self, script_text): | 788 def ExecPresubmitScript(self, script_text): |
767 """Executes GetPreferredTrySlaves() from a single presubmit script. | 789 """Executes GetPreferredTrySlaves() from a single presubmit script. |
768 | 790 |
769 Args: | 791 Args: |
770 script_text: The text of the presubmit script. | 792 script_text: The text of the presubmit script. |
771 | 793 |
772 Return: | 794 Return: |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1017 help="Use upload instead of commit checks") | 1039 help="Use upload instead of commit checks") |
1018 parser.add_option("-r", "--recursive", action="store_true", | 1040 parser.add_option("-r", "--recursive", action="store_true", |
1019 help="Act recursively") | 1041 help="Act recursively") |
1020 parser.add_option("-v", "--verbose", action="store_true", default=False, | 1042 parser.add_option("-v", "--verbose", action="store_true", default=False, |
1021 help="Verbose output") | 1043 help="Verbose output") |
1022 parser.add_option("--files") | 1044 parser.add_option("--files") |
1023 parser.add_option("--name", default='no name') | 1045 parser.add_option("--name", default='no name') |
1024 parser.add_option("--description", default='') | 1046 parser.add_option("--description", default='') |
1025 parser.add_option("--issue", type='int', default=0) | 1047 parser.add_option("--issue", type='int', default=0) |
1026 parser.add_option("--patchset", type='int', default=0) | 1048 parser.add_option("--patchset", type='int', default=0) |
1027 parser.add_option("--root", default='') | 1049 parser.add_option("--root", default=os.getcwd(), |
| 1050 help="Search for PRESUBMIT.py up to this directory. " |
| 1051 "If inherit-review-settings-ok is present in this " |
| 1052 "directory, parent directories up to the root file " |
| 1053 "system directories will also be searched.") |
1028 parser.add_option("--default_presubmit") | 1054 parser.add_option("--default_presubmit") |
1029 parser.add_option("--may_prompt", action='store_true', default=False) | 1055 parser.add_option("--may_prompt", action='store_true', default=False) |
1030 options, args = parser.parse_args(argv[1:]) | 1056 options, args = parser.parse_args(argv[1:]) |
1031 if not options.root: | |
1032 options.root = os.getcwd() | |
1033 if os.path.isdir(os.path.join(options.root, '.git')): | 1057 if os.path.isdir(os.path.join(options.root, '.git')): |
1034 change_class = GitChange | 1058 change_class = GitChange |
1035 if not options.files: | 1059 if not options.files: |
1036 if args: | 1060 if args: |
1037 options.files = ParseFiles(args, options.recursive) | 1061 options.files = ParseFiles(args, options.recursive) |
1038 else: | 1062 else: |
1039 # Grab modified files. | 1063 # Grab modified files. |
1040 options.files = scm.GIT.CaptureStatus([options.root]) | 1064 options.files = scm.GIT.CaptureStatus([options.root]) |
1041 elif os.path.isdir(os.path.join(options.root, '.svn')): | 1065 elif os.path.isdir(os.path.join(options.root, '.svn')): |
1042 change_class = SvnChange | 1066 change_class = SvnChange |
(...skipping 20 matching lines...) Expand all Loading... |
1063 options.commit, | 1087 options.commit, |
1064 options.verbose, | 1088 options.verbose, |
1065 sys.stdout, | 1089 sys.stdout, |
1066 sys.stdin, | 1090 sys.stdin, |
1067 options.default_presubmit, | 1091 options.default_presubmit, |
1068 options.may_prompt) | 1092 options.may_prompt) |
1069 | 1093 |
1070 | 1094 |
1071 if __name__ == '__main__': | 1095 if __name__ == '__main__': |
1072 sys.exit(Main(sys.argv)) | 1096 sys.exit(Main(sys.argv)) |
OLD | NEW |