From 61e0b691d678aef2d408d041d30faf6e8a9ecd07 Mon Sep 17 00:00:00 2001 From: "maruel@chromium.org" Date: Tue, 12 Apr 2011 21:01:01 +0000 Subject: [PATCH] Add script to apply a patch from rietveld. At the moment it just fetches the patch. It's still useful to debug rietveld issues. Improve resiliency to invalid patches. R=dpranke@chromium.org BUG= TEST= Review URL: http://codereview.chromium.org/6825085 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@81305 0039d316-1c4b-4281-b951-d872f2087c98 --- apply_issue.py | 62 +++++++++++++++++++++++++++++++++++++++++++++ patch.py | 2 ++ rietveld.py | 7 +++-- tests/patch_test.py | 14 ++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100755 apply_issue.py diff --git a/apply_issue.py b/apply_issue.py new file mode 100755 index 0000000000..a012648b1d --- /dev/null +++ b/apply_issue.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Applies an issue from Rietveld. +""" + +import logging +import optparse +import sys + +import breakpad # pylint: disable=W0611 +import fix_encoding +import rietveld + + +def main(): + parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) + parser.add_option( + '-v', '--verbose', action='count', help='Prints debugging infos') + parser.add_option( + '-i', '--issue', type='int', help='Rietveld issue number') + parser.add_option( + '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number') + parser.add_option( + '-r', + '--root_dir', + action='store', + help='Root directory to apply the patch') + parser.add_option( + '-s', + '--server', + action='store', + default='http://codereview.chromium.org', + help='Rietveld server') + options, args = parser.parse_args() + LOG_FORMAT = '%(levelname)s %(filename)s(%(lineno)d): %(message)s' + if not options.verbose: + logging.basicConfig(level=logging.WARNING, format=LOG_FORMAT) + elif options.verbose == 1: + logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) + elif options.verbose > 1: + logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT) + if args: + parser.error('Extra argument(s) "%s" not understood' % ' '.join(args)) + if not options.issue: + parser.error('Require --issue') + + obj = rietveld.Rietveld(options.server, None, None) + + if not options.patchset: + options.patchset = obj.get_issue_properties( + options.issue, False)['patchsets'][-1] + logging.info('Using patchset %d' % options.patchset) + obj.get_patch(options.issue, options.patchset) + return 0 + + +if __name__ == "__main__": + fix_encoding.fix_encoding() + sys.exit(main()) diff --git a/patch.py b/patch.py index 18c16e2c82..f6b19aca2e 100644 --- a/patch.py +++ b/patch.py @@ -89,6 +89,8 @@ class FilePatchDiff(FilePatchBase): def __init__(self, filename, diff, svn_properties): super(FilePatchDiff, self).__init__(filename) + if not diff: + self._fail('File doesn\'t have a diff.') self.diff_header, self.diff_hunks = self._split_header(diff) self.svn_properties = svn_properties or [] self.is_git_diff = self._is_git_diff_header(self.diff_header) diff --git a/rietveld.py b/rietveld.py index 98422d6467..0bcb19f4a8 100644 --- a/rietveld.py +++ b/rietveld.py @@ -112,10 +112,11 @@ class Rietveld(object): props = self.get_patchset_properties(issue, patchset) or {} out = [] for filename, state in props.get('files', {}).iteritems(): + logging.debug('%s' % filename) status = state.get('status') if status is None: raise patch.UnsupportedPatchFormat( - filename, 'File\'s status is None, patchset upload is incomplete') + filename, 'File\'s status is None, patchset upload is incomplete.') # TODO(maruel): That's bad, it confuses property change. status = status.strip() @@ -137,7 +138,8 @@ class Rietveld(object): if state['num_chunks']: diff = self.get_file_diff(issue, patchset, state['id']) else: - diff = None + raise patch.UnsupportedPatchFormat( + filename, 'File doesn\'t have a diff.') out.append(patch.FilePatchDiff(filename, diff, props)) else: # Line too long (N/80) @@ -188,6 +190,7 @@ class Rietveld(object): maxtries = 5 for retry in xrange(maxtries): try: + logging.debug('%s' % request_path) result = self.rpc_server.Send(request_path, **kwargs) # Sometimes GAE returns a HTTP 200 but with HTTP 500 as the content. How # nice. diff --git a/tests/patch_test.py b/tests/patch_test.py index bd8a4c71a1..b76c693d0d 100755 --- a/tests/patch_test.py +++ b/tests/patch_test.py @@ -192,6 +192,20 @@ class PatchTest(unittest.TestCase): except patch.UnsupportedPatchFormat: pass + def testFilePatchNoDiff(self): + try: + patch.FilePatchDiff('foo', '', []) + self.fail() + except patch.UnsupportedPatchFormat: + pass + + def testFilePatchNoneDiff(self): + try: + patch.FilePatchDiff('foo', None, []) + self.fail() + except patch.UnsupportedPatchFormat: + pass + def testFilePatchBadDiffName(self): try: patch.FilePatchDiff('foo', SVN_PATCH, [])