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

Side by Side Diff: presubmit_support.py

Issue 7253015: Remove manual --tbr support and convert it into automatic TBR= detection. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: removed tests/tbr.sh Created 9 years, 5 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
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.1' 9 __version__ = '1.6.1'
10 10
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 r".*\bRelease[\\\/].*", 210 r".*\bRelease[\\\/].*",
211 r".*\bxcodebuild[\\\/].*", 211 r".*\bxcodebuild[\\\/].*",
212 r".*\bsconsbuild[\\\/].*", 212 r".*\bsconsbuild[\\\/].*",
213 # All caps files like README and LICENCE. 213 # All caps files like README and LICENCE.
214 r".*\b[A-Z0-9_]{2,}$", 214 r".*\b[A-Z0-9_]{2,}$",
215 # SCM (can happen in dual SCM configuration). (Slightly over aggressive) 215 # SCM (can happen in dual SCM configuration). (Slightly over aggressive)
216 r"(|.*[\\\/])\.git[\\\/].*", 216 r"(|.*[\\\/])\.git[\\\/].*",
217 r"(|.*[\\\/])\.svn[\\\/].*", 217 r"(|.*[\\\/])\.svn[\\\/].*",
218 ) 218 )
219 219
220 def __init__(self, change, presubmit_path, is_committing, tbr, 220 def __init__(self, change, presubmit_path, is_committing,
221 rietveld_obj, verbose): 221 rietveld_obj, verbose):
222 """Builds an InputApi object. 222 """Builds an InputApi object.
223 223
224 Args: 224 Args:
225 change: A presubmit.Change object. 225 change: A presubmit.Change object.
226 presubmit_path: The path to the presubmit script being processed. 226 presubmit_path: The path to the presubmit script being processed.
227 is_committing: True if the change is about to be committed. 227 is_committing: True if the change is about to be committed.
228 tbr: True if '--tbr' was passed to skip any reviewer/owner checks
229 rietveld_obj: rietveld.Rietveld client object 228 rietveld_obj: rietveld.Rietveld client object
230 """ 229 """
231 # Version number of the presubmit_support script. 230 # Version number of the presubmit_support script.
232 self.version = [int(x) for x in __version__.split('.')] 231 self.version = [int(x) for x in __version__.split('.')]
233 self.change = change 232 self.change = change
234 self.is_committing = is_committing 233 self.is_committing = is_committing
235 self.tbr = tbr
236 self.rietveld = rietveld_obj 234 self.rietveld = rietveld_obj
237 # TBD 235 # TBD
238 self.host_url = 'http://codereview.chromium.org' 236 self.host_url = 'http://codereview.chromium.org'
239 if self.rietveld: 237 if self.rietveld:
240 self.host_url = self.rietveld.url 238 self.host_url = self.rietveld.url
241 239
242 # 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
243 # so that presubmit scripts don't have to import them. 241 # so that presubmit scripts don't have to import them.
244 self.basename = os.path.basename 242 self.basename = os.path.basename
245 self.cPickle = cPickle 243 self.cPickle = cPickle
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 """Reads an arbitrary file. 408 """Reads an arbitrary file.
411 409
412 Deny reading anything outside the repository. 410 Deny reading anything outside the repository.
413 """ 411 """
414 if isinstance(file_item, AffectedFile): 412 if isinstance(file_item, AffectedFile):
415 file_item = file_item.AbsoluteLocalPath() 413 file_item = file_item.AbsoluteLocalPath()
416 if not file_item.startswith(self.change.RepositoryRoot()): 414 if not file_item.startswith(self.change.RepositoryRoot()):
417 raise IOError('Access outside the repository root is denied.') 415 raise IOError('Access outside the repository root is denied.')
418 return gclient_utils.FileRead(file_item, mode) 416 return gclient_utils.FileRead(file_item, mode)
419 417
418 @property
419 def tbr(self):
420 """Returns if a change is TBR'ed."""
421 return 'TBR' in self.change.tags
422
420 423
421 class AffectedFile(object): 424 class AffectedFile(object):
422 """Representation of a file in a change.""" 425 """Representation of a file in a change."""
423 # Method could be a function 426 # Method could be a function
424 # pylint: disable=R0201 427 # pylint: disable=R0201
425 def __init__(self, path, action, repository_root=''): 428 def __init__(self, path, action, repository_root=''):
426 self._path = path 429 self._path = path
427 self._action = action 430 self._action = action
428 self._local_root = repository_root 431 self._local_root = repository_root
429 self._is_directory = None 432 self._is_directory = None
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 presubmit_script, filename, project) 953 presubmit_script, filename, project)
951 954
952 slaves = list(set(results)) 955 slaves = list(set(results))
953 if slaves and verbose: 956 if slaves and verbose:
954 output_stream.write(', '.join(slaves)) 957 output_stream.write(', '.join(slaves))
955 output_stream.write('\n') 958 output_stream.write('\n')
956 return slaves 959 return slaves
957 960
958 961
959 class PresubmitExecuter(object): 962 class PresubmitExecuter(object):
960 def __init__(self, change, committing, tbr, rietveld_obj, verbose): 963 def __init__(self, change, committing, rietveld_obj, verbose):
961 """ 964 """
962 Args: 965 Args:
963 change: The Change object. 966 change: The Change object.
964 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 967 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
965 tbr: True if '--tbr' was passed to skip any reviewer/owner checks
966 rietveld_obj: rietveld.Rietveld client object. 968 rietveld_obj: rietveld.Rietveld client object.
967 """ 969 """
968 self.change = change 970 self.change = change
969 self.committing = committing 971 self.committing = committing
970 self.tbr = tbr
971 self.rietveld = rietveld_obj 972 self.rietveld = rietveld_obj
972 self.verbose = verbose 973 self.verbose = verbose
973 974
974 def ExecPresubmitScript(self, script_text, presubmit_path): 975 def ExecPresubmitScript(self, script_text, presubmit_path):
975 """Executes a single presubmit script. 976 """Executes a single presubmit script.
976 977
977 Args: 978 Args:
978 script_text: The text of the presubmit script. 979 script_text: The text of the presubmit script.
979 presubmit_path: The path to the presubmit file (this will be reported via 980 presubmit_path: The path to the presubmit file (this will be reported via
980 input_api.PresubmitLocalPath()). 981 input_api.PresubmitLocalPath()).
981 982
982 Return: 983 Return:
983 A list of result objects, empty if no problems. 984 A list of result objects, empty if no problems.
984 """ 985 """
985 986
986 # Change to the presubmit file's directory to support local imports. 987 # Change to the presubmit file's directory to support local imports.
987 main_path = os.getcwd() 988 main_path = os.getcwd()
988 os.chdir(os.path.dirname(presubmit_path)) 989 os.chdir(os.path.dirname(presubmit_path))
989 990
990 # Load the presubmit script into context. 991 # Load the presubmit script into context.
991 input_api = InputApi(self.change, presubmit_path, self.committing, 992 input_api = InputApi(self.change, presubmit_path, self.committing,
992 self.tbr, self.rietveld, self.verbose) 993 self.rietveld, self.verbose)
993 context = {} 994 context = {}
994 try: 995 try:
995 exec script_text in context 996 exec script_text in context
996 except Exception, e: 997 except Exception, e:
997 raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e)) 998 raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e))
998 999
999 # These function names must change if we make substantial changes to 1000 # These function names must change if we make substantial changes to
1000 # the presubmit API that are not backwards compatible. 1001 # the presubmit API that are not backwards compatible.
1001 if self.committing: 1002 if self.committing:
1002 function_name = 'CheckChangeOnCommit' 1003 function_name = 'CheckChangeOnCommit'
(...skipping 21 matching lines...) Expand all
1024 return result 1025 return result
1025 1026
1026 1027
1027 def DoPresubmitChecks(change, 1028 def DoPresubmitChecks(change,
1028 committing, 1029 committing,
1029 verbose, 1030 verbose,
1030 output_stream, 1031 output_stream,
1031 input_stream, 1032 input_stream,
1032 default_presubmit, 1033 default_presubmit,
1033 may_prompt, 1034 may_prompt,
1034 tbr,
1035 rietveld_obj): 1035 rietveld_obj):
1036 """Runs all presubmit checks that apply to the files in the change. 1036 """Runs all presubmit checks that apply to the files in the change.
1037 1037
1038 This finds all PRESUBMIT.py files in directories enclosing the files in the 1038 This finds all PRESUBMIT.py files in directories enclosing the files in the
1039 change (up to the repository root) and calls the relevant entrypoint function 1039 change (up to the repository root) and calls the relevant entrypoint function
1040 depending on whether the change is being committed or uploaded. 1040 depending on whether the change is being committed or uploaded.
1041 1041
1042 Prints errors, warnings and notifications. Prompts the user for warnings 1042 Prints errors, warnings and notifications. Prompts the user for warnings
1043 when needed. 1043 when needed.
1044 1044
1045 Args: 1045 Args:
1046 change: The Change object. 1046 change: The Change object.
1047 committing: True if 'gcl commit' is running, False if 'gcl upload' is. 1047 committing: True if 'gcl commit' is running, False if 'gcl upload' is.
1048 verbose: Prints debug info. 1048 verbose: Prints debug info.
1049 output_stream: A stream to write output from presubmit tests to. 1049 output_stream: A stream to write output from presubmit tests to.
1050 input_stream: A stream to read input from the user. 1050 input_stream: A stream to read input from the user.
1051 default_presubmit: A default presubmit script to execute in any case. 1051 default_presubmit: A default presubmit script to execute in any case.
1052 may_prompt: Enable (y/n) questions on warning or error. 1052 may_prompt: Enable (y/n) questions on warning or error.
1053 tbr: was --tbr specified to skip any reviewer/owner checks?
1054 rietveld_obj: rietveld.Rietveld object. 1053 rietveld_obj: rietveld.Rietveld object.
1055 1054
1056 Warning: 1055 Warning:
1057 If may_prompt is true, output_stream SHOULD be sys.stdout and input_stream 1056 If may_prompt is true, output_stream SHOULD be sys.stdout and input_stream
1058 SHOULD be sys.stdin. 1057 SHOULD be sys.stdin.
1059 1058
1060 Return: 1059 Return:
1061 A PresubmitOutput object. Use output.should_continue() to figure out 1060 A PresubmitOutput object. Use output.should_continue() to figure out
1062 if there were errors or warnings and the caller should abort. 1061 if there were errors or warnings and the caller should abort.
1063 """ 1062 """
1064 old_environ = os.environ 1063 old_environ = os.environ
1065 try: 1064 try:
1066 # Make sure python subprocesses won't generate .pyc files. 1065 # Make sure python subprocesses won't generate .pyc files.
1067 os.environ = os.environ.copy() 1066 os.environ = os.environ.copy()
1068 os.environ['PYTHONDONTWRITEBYTECODE'] = '1' 1067 os.environ['PYTHONDONTWRITEBYTECODE'] = '1'
1069 1068
1070 output = PresubmitOutput(input_stream, output_stream) 1069 output = PresubmitOutput(input_stream, output_stream)
1071 if committing: 1070 if committing:
1072 output.write("Running presubmit commit checks ...\n") 1071 output.write("Running presubmit commit checks ...\n")
1073 else: 1072 else:
1074 output.write("Running presubmit upload checks ...\n") 1073 output.write("Running presubmit upload checks ...\n")
1075 start_time = time.time() 1074 start_time = time.time()
1076 presubmit_files = ListRelevantPresubmitFiles( 1075 presubmit_files = ListRelevantPresubmitFiles(
1077 change.AbsoluteLocalPaths(True), change.RepositoryRoot()) 1076 change.AbsoluteLocalPaths(True), change.RepositoryRoot())
1078 if not presubmit_files and verbose: 1077 if not presubmit_files and verbose:
1079 output.write("Warning, no presubmit.py found.\n") 1078 output.write("Warning, no presubmit.py found.\n")
1080 results = [] 1079 results = []
1081 executer = PresubmitExecuter(change, committing, tbr, rietveld_obj, verbose) 1080 executer = PresubmitExecuter(change, committing, rietveld_obj, verbose)
1082 if default_presubmit: 1081 if default_presubmit:
1083 if verbose: 1082 if verbose:
1084 output.write("Running default presubmit script.\n") 1083 output.write("Running default presubmit script.\n")
1085 fake_path = os.path.join(change.RepositoryRoot(), 'PRESUBMIT.py') 1084 fake_path = os.path.join(change.RepositoryRoot(), 'PRESUBMIT.py')
1086 results += executer.ExecPresubmitScript(default_presubmit, fake_path) 1085 results += executer.ExecPresubmitScript(default_presubmit, fake_path)
1087 for filename in presubmit_files: 1086 for filename in presubmit_files:
1088 filename = os.path.abspath(filename) 1087 filename = os.path.abspath(filename)
1089 if verbose: 1088 if verbose:
1090 output.write("Running %s\n" % filename) 1089 output.write("Running %s\n" % filename)
1091 # Accept CRLF presubmit script. 1090 # Accept CRLF presubmit script.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 files, 1234 files,
1236 options.issue, 1235 options.issue,
1237 options.patchset, 1236 options.patchset,
1238 options.author), 1237 options.author),
1239 options.commit, 1238 options.commit,
1240 options.verbose, 1239 options.verbose,
1241 sys.stdout, 1240 sys.stdout,
1242 sys.stdin, 1241 sys.stdin,
1243 options.default_presubmit, 1242 options.default_presubmit,
1244 options.may_prompt, 1243 options.may_prompt,
1245 False,
1246 rietveld_obj) 1244 rietveld_obj)
1247 return not results.should_continue() 1245 return not results.should_continue()
1248 except PresubmitFailure, e: 1246 except PresubmitFailure, e:
1249 print >> sys.stderr, e 1247 print >> sys.stderr, e
1250 print >> sys.stderr, 'Maybe your depot_tools is out of date?' 1248 print >> sys.stderr, 'Maybe your depot_tools is out of date?'
1251 print >> sys.stderr, 'If all fails, contact maruel@' 1249 print >> sys.stderr, 'If all fails, contact maruel@'
1252 return 2 1250 return 2
1253 1251
1254 1252
1255 if __name__ == '__main__': 1253 if __name__ == '__main__':
1256 fix_encoding.fix_encoding() 1254 fix_encoding.fix_encoding()
1257 sys.exit(Main(None)) 1255 sys.exit(Main(None))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698