123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #!/usr/bin/env python
- # Copyright 2014 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.
- """Upload a cherry pick CL to rietveld."""
- import md5
- import optparse
- import subprocess2
- import sys
- import auth
- from git_cl import Changelist
- from git_common import config, run
- from third_party.upload import EncodeMultipartFormData, GitVCS
- from rietveld import Rietveld
- def cherry_pick(target_branch, commit, auth_config):
- """Attempt to upload a cherry pick CL to rietveld.
- Args:
- target_branch: The branch to cherry pick onto.
- commit: The git hash of the commit to cherry pick.
- auth_config: auth.AuthConfig object with authentication configuration.
- """
- author = config('user.email')
- description = '%s\n\n(cherry picked from commit %s)\n' % (
- run('show', '--pretty=%B', '--quiet', commit), commit)
- parent = run('show', '--pretty=%P', '--quiet', commit)
- print 'Found parent revision:', parent
- class Options(object):
- def __init__(self):
- self.emulate_svn_auto_props = False
- content_type, payload = EncodeMultipartFormData([
- ('base', '%s@%s' % (Changelist().GetRemoteUrl(), target_branch)),
- ('cc', config('rietveld.cc')),
- ('content_upload', '1'),
- ('description', description),
- ('project', '%s@%s' % (config('rietveld.project'), target_branch)),
- ('subject', description.splitlines()[0]),
- ('user', author),
- ], [
- ('data', 'data.diff', GitVCS(Options()).PostProcessDiff(
- run('diff', parent, commit))),
- ])
- rietveld = Rietveld(config('rietveld.server'), auth_config, author)
- # pylint: disable=protected-access
- output = rietveld._send(
- '/upload',
- payload=payload,
- content_type=content_type,
- ).splitlines()
- # If successful, output will look like:
- # Issue created. URL: https://codereview.chromium.org/1234567890
- # 1
- # 10001 some/path/first.file
- # 10002 some/path/second.file
- # 10003 some/path/third.file
- if output[0].startswith('Issue created. URL: '):
- print output[0]
- issue = output[0].rsplit('/', 1)[-1]
- patchset = output[1]
- files = output[2:]
- for f in files:
- file_id, filename = f.split()
- mode = 'M'
- try:
- content = run('show', '%s:%s' % (parent, filename))
- except subprocess2.CalledProcessError:
- # File didn't exist in the parent revision.
- content = ''
- mode = 'A'
- content_type, payload = EncodeMultipartFormData([
- ('checksum', md5.md5(content).hexdigest()),
- ('filename', filename),
- ('is_current', 'False'),
- ('status', mode),
- ], [
- ('data', filename, content),
- ])
- # pylint: disable=protected-access
- print ' Uploading base file for %s:' % filename, rietveld._send(
- '/%s/upload_content/%s/%s' % (issue, patchset, file_id),
- payload=payload,
- content_type=content_type,
- )
- try:
- content = run('show', '%s:%s' % (commit, filename))
- except subprocess2.CalledProcessError:
- # File no longer exists in the new commit.
- content = ''
- mode = 'D'
- content_type, payload = EncodeMultipartFormData([
- ('checksum', md5.md5(content).hexdigest()),
- ('filename', filename),
- ('is_current', 'True'),
- ('status', mode),
- ], [
- ('data', filename, content),
- ])
- # pylint: disable=protected-access
- print ' Uploading %s:' % filename, rietveld._send(
- '/%s/upload_content/%s/%s' % (issue, patchset, file_id),
- payload=payload,
- content_type=content_type,
- )
- # pylint: disable=protected-access
- print 'Finalizing upload:', rietveld._send('/%s/upload_complete/1' % issue)
- def main():
- parser = optparse.OptionParser(
- usage='usage: %prog --branch <branch> <commit>')
- parser.add_option(
- '--branch',
- '-b',
- help='The upstream branch to cherry pick to.',
- metavar='<branch>')
- auth.add_auth_options(parser)
- options, args = parser.parse_args()
- auth_config = auth.extract_auth_config_from_options
- if not options.branch:
- parser.error('--branch is required')
- if len(args) != 1:
- parser.error('Expecting single argument <commit>')
- cherry_pick(options.branch, args[0], auth_config)
- return 0
- if __name__ == '__main__':
- try:
- sys.exit(main())
- except KeyboardInterrupt:
- sys.stderr.write('interrupted\n')
- sys.exit(1)
|