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

Unified Diff: presubmit_support.py

Issue 6810012: Add verbose support throught presubmit checks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: merge error 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « presubmit_canned_checks.py ('k') | tests/presubmit_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: presubmit_support.py
diff --git a/presubmit_support.py b/presubmit_support.py
index 4df39c02b485391ba4ff0bd0b69b2e3395120e22..0929bd1c83e8a2a5fe2dd18728fdd81b8efa352a 100755
--- a/presubmit_support.py
+++ b/presubmit_support.py
@@ -6,7 +6,7 @@
"""Enables directory-specific presubmit checks to run at upload and/or commit.
"""
-__version__ = '1.5'
+__version__ = '1.6'
# TODO(joi) Add caching where appropriate/needed. The API is designed to allow
# caching (between all different invocations of presubmit scripts for a given
@@ -14,7 +14,6 @@ __version__ = '1.5'
import cPickle # Exposed through the API.
import cStringIO # Exposed through the API.
-import exceptions
import fnmatch
import glob
import logging
@@ -56,11 +55,7 @@ import subprocess2 as subprocess # Exposed through the API.
_ASKED_FOR_FEEDBACK = False
-class NotImplementedException(Exception):
- """We're leaving placeholders in a bunch of places to remind us of the
- design of the API, but we have not implemented all of it yet. Implement as
- the need arises.
- """
+class PresubmitFailure(Exception):
pass
@@ -178,7 +173,7 @@ class OutputApi(object):
"""A warning that should be included in the review request email."""
def __init__(self, *args, **kwargs):
super(OutputApi.MailTextResult, self).__init__()
- raise NotImplementedException()
+ raise NotImplementedError()
class InputApi(object):
@@ -222,7 +217,8 @@ class InputApi(object):
# TODO(dpranke): Update callers to pass in tbr, host_url, remove
# default arguments.
- def __init__(self, change, presubmit_path, is_committing, tbr, host_url=None):
+ def __init__(self, change, presubmit_path, is_committing, tbr, host_url,
+ verbose):
"""Builds an InputApi object.
Args:
@@ -276,6 +272,7 @@ class InputApi(object):
# in order to be able to handle wildcard OWNERS files?
self.owners_db = owners.Database(change.RepositoryRoot(),
fopen=file, os_path=self.os_path)
+ self.verbose = verbose
def PresubmitLocalPath(self):
"""Returns the local path of the presubmit script currently being run.
@@ -595,7 +592,7 @@ class GitAffectedFile(AffectedFile):
def ServerPath(self):
if self._server_path is None:
- raise NotImplementedException() # TODO(maruel) Implement.
+ raise NotImplementedError('TODO(maruel) Implement.')
return self._server_path
def IsDirectory(self):
@@ -606,13 +603,12 @@ class GitAffectedFile(AffectedFile):
# querying subversion, especially on Windows.
self._is_directory = os.path.isdir(path)
else:
- # raise NotImplementedException() # TODO(maruel) Implement.
self._is_directory = False
return self._is_directory
def Property(self, property_name):
if not property_name in self._properties:
- raise NotImplementedException() # TODO(maruel) Implement.
+ raise NotImplementedError('TODO(maruel) Implement.')
return self._properties[property_name]
def IsTextFile(self):
@@ -623,7 +619,6 @@ class GitAffectedFile(AffectedFile):
elif self.IsDirectory():
self._is_text_file = False
else:
- # raise NotImplementedException() # TODO(maruel) Implement.
self._is_text_file = os.path.isfile(self.AbsoluteLocalPath())
return self._is_text_file
@@ -861,7 +856,7 @@ def ListRelevantPresubmitFiles(files, root):
class GetTrySlavesExecuter(object):
@staticmethod
- def ExecPresubmitScript(script_text):
+ def ExecPresubmitScript(script_text, presubmit_path):
"""Executes GetPreferredTrySlaves() from a single presubmit script.
Args:
@@ -871,21 +866,24 @@ class GetTrySlavesExecuter(object):
A list of try slaves.
"""
context = {}
- exec script_text in context
+ try:
+ exec script_text in context
+ except Exception, e:
+ raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e))
function_name = 'GetPreferredTrySlaves'
if function_name in context:
result = eval(function_name + '()', context)
if not isinstance(result, types.ListType):
- raise exceptions.RuntimeError(
+ raise PresubmitFailure(
'Presubmit functions must return a list, got a %s instead: %s' %
(type(result), str(result)))
for item in result:
if not isinstance(item, basestring):
- raise exceptions.RuntimeError('All try slaves names must be strings.')
+ raise PresubmitFailure('All try slaves names must be strings.')
if item != item.strip():
- raise exceptions.RuntimeError('Try slave names cannot start/end'
- 'with whitespace')
+ raise PresubmitFailure(
+ 'Try slave names cannot start/end with whitespace')
else:
result = []
return result
@@ -916,14 +914,15 @@ def DoGetTrySlaves(changed_files,
if default_presubmit:
if verbose:
output_stream.write("Running default presubmit script.\n")
- results += executer.ExecPresubmitScript(default_presubmit)
+ fake_path = os.path.join(repository_root, 'PRESUBMIT.py')
+ results += executer.ExecPresubmitScript(default_presubmit, fake_path)
for filename in presubmit_files:
filename = os.path.abspath(filename)
if verbose:
output_stream.write("Running %s\n" % filename)
# Accept CRLF presubmit script.
presubmit_script = gclient_utils.FileRead(filename, 'rU')
- results += executer.ExecPresubmitScript(presubmit_script)
+ results += executer.ExecPresubmitScript(presubmit_script, filename)
slaves = list(set(results))
if slaves and verbose:
@@ -933,7 +932,7 @@ def DoGetTrySlaves(changed_files,
class PresubmitExecuter(object):
- def __init__(self, change, committing, tbr, host_url):
+ def __init__(self, change, committing, tbr, host_url, verbose):
"""
Args:
change: The Change object.
@@ -946,6 +945,7 @@ class PresubmitExecuter(object):
self.committing = committing
self.tbr = tbr
self.host_url = host_url
+ self.verbose = verbose
def ExecPresubmitScript(self, script_text, presubmit_path):
"""Executes a single presubmit script.
@@ -965,9 +965,12 @@ class PresubmitExecuter(object):
# Load the presubmit script into context.
input_api = InputApi(self.change, presubmit_path, self.committing,
- self.tbr, self.host_url)
+ self.tbr, self.host_url, self.verbose)
context = {}
- exec script_text in context
+ try:
+ exec script_text in context
+ except Exception, e:
+ raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e))
# These function names must change if we make substantial changes to
# the presubmit API that are not backwards compatible.
@@ -982,11 +985,11 @@ class PresubmitExecuter(object):
logging.debug('Running %s done.' % function_name)
if not (isinstance(result, types.TupleType) or
isinstance(result, types.ListType)):
- raise exceptions.RuntimeError(
+ raise PresubmitFailure(
'Presubmit functions must return a tuple or list')
for item in result:
if not isinstance(item, OutputApi.PresubmitResult):
- raise exceptions.RuntimeError(
+ raise PresubmitFailure(
'All presubmit results must be of types derived from '
'output_api.PresubmitResult')
else:
@@ -1047,7 +1050,7 @@ def DoPresubmitChecks(change,
if not presubmit_files and verbose:
output.write("Warning, no presubmit.py found.\n")
results = []
- executer = PresubmitExecuter(change, committing, tbr, host_url)
+ executer = PresubmitExecuter(change, committing, tbr, host_url, verbose)
if default_presubmit:
if verbose:
output.write("Running default presubmit script.\n")
@@ -1160,8 +1163,8 @@ def Main(argv):
help="Use upload instead of commit checks")
parser.add_option("-r", "--recursive", action="store_true",
help="Act recursively")
- parser.add_option("-v", "--verbose", action="store_true", default=False,
- help="Verbose output")
+ parser.add_option("-v", "--verbose", action="count", default=0,
+ help="Use 2 times for more debug info")
parser.add_option("--name", default='no name')
parser.add_option("--description", default='')
parser.add_option("--issue", type='int', default=0)
@@ -1174,26 +1177,36 @@ def Main(argv):
parser.add_option("--default_presubmit")
parser.add_option("--may_prompt", action='store_true', default=False)
options, args = parser.parse_args(argv)
- if options.verbose:
+ if options.verbose >= 2:
logging.basicConfig(level=logging.DEBUG)
+ elif options.verbose:
+ logging.basicConfig(level=logging.INFO)
+ else:
+ logging.basicConfig(level=logging.ERROR)
change_class, files = load_files(options, args)
if not change_class:
parser.error('For unversioned directory, <files> is not optional.')
- if options.verbose:
- print "Found %d file(s)." % len(files)
- results = DoPresubmitChecks(change_class(options.name,
- options.description,
- options.root,
- files,
- options.issue,
- options.patchset),
- options.commit,
- options.verbose,
- sys.stdout,
- sys.stdin,
- options.default_presubmit,
- options.may_prompt)
- return not results.should_continue()
+ logging.info('Found %d file(s).' % len(files))
+ try:
+ results = DoPresubmitChecks(
+ change_class(options.name,
+ options.description,
+ options.root,
+ files,
+ options.issue,
+ options.patchset),
+ options.commit,
+ options.verbose,
+ sys.stdout,
+ sys.stdin,
+ options.default_presubmit,
+ options.may_prompt)
+ return not results.should_continue()
+ except PresubmitFailure, e:
+ print >> sys.stderr, e
+ print >> sys.stderr, 'Maybe your depot_tools is out of date?'
+ print >> sys.stderr, 'If all fails, contact maruel@'
+ return 2
if __name__ == '__main__':
« no previous file with comments | « presubmit_canned_checks.py ('k') | tests/presubmit_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698