| 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 |