Chromium Code Reviews| 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 |