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.4 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.4 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=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)
 |