Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: presubmit_support.py

Issue 6825008: First stab at using Rietveld wrapper object in both gcl.py and git-cl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: small fix Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « git_cl.py ('k') | rietveld.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 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.6' 9 __version__ = '1.6.1'
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 fnmatch 17 import fnmatch
18 import glob 18 import glob
19 import logging 19 import logging
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 r".*\bRelease[\\\/].*", 208 r".*\bRelease[\\\/].*",
209 r".*\bxcodebuild[\\\/].*", 209 r".*\bxcodebuild[\\\/].*",
210 r".*\bsconsbuild[\\\/].*", 210 r".*\bsconsbuild[\\\/].*",
211 # All caps files like README and LICENCE. 211 # All caps files like README and LICENCE.
212 r".*\b[A-Z0-9_]{2,}$", 212 r".*\b[A-Z0-9_]{2,}$",
213 # SCM (can happen in dual SCM configuration). (Slightly over aggressive) 213 # SCM (can happen in dual SCM configuration). (Slightly over aggressive)
214 r"(|.*[\\\/])\.git[\\\/].*", 214 r"(|.*[\\\/])\.git[\\\/].*",
215 r"(|.*[\\\/])\.svn[\\\/].*", 215 r"(|.*[\\\/])\.svn[\\\/].*",
216 ) 216 )
217 217
218 # TODO(dpranke): Update callers to pass in tbr, host_url, remove 218 def __init__(self, change, presubmit_path, is_committing, tbr,
219 # default arguments. 219 rietveld, verbose):
220 def __init__(self, change, presubmit_path, is_committing, tbr, host_url,
221 verbose):
222 """Builds an InputApi object. 220 """Builds an InputApi object.
223 221
224 Args: 222 Args:
225 change: A presubmit.Change object. 223 change: A presubmit.Change object.
226 presubmit_path: The path to the presubmit script being processed. 224 presubmit_path: The path to the presubmit script being processed.
227 is_committing: True if the change is about to be committed. 225 is_committing: True if the change is about to be committed.
228 tbr: True if '--tbr' was passed to skip any reviewer/owner checks 226 tbr: True if '--tbr' was passed to skip any reviewer/owner checks
229 host_url: scheme, host, and path of rietveld instance 227 rietveld: rietveld client object
230 """ 228 """
231 # Version number of the presubmit_support script. 229 # Version number of the presubmit_support script.
232 self.version = [int(x) for x in __version__.split('.')] 230 self.version = [int(x) for x in __version__.split('.')]
233 self.change = change 231 self.change = change
234 self.host_url = host_url
235 self.is_committing = is_committing 232 self.is_committing = is_committing
236 self.tbr = tbr 233 self.tbr = tbr
237 self.host_url = host_url or 'http://codereview.chromium.org' 234 self.rietveld = rietveld
235 # TBD
236 self.host_url = 'http://codereview.chromium.org'
237 if self.rietveld:
238 self.host_url = rietveld.url
238 239
239 # We expose various modules and functions as attributes of the input_api 240 # We expose various modules and functions as attributes of the input_api
240 # so that presubmit scripts don't have to import them. 241 # so that presubmit scripts don't have to import them.
241 self.basename = os.path.basename 242 self.basename = os.path.basename
242 self.cPickle = cPickle 243 self.cPickle = cPickle
243 self.cStringIO = cStringIO 244 self.cStringIO = cStringIO
244 self.json = json 245 self.json = json
245 self.os_listdir = os.listdir 246 self.os_listdir = os.listdir
246 self.os_walk = os.walk 247 self.os_walk = os.walk
247 self.os_path = os.path 248 self.os_path = os.path
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 results += executer.ExecPresubmitScript(presubmit_script, filename) 926 results += executer.ExecPresubmitScript(presubmit_script, filename)
926 927
927 slaves = list(set(results)) 928 slaves = list(set(results))
928 if slaves and verbose: 929 if slaves and verbose:
929 output_stream.write(', '.join(slaves)) 930 output_stream.write(', '.join(slaves))
930 output_stream.write('\n') 931 output_stream.write('\n')
931 return slaves 932 return slaves
932 933
933 934
934 class PresubmitExecuter(object): 935 class PresubmitExecuter(object):
935 def __init__(self, change, committing, tbr, host_url, verbose): 936 def __init__(self, change, committing, tbr, rietveld, verbose):
936 """ 937 """
937 Args: 938 Args:
938 change: The Change object. 939 change: The Change object.
939 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 940 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
940 tbr: True if '--tbr' was passed to skip any reviewer/owner checks 941 tbr: True if '--tbr' was passed to skip any reviewer/owner checks
941 host_url: scheme, host, and path of rietveld instance 942 rietveld: rietveld client object.
942 (or None for default)
943 """ 943 """
944 self.change = change 944 self.change = change
945 self.committing = committing 945 self.committing = committing
946 self.tbr = tbr 946 self.tbr = tbr
947 self.host_url = host_url 947 self.rietveld = rietveld
948 self.verbose = verbose 948 self.verbose = verbose
949 949
950 def ExecPresubmitScript(self, script_text, presubmit_path): 950 def ExecPresubmitScript(self, script_text, presubmit_path):
951 """Executes a single presubmit script. 951 """Executes a single presubmit script.
952 952
953 Args: 953 Args:
954 script_text: The text of the presubmit script. 954 script_text: The text of the presubmit script.
955 presubmit_path: The path to the presubmit file (this will be reported via 955 presubmit_path: The path to the presubmit file (this will be reported via
956 input_api.PresubmitLocalPath()). 956 input_api.PresubmitLocalPath()).
957 957
958 Return: 958 Return:
959 A list of result objects, empty if no problems. 959 A list of result objects, empty if no problems.
960 """ 960 """
961 961
962 # Change to the presubmit file's directory to support local imports. 962 # Change to the presubmit file's directory to support local imports.
963 main_path = os.getcwd() 963 main_path = os.getcwd()
964 os.chdir(os.path.dirname(presubmit_path)) 964 os.chdir(os.path.dirname(presubmit_path))
965 965
966 # Load the presubmit script into context. 966 # Load the presubmit script into context.
967 input_api = InputApi(self.change, presubmit_path, self.committing, 967 input_api = InputApi(self.change, presubmit_path, self.committing,
968 self.tbr, self.host_url, self.verbose) 968 self.tbr, self.rietveld, self.verbose)
969 context = {} 969 context = {}
970 try: 970 try:
971 exec script_text in context 971 exec script_text in context
972 except Exception, e: 972 except Exception, e:
973 raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e)) 973 raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e))
974 974
975 # These function names must change if we make substantial changes to 975 # These function names must change if we make substantial changes to
976 # the presubmit API that are not backwards compatible. 976 # the presubmit API that are not backwards compatible.
977 if self.committing: 977 if self.committing:
978 function_name = 'CheckChangeOnCommit' 978 function_name = 'CheckChangeOnCommit'
(...skipping 14 matching lines...) Expand all
993 'All presubmit results must be of types derived from ' 993 'All presubmit results must be of types derived from '
994 'output_api.PresubmitResult') 994 'output_api.PresubmitResult')
995 else: 995 else:
996 result = () # no error since the script doesn't care about current event. 996 result = () # no error since the script doesn't care about current event.
997 997
998 # Return the process to the original working directory. 998 # Return the process to the original working directory.
999 os.chdir(main_path) 999 os.chdir(main_path)
1000 return result 1000 return result
1001 1001
1002 1002
1003 # TODO(dpranke): make all callers pass in tbr, host_url?
1004 def DoPresubmitChecks(change, 1003 def DoPresubmitChecks(change,
1005 committing, 1004 committing,
1006 verbose, 1005 verbose,
1007 output_stream, 1006 output_stream,
1008 input_stream, 1007 input_stream,
1009 default_presubmit, 1008 default_presubmit,
1010 may_prompt, 1009 may_prompt,
1011 tbr=False, 1010 tbr,
1012 host_url=None): 1011 rietveld):
1013 """Runs all presubmit checks that apply to the files in the change. 1012 """Runs all presubmit checks that apply to the files in the change.
1014 1013
1015 This finds all PRESUBMIT.py files in directories enclosing the files in the 1014 This finds all PRESUBMIT.py files in directories enclosing the files in the
1016 change (up to the repository root) and calls the relevant entrypoint function 1015 change (up to the repository root) and calls the relevant entrypoint function
1017 depending on whether the change is being committed or uploaded. 1016 depending on whether the change is being committed or uploaded.
1018 1017
1019 Prints errors, warnings and notifications. Prompts the user for warnings 1018 Prints errors, warnings and notifications. Prompts the user for warnings
1020 when needed. 1019 when needed.
1021 1020
1022 Args: 1021 Args:
1023 change: The Change object. 1022 change: The Change object.
1024 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 1023 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
1025 verbose: Prints debug info. 1024 verbose: Prints debug info.
1026 output_stream: A stream to write output from presubmit tests to. 1025 output_stream: A stream to write output from presubmit tests to.
1027 input_stream: A stream to read input from the user. 1026 input_stream: A stream to read input from the user.
1028 default_presubmit: A default presubmit script to execute in any case. 1027 default_presubmit: A default presubmit script to execute in any case.
1029 may_prompt: Enable (y/n) questions on warning or error. 1028 may_prompt: Enable (y/n) questions on warning or error.
1030 tbr: was --tbr specified to skip any reviewer/owner checks? 1029 tbr: was --tbr specified to skip any reviewer/owner checks?
1031 host_url: scheme, host, and port of host to use for rietveld-related 1030 rietveld: rietveld object.
1032 checks
1033 1031
1034 Warning: 1032 Warning:
1035 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
1036 SHOULD be sys.stdin. 1034 SHOULD be sys.stdin.
1037 1035
1038 Return: 1036 Return:
1039 A PresubmitOutput object. Use output.should_continue() to figure out 1037 A PresubmitOutput object. Use output.should_continue() to figure out
1040 if there were errors or warnings and the caller should abort. 1038 if there were errors or warnings and the caller should abort.
1041 """ 1039 """
1042 output = PresubmitOutput(input_stream, output_stream) 1040 output = PresubmitOutput(input_stream, output_stream)
1043 if committing: 1041 if committing:
1044 output.write("Running presubmit commit checks ...\n") 1042 output.write("Running presubmit commit checks ...\n")
1045 else: 1043 else:
1046 output.write("Running presubmit upload checks ...\n") 1044 output.write("Running presubmit upload checks ...\n")
1047 start_time = time.time() 1045 start_time = time.time()
1048 presubmit_files = ListRelevantPresubmitFiles(change.AbsoluteLocalPaths(True), 1046 presubmit_files = ListRelevantPresubmitFiles(change.AbsoluteLocalPaths(True),
1049 change.RepositoryRoot()) 1047 change.RepositoryRoot())
1050 if not presubmit_files and verbose: 1048 if not presubmit_files and verbose:
1051 output.write("Warning, no presubmit.py found.\n") 1049 output.write("Warning, no presubmit.py found.\n")
1052 results = [] 1050 results = []
1053 executer = PresubmitExecuter(change, committing, tbr, host_url, verbose) 1051 executer = PresubmitExecuter(change, committing, tbr, rietveld, verbose)
1054 if default_presubmit: 1052 if default_presubmit:
1055 if verbose: 1053 if verbose:
1056 output.write("Running default presubmit script.\n") 1054 output.write("Running default presubmit script.\n")
1057 fake_path = os.path.join(change.RepositoryRoot(), 'PRESUBMIT.py') 1055 fake_path = os.path.join(change.RepositoryRoot(), 'PRESUBMIT.py')
1058 results += executer.ExecPresubmitScript(default_presubmit, fake_path) 1056 results += executer.ExecPresubmitScript(default_presubmit, fake_path)
1059 for filename in presubmit_files: 1057 for filename in presubmit_files:
1060 filename = os.path.abspath(filename) 1058 filename = os.path.abspath(filename)
1061 if verbose: 1059 if verbose:
1062 output.write("Running %s\n" % filename) 1060 output.write("Running %s\n" % filename)
1063 # Accept CRLF presubmit script. 1061 # Accept CRLF presubmit script.
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 options.description, 1191 options.description,
1194 options.root, 1192 options.root,
1195 files, 1193 files,
1196 options.issue, 1194 options.issue,
1197 options.patchset), 1195 options.patchset),
1198 options.commit, 1196 options.commit,
1199 options.verbose, 1197 options.verbose,
1200 sys.stdout, 1198 sys.stdout,
1201 sys.stdin, 1199 sys.stdin,
1202 options.default_presubmit, 1200 options.default_presubmit,
1203 options.may_prompt) 1201 options.may_prompt,
1202 False,
1203 None)
1204 return not results.should_continue() 1204 return not results.should_continue()
1205 except PresubmitFailure, e: 1205 except PresubmitFailure, e:
1206 print >> sys.stderr, e 1206 print >> sys.stderr, e
1207 print >> sys.stderr, 'Maybe your depot_tools is out of date?' 1207 print >> sys.stderr, 'Maybe your depot_tools is out of date?'
1208 print >> sys.stderr, 'If all fails, contact maruel@' 1208 print >> sys.stderr, 'If all fails, contact maruel@'
1209 return 2 1209 return 2
1210 1210
1211 1211
1212 if __name__ == '__main__': 1212 if __name__ == '__main__':
1213 fix_encoding.fix_encoding() 1213 fix_encoding.fix_encoding()
1214 sys.exit(Main(None)) 1214 sys.exit(Main(None))
OLDNEW
« no previous file with comments | « git_cl.py ('k') | rietveld.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698