You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
4.3 KiB
Python
156 lines
4.3 KiB
Python
#!/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=W0212
|
|
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=W0212
|
|
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=W0212
|
|
print ' Uploading %s:' % filename, rietveld._send(
|
|
'/%s/upload_content/%s/%s' % (issue, patchset, file_id),
|
|
payload=payload,
|
|
content_type=content_type,
|
|
)
|
|
|
|
# pylint: disable=W0212
|
|
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)
|