OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 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.5' | 9 __version__ = '1.3.5' |
10 | 10 |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
220 r".*\bRelease[\\\/].*", | 220 r".*\bRelease[\\\/].*", |
221 r".*\bxcodebuild[\\\/].*", | 221 r".*\bxcodebuild[\\\/].*", |
222 r".*\bsconsbuild[\\\/].*", | 222 r".*\bsconsbuild[\\\/].*", |
223 # All caps files like README and LICENCE. | 223 # All caps files like README and LICENCE. |
224 r".*\b[A-Z0-9_]{2,}$", | 224 r".*\b[A-Z0-9_]{2,}$", |
225 # SCM (can happen in dual SCM configuration). (Slightly over aggressive) | 225 # SCM (can happen in dual SCM configuration). (Slightly over aggressive) |
226 r"(|.*[\\\/])\.git[\\\/].*", | 226 r"(|.*[\\\/])\.git[\\\/].*", |
227 r"(|.*[\\\/])\.svn[\\\/].*", | 227 r"(|.*[\\\/])\.svn[\\\/].*", |
228 ) | 228 ) |
229 | 229 |
230 # TODO(dpranke): Update callers to pass in is_tbr, host_url, remove | 230 def __init__(self, change, presubmit_path, is_committing, tbr, host_url=None): |
231 # default arguments. | |
232 def __init__(self, change, presubmit_path, is_committing, is_tbr=False, | |
233 host_url='http://codereview.chromium.org'): | |
234 """Builds an InputApi object. | 231 """Builds an InputApi object. |
235 | 232 |
236 Args: | 233 Args: |
237 change: A presubmit.Change object. | 234 change: A presubmit.Change object. |
238 presubmit_path: The path to the presubmit script being processed. | 235 presubmit_path: The path to the presubmit script being processed. |
239 is_committing: True if the change is about to be committed. | 236 is_committing: True if the change is about to be committed. |
237 tbr: True if '--tbr' was passed to skip any reviewer/owner checks | |
238 host_url: scheme, host, and path of rietveld instance | |
240 """ | 239 """ |
241 # Version number of the presubmit_support script. | 240 # Version number of the presubmit_support script. |
242 self.version = [int(x) for x in __version__.split('.')] | 241 self.version = [int(x) for x in __version__.split('.')] |
243 self.change = change | 242 self.change = change |
244 self.host_url = host_url | 243 self.host_url = host_url |
245 self.is_committing = is_committing | 244 self.is_committing = is_committing |
246 self.is_tbr = is_tbr | 245 self.tbr = tbr |
246 self.host_url = host_url or 'http://codereview.chromium.org' | |
M-A Ruel
2011/03/11 00:48:41
Bad idea. You don't want reviews on the private in
| |
247 | 247 |
248 # We expose various modules and functions as attributes of the input_api | 248 # We expose various modules and functions as attributes of the input_api |
249 # so that presubmit scripts don't have to import them. | 249 # so that presubmit scripts don't have to import them. |
250 self.basename = os.path.basename | 250 self.basename = os.path.basename |
251 self.cPickle = cPickle | 251 self.cPickle = cPickle |
252 self.cStringIO = cStringIO | 252 self.cStringIO = cStringIO |
253 self.json = json | 253 self.json = json |
254 self.os_path = os.path | 254 self.os_path = os.path |
255 self.pickle = pickle | 255 self.pickle = pickle |
256 self.marshal = marshal | 256 self.marshal = marshal |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
928 results += executer.ExecPresubmitScript(presubmit_script) | 928 results += executer.ExecPresubmitScript(presubmit_script) |
929 | 929 |
930 slaves = list(set(results)) | 930 slaves = list(set(results)) |
931 if slaves and verbose: | 931 if slaves and verbose: |
932 output_stream.write(', '.join(slaves)) | 932 output_stream.write(', '.join(slaves)) |
933 output_stream.write('\n') | 933 output_stream.write('\n') |
934 return slaves | 934 return slaves |
935 | 935 |
936 | 936 |
937 class PresubmitExecuter(object): | 937 class PresubmitExecuter(object): |
938 def __init__(self, change, committing): | 938 def __init__(self, change, committing, tbr, host_url): |
939 """ | 939 """ |
940 Args: | 940 Args: |
941 change: The Change object. | 941 change: The Change object. |
942 committing: True if 'gcl commit' is running, False if 'gcl upload' is. | 942 committing: True if 'gcl commit' is running, False if 'gcl upload' is. |
943 tbr: True if '--tbr' was passed to skip any reviewer/owner checks | |
944 host_url: scheme, host, and path of rietveld instance | |
945 (or None for default) | |
943 """ | 946 """ |
944 self.change = change | 947 self.change = change |
945 self.committing = committing | 948 self.committing = committing |
949 self.tbr = tbr | |
950 self.host_url = host_url | |
946 | 951 |
947 def ExecPresubmitScript(self, script_text, presubmit_path): | 952 def ExecPresubmitScript(self, script_text, presubmit_path): |
948 """Executes a single presubmit script. | 953 """Executes a single presubmit script. |
949 | 954 |
950 Args: | 955 Args: |
951 script_text: The text of the presubmit script. | 956 script_text: The text of the presubmit script. |
952 presubmit_path: The path to the presubmit file (this will be reported via | 957 presubmit_path: The path to the presubmit file (this will be reported via |
953 input_api.PresubmitLocalPath()). | 958 input_api.PresubmitLocalPath()). |
954 | 959 |
955 Return: | 960 Return: |
956 A list of result objects, empty if no problems. | 961 A list of result objects, empty if no problems. |
957 """ | 962 """ |
958 | 963 |
959 # Change to the presubmit file's directory to support local imports. | 964 # Change to the presubmit file's directory to support local imports. |
960 main_path = os.getcwd() | 965 main_path = os.getcwd() |
961 os.chdir(os.path.dirname(presubmit_path)) | 966 os.chdir(os.path.dirname(presubmit_path)) |
962 | 967 |
963 # Load the presubmit script into context. | 968 # Load the presubmit script into context. |
964 input_api = InputApi(self.change, presubmit_path, self.committing) | 969 input_api = InputApi(self.change, presubmit_path, self.committing, |
970 self.tbr, self.host_url) | |
965 context = {} | 971 context = {} |
966 exec script_text in context | 972 exec script_text in context |
967 | 973 |
968 # These function names must change if we make substantial changes to | 974 # These function names must change if we make substantial changes to |
969 # the presubmit API that are not backwards compatible. | 975 # the presubmit API that are not backwards compatible. |
970 if self.committing: | 976 if self.committing: |
971 function_name = 'CheckChangeOnCommit' | 977 function_name = 'CheckChangeOnCommit' |
972 else: | 978 else: |
973 function_name = 'CheckChangeOnUpload' | 979 function_name = 'CheckChangeOnUpload' |
974 if function_name in context: | 980 if function_name in context: |
(...skipping 10 matching lines...) Expand all Loading... | |
985 raise exceptions.RuntimeError( | 991 raise exceptions.RuntimeError( |
986 'All presubmit results must be of types derived from ' | 992 'All presubmit results must be of types derived from ' |
987 'output_api.PresubmitResult') | 993 'output_api.PresubmitResult') |
988 else: | 994 else: |
989 result = () # no error since the script doesn't care about current event. | 995 result = () # no error since the script doesn't care about current event. |
990 | 996 |
991 # Return the process to the original working directory. | 997 # Return the process to the original working directory. |
992 os.chdir(main_path) | 998 os.chdir(main_path) |
993 return result | 999 return result |
994 | 1000 |
995 | 1001 # TODO(dpranke): make all callers pass in tbr, host_url? |
996 def DoPresubmitChecks(change, | 1002 def DoPresubmitChecks(change, |
997 committing, | 1003 committing, |
998 verbose, | 1004 verbose, |
999 output_stream, | 1005 output_stream, |
1000 input_stream, | 1006 input_stream, |
1001 default_presubmit, | 1007 default_presubmit, |
1002 may_prompt): | 1008 may_prompt, |
1009 tbr=False, | |
1010 host_url=None): | |
1003 """Runs all presubmit checks that apply to the files in the change. | 1011 """Runs all presubmit checks that apply to the files in the change. |
1004 | 1012 |
1005 This finds all PRESUBMIT.py files in directories enclosing the files in the | 1013 This finds all PRESUBMIT.py files in directories enclosing the files in the |
1006 change (up to the repository root) and calls the relevant entrypoint function | 1014 change (up to the repository root) and calls the relevant entrypoint function |
1007 depending on whether the change is being committed or uploaded. | 1015 depending on whether the change is being committed or uploaded. |
1008 | 1016 |
1009 Prints errors, warnings and notifications. Prompts the user for warnings | 1017 Prints errors, warnings and notifications. Prompts the user for warnings |
1010 when needed. | 1018 when needed. |
1011 | 1019 |
1012 Args: | 1020 Args: |
1013 change: The Change object. | 1021 change: The Change object. |
1014 committing: True if 'gcl commit' is running, False if 'gcl upload' is. | 1022 committing: True if 'gcl commit' is running, False if 'gcl upload' is. |
1015 verbose: Prints debug info. | 1023 verbose: Prints debug info. |
1016 output_stream: A stream to write output from presubmit tests to. | 1024 output_stream: A stream to write output from presubmit tests to. |
1017 input_stream: A stream to read input from the user. | 1025 input_stream: A stream to read input from the user. |
1018 default_presubmit: A default presubmit script to execute in any case. | 1026 default_presubmit: A default presubmit script to execute in any case. |
1019 may_prompt: Enable (y/n) questions on warning or error. | 1027 may_prompt: Enable (y/n) questions on warning or error. |
1028 tbr: was --tbr specified to skip any reviewer/owner checks? | |
1029 host_url: scheme, host, and port of host to use for rietveld-related | |
1030 checks | |
1020 | 1031 |
1021 Warning: | 1032 Warning: |
1022 If may_prompt is true, output_stream SHOULD be sys.stdout and input_stream | 1033 If may_prompt is true, output_stream SHOULD be sys.stdout and input_stream |
1023 SHOULD be sys.stdin. | 1034 SHOULD be sys.stdin. |
1024 | 1035 |
1025 Return: | 1036 Return: |
1026 True if execution can continue, False if not. | 1037 True if execution can continue, False if not. |
1027 """ | 1038 """ |
1028 print "Running presubmit hooks..." | 1039 print "Running presubmit hooks..." |
1029 start_time = time.time() | 1040 start_time = time.time() |
1030 presubmit_files = ListRelevantPresubmitFiles(change.AbsoluteLocalPaths(True), | 1041 presubmit_files = ListRelevantPresubmitFiles(change.AbsoluteLocalPaths(True), |
1031 change.RepositoryRoot()) | 1042 change.RepositoryRoot()) |
1032 if not presubmit_files and verbose: | 1043 if not presubmit_files and verbose: |
1033 output_stream.write("Warning, no presubmit.py found.\n") | 1044 output_stream.write("Warning, no presubmit.py found.\n") |
1034 results = [] | 1045 results = [] |
1035 executer = PresubmitExecuter(change, committing) | 1046 executer = PresubmitExecuter(change, committing, tbr, host_url) |
1036 if default_presubmit: | 1047 if default_presubmit: |
1037 if verbose: | 1048 if verbose: |
1038 output_stream.write("Running default presubmit script.\n") | 1049 output_stream.write("Running default presubmit script.\n") |
1039 fake_path = os.path.join(change.RepositoryRoot(), 'PRESUBMIT.py') | 1050 fake_path = os.path.join(change.RepositoryRoot(), 'PRESUBMIT.py') |
1040 results += executer.ExecPresubmitScript(default_presubmit, fake_path) | 1051 results += executer.ExecPresubmitScript(default_presubmit, fake_path) |
1041 for filename in presubmit_files: | 1052 for filename in presubmit_files: |
1042 filename = os.path.abspath(filename) | 1053 filename = os.path.abspath(filename) |
1043 if verbose: | 1054 if verbose: |
1044 output_stream.write("Running %s\n" % filename) | 1055 output_stream.write("Running %s\n" % filename) |
1045 # Accept CRLF presubmit script. | 1056 # Accept CRLF presubmit script. |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1185 options.commit, | 1196 options.commit, |
1186 options.verbose, | 1197 options.verbose, |
1187 sys.stdout, | 1198 sys.stdout, |
1188 sys.stdin, | 1199 sys.stdin, |
1189 options.default_presubmit, | 1200 options.default_presubmit, |
1190 options.may_prompt) | 1201 options.may_prompt) |
1191 | 1202 |
1192 | 1203 |
1193 if __name__ == '__main__': | 1204 if __name__ == '__main__': |
1194 sys.exit(Main(sys.argv)) | 1205 sys.exit(Main(sys.argv)) |
OLD | NEW |