普通文本  |  130行  |  3.79 KB

#!/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.

"""Rolls swarming_client.

While it is currently hard coded for swarming_client/, it is potentially
modifiable to allow different dependencies. Works only with git checkout and git
dependencies.
"""

import optparse
import os
import re
import subprocess
import sys

SRC_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


def is_pristine(root, merge_base='origin/master'):
  """Returns True is a git checkout is pristine."""
  cmd = ['git', 'diff', '--ignore-submodules', merge_base]
  return not (
      subprocess.check_output(cmd, cwd=root).strip() or
      subprocess.check_output(cmd + ['--cached'], cwd=root).strip())


def roll(deps_dir, key, reviewer, bug):
  if not is_pristine(SRC_ROOT):
    print >> sys.stderr, 'Ensure %s is clean first.' % SRC_ROOT
    return 1

  full_dir = os.path.join(SRC_ROOT, deps_dir)
  head = subprocess.check_output(
      ['git', 'rev-parse', 'HEAD'], cwd=full_dir).strip()
  deps = os.path.join(SRC_ROOT, 'DEPS')
  with open(deps, 'rb') as f:
    deps_content = f.read()

  if not head in deps_content:
    print('Warning: %s is not checked out at the expected revision in DEPS' %
          deps_dir)
    # It happens if the user checked out a branch in the dependency by himself.
    # Fall back to reading the DEPS to figure out the original commit.
    for i in deps_content.splitlines():
      m = re.match(r'\s+"' + key + '": "([a-z0-9]{40})",', i)
      if m:
        head = m.group(1)
        break
    else:
      print >> sys.stderr, 'Expected to find commit %s for %s in DEPS' % (
          head, key)
      return 1

  print('Found old revision %s' % head)

  subprocess.check_call(['git', 'fetch', 'origin'], cwd=full_dir)
  master = subprocess.check_output(
      ['git', 'rev-parse', 'origin/master'], cwd=full_dir).strip()
  print('Found new revision %s' % master)

  if master == head:
    print('No revision to roll!')
    return 1

  commit_range = '%s..%s' % (head[:9], master[:9])
  logs = subprocess.check_output(
      ['git', 'log', commit_range, '--date=short', '--format=%ad %ae %s'],
      cwd=full_dir).strip()
  logs = logs.replace('@chromium.org', '')
  cmd = (
      'git log %s --date=short --format=\'%%ad %%ae %%s\' | '
      'sed \'s/@chromium\.org//\'') % commit_range

  msg = (
      'Roll %s/ to %s.\n'
      '\n'
      '$ %s\n'
      '%s\n\n'
      'R=%s\n'
      'BUG=%s') % (
          deps_dir,
          master,
          cmd,
          logs,
          reviewer,
          bug)

  print('Commit message:')
  print('\n'.join('    ' + i for i in msg.splitlines()))
  deps_content = deps_content.replace(head, master)
  with open(deps, 'wb') as f:
    f.write(deps_content)
  subprocess.check_call(['git', 'add', 'DEPS'], cwd=SRC_ROOT)
  subprocess.check_call(['git', 'commit', '-m', msg], cwd=SRC_ROOT)
  print('Run:')
  print('  git cl upl --send-mail')
  return 0


def main():
  parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
  parser.add_option(
      '-r', '--reviewer', default='',
      help='To specify multiple reviewers, use comma separated list, e.g. '
           '-r joe,jack,john. Defaults to @chromium.org')
  parser.add_option('-b', '--bug', default='')
  options, args = parser.parse_args()
  if args:
    parser.error('Unknown argument %s' % args)
  if not options.reviewer:
    parser.error('Pass a reviewer right away with -r/--reviewer')

  reviewers = options.reviewer.split(',')
  for i, r in enumerate(reviewers):
    if not '@' in r:
      reviewers[i] = r + '@chromium.org'

  return roll(
      'tools/swarming_client',
      'swarming_revision',
      ','.join(reviewers),
      options.bug)


if __name__ == '__main__':
  sys.exit(main())