#!/usr/bin/env python
# Copyright (c) 2012 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.

"""Client-side script to send a try job to the try server. It communicates to
the try server by either writting to a svn/git repository or by directly
connecting to the server by HTTP.
"""

import contextlib
import datetime
import errno
import getpass
import itertools
import json
import logging
import optparse
import os
import posixpath
import re
import shutil
import sys
import tempfile
import urllib
import urllib2
import urlparse

import breakpad  # pylint: disable=W0611

import fix_encoding
import gcl
import gclient_utils
import gerrit_util
import scm
import subprocess2


__version__ = '1.2'


# Constants
HELP_STRING = "Sorry, Tryserver is not available."
USAGE = r"""%prog [options]

Client-side script to send a try job to the try server. It communicates to
the try server by either writting to a svn repository or by directly connecting
to the server by HTTP."""

EPILOG = """
Examples:
  Send a patch directly from rietveld:
    %(prog)s -R codereview.chromium.org/1337
        --email recipient@example.com --root src

  Try a change against a particular revision:
    %(prog)s -r 123

  Try a change including changes to a sub repository:
    %(prog)s -s third_party/WebKit

  A git patch off a web site (git inserts a/ and b/) and fix the base dir:
    %(prog)s --url http://url/to/patch.diff --patchlevel 1 --root src

  Use svn to store the try job, specify an alternate email address and use a
  premade diff file on the local drive:
    %(prog)s --email user@example.com
            --svn_repo svn://svn.chromium.org/chrome-try/try --diff foo.diff

  Running only on a 'mac' slave with revision 123 and clobber first; specify
  manually the 3 source files to use for the try job:
    %(prog)s --bot mac --revision 123 --clobber -f src/a.cc -f src/a.h
            -f include/b.h
"""

GIT_PATCH_DIR_BASENAME = os.path.join('git-try', 'patches-git')
GIT_BRANCH_FILE = 'ref'
_GIT_PUSH_ATTEMPTS = 3

def DieWithError(message):
  print >> sys.stderr, message
  sys.exit(1)


def RunCommand(args, error_ok=False, error_message=None, **kwargs):
  try:
    return subprocess2.check_output(args, shell=False, **kwargs)
  except subprocess2.CalledProcessError, e:
    if not error_ok:
      DieWithError(
          'Command "%s" failed.\n%s' % (
            ' '.join(args), error_message or e.stdout or ''))
    return e.stdout


def RunGit(args, **kwargs):
  """Returns stdout."""
  return RunCommand(['git'] + args, **kwargs)

class Error(Exception):
  """An error during a try job submission.

  For this error, trychange.py does not display stack trace, only message
  """

class InvalidScript(Error):
  def __str__(self):
    return self.args[0] + '\n' + HELP_STRING


class NoTryServerAccess(Error):
  def __str__(self):
    return self.args[0] + '\n' + HELP_STRING

def Escape(name):
  """Escapes characters that could interfere with the file system or try job
  parsing.
  """
  return re.sub(r'[^\w#-]', '_', name)


class SCM(object):
  """Simplistic base class to implement one function: ProcessOptions."""
  def __init__(self, options, path, file_list):
    items = path.split('@')
    assert len(items) <= 2
    self.checkout_root = os.path.abspath(items[0])
    items.append(None)
    self.diff_against = items[1]
    self.options = options
    # Lazy-load file list from the SCM unless files were specified in options.
    self._files = None
    self._file_tuples = None
    if file_list:
      self._files = file_list
      self._file_tuples = [('M', f) for f in self.files]
    self.options.files = None
    self.codereview_settings = None
    self.codereview_settings_file = 'codereview.settings'
    self.toplevel_root = None

  def GetFileNames(self):
    """Return the list of files in the diff."""
    return self.files

  def GetCodeReviewSetting(self, key):
    """Returns a value for the given key for this repository.

    Uses gcl-style settings from the repository.
    """
    if gcl:
      gcl_setting = gcl.GetCodeReviewSetting(key)
      if gcl_setting != '':
        return gcl_setting
    if self.codereview_settings is None:
      self.codereview_settings = {}
      settings_file = self.ReadRootFile(self.codereview_settings_file)
      if settings_file:
        for line in settings_file.splitlines():
          if not line or line.lstrip().startswith('#'):
            continue
          k, v = line.split(":", 1)
          self.codereview_settings[k.strip()] = v.strip()
    return self.codereview_settings.get(key, '')

  def _GclStyleSettings(self):
    """Set default settings based on the gcl-style settings from the repository.

    The settings in the self.options object will only be set if no previous
    value exists (i.e. command line flags to the try command will override the
    settings in codereview.settings).
    """
    settings = {
      'port': self.GetCodeReviewSetting('TRYSERVER_HTTP_PORT'),
      'host': self.GetCodeReviewSetting('TRYSERVER_HTTP_HOST'),
      'svn_repo': self.GetCodeReviewSetting('TRYSERVER_SVN_URL'),
      'gerrit_url': self.GetCodeReviewSetting('TRYSERVER_GERRIT_URL'),
      'git_repo': self.GetCodeReviewSetting('TRYSERVER_GIT_URL'),
      'project': self.GetCodeReviewSetting('TRYSERVER_PROJECT'),
      # Primarily for revision=auto
      'revision': self.GetCodeReviewSetting('TRYSERVER_REVISION'),
      'root': self.GetCodeReviewSetting('TRYSERVER_ROOT'),
      'patchlevel': self.GetCodeReviewSetting('TRYSERVER_PATCHLEVEL'),
    }
    logging.info('\n'.join(['%s: %s' % (k, v)
                            for (k, v) in settings.iteritems() if v]))
    for (k, v) in settings.iteritems():
      # Avoid overwriting options already set using command line flags.
      if v and getattr(self.options, k) is None:
        setattr(self.options, k, v)

  def AutomagicalSettings(self):
    """Determines settings based on supported code review and checkout tools.
    """
    # Try to find gclient or repo root first.
    if not self.options.no_search:
      self.toplevel_root = gclient_utils.FindGclientRoot(self.checkout_root)
      if self.toplevel_root:
        logging.info('Found .gclient at %s' % self.toplevel_root)
      else:
        self.toplevel_root = gclient_utils.FindFileUpwards(
            os.path.join('..', '.repo'), self.checkout_root)
        if self.toplevel_root:
          logging.info('Found .repo dir at %s'
                       % os.path.dirname(self.toplevel_root))

      # Parse TRYSERVER_* settings from codereview.settings before falling back
      # on setting self.options.root manually further down. Otherwise
      # TRYSERVER_ROOT would never be used in codereview.settings.
      self._GclStyleSettings()

      if self.toplevel_root and not self.options.root:
        assert os.path.abspath(self.toplevel_root) == self.toplevel_root
        self.options.root = gclient_utils.PathDifference(self.toplevel_root,
                                                         self.checkout_root)
    else:
      self._GclStyleSettings()

  def ReadRootFile(self, filename):
    cur = self.checkout_root
    root = self.toplevel_root or self.checkout_root

    assert cur.startswith(root), (root, cur)
    while cur.startswith(root):
      filepath = os.path.join(cur, filename)
      if os.path.isfile(filepath):
        logging.info('Found %s at %s' % (filename, cur))
        return gclient_utils.FileRead(filepath)
      cur = os.path.dirname(cur)
    logging.warning('Didn\'t find %s' % filename)
    return None

  def _SetFileTuples(self, file_tuples):
    excluded = ['!', '?', 'X', ' ', '~']
    def Excluded(f):
      if f[0][0] in excluded:
        return True
      for r in self.options.exclude:
        if re.search(r, f[1]):
          logging.info('Ignoring "%s"' % f[1])
          return True
      return False

    self._file_tuples = [f for f in file_tuples if not Excluded(f)]
    self._files = [f[1] for f in self._file_tuples]

  def CaptureStatus(self):
    """Returns the 'svn status' emulated output as an array of (status, file)
       tuples."""
    raise NotImplementedError(
        "abstract method -- subclass %s must override" % self.__class__)

  @property
  def files(self):
    if self._files is None:
      self._SetFileTuples(self.CaptureStatus())
    return self._files

  @property
  def file_tuples(self):
    if self._file_tuples is None:
      self._SetFileTuples(self.CaptureStatus())
    return self._file_tuples


class SVN(SCM):
  """Gathers the options and diff for a subversion checkout."""
  def __init__(self, *args, **kwargs):
    SCM.__init__(self, *args, **kwargs)
    self.checkout_root = scm.SVN.GetCheckoutRoot(self.checkout_root)
    if not self.options.email:
      # Assumes the svn credential is an email address.
      self.options.email = scm.SVN.GetEmail(self.checkout_root)
    logging.info("SVN(%s)" % self.checkout_root)

  def ReadRootFile(self, filename):
    data = SCM.ReadRootFile(self, filename)
    if data:
      return data

    # Try to search on the subversion repository for the file.
    if not gcl:
      return None
    data = gcl.GetCachedFile(filename)
    logging.debug('%s:\n%s' % (filename, data))
    return data

  def CaptureStatus(self):
    return scm.SVN.CaptureStatus(None, self.checkout_root)

  def GenerateDiff(self):
    """Returns a string containing the diff for the given file list.

    The files in the list should either be absolute paths or relative to the
    given root.
    """
    return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True,
                                revision=self.diff_against)


class GIT(SCM):
  """Gathers the options and diff for a git checkout."""
  def __init__(self, *args, **kwargs):
    SCM.__init__(self, *args, **kwargs)
    self.checkout_root = scm.GIT.GetCheckoutRoot(self.checkout_root)
    if not self.options.name:
      self.options.name = scm.GIT.GetPatchName(self.checkout_root)
    if not self.options.email:
      self.options.email = scm.GIT.GetEmail(self.checkout_root)
    if not self.diff_against:
      self.diff_against = scm.GIT.GetUpstreamBranch(self.checkout_root)
      if not self.diff_against:
        raise NoTryServerAccess(
            "Unable to determine default branch to diff against. "
            "Verify this branch is set up to track another"
            "(via the --track argument to \"git checkout -b ...\"")
    logging.info("GIT(%s)" % self.checkout_root)

  def CaptureStatus(self):
    return scm.GIT.CaptureStatus(
        [],
        self.checkout_root.replace(os.sep, '/'),
        self.diff_against)

  def GenerateDiff(self):
    if RunGit(['diff-index', 'HEAD']):
      print 'Cannot try with a dirty tree.  You must commit locally first.'
      return None
    return scm.GIT.GenerateDiff(
        self.checkout_root,
        files=self.files,
        full_move=True,
        branch=self.diff_against)


def _ParseBotList(botlist, testfilter):
  """Parses bot configurations from a list of strings."""
  bots = []
  if testfilter:
    for bot in itertools.chain.from_iterable(botspec.split(',')
                                             for botspec in botlist):
      tests = set()
      if ':' in bot:
        if bot.endswith(':compile'):
          tests |= set(['compile'])
        else:
          raise ValueError(
              'Can\'t use both --testfilter and --bot builder:test formats '
              'at the same time')

      bots.append((bot, tests))
  else:
    for botspec in botlist:
      botname = botspec.split(':')[0]
      tests = set()
      if ':' in botspec:
        tests |= set(filter(None, botspec.split(':')[1].split(',')))
      bots.append((botname, tests))
  return bots


def _ApplyTestFilter(testfilter, bot_spec):
  """Applies testfilter from CLI.

  Specifying a testfilter strips off any builder-specified tests (except for
  compile).
  """
  if testfilter:
    return [(botname, set(testfilter) | (tests & set(['compile'])))
            for botname, tests in bot_spec]
  else:
    return bot_spec


def _GenTSBotSpec(checkouts, change, changed_files, options):
  bot_spec = []
  # Get try slaves from PRESUBMIT.py files if not specified.
  # Even if the diff comes from options.url, use the local checkout for bot
  # selection.
  try:
    import presubmit_support
    root_presubmit = checkouts[0].ReadRootFile('PRESUBMIT.py')
    if not change:
      if not changed_files:
        changed_files = checkouts[0].file_tuples
      change = presubmit_support.Change(options.name,
                                        '',
                                        checkouts[0].checkout_root,
                                        changed_files,
                                        options.issue,
                                        options.patchset,
                                        options.email)
    masters = presubmit_support.DoGetTryMasters(
        change,
        checkouts[0].GetFileNames(),
        checkouts[0].checkout_root,
        root_presubmit,
        options.project,
        options.verbose,
        sys.stdout)

    # Compatibility for old checkouts and bots that were on tryserver.chromium.
    trybots = masters.get('tryserver.chromium', [])

    # Compatibility for checkouts that are not using tryserver.chromium
    # but are stuck with git-try or gcl-try.
    if not trybots and len(masters) == 1:
      trybots = masters.values()[0]

    if trybots:
      old_style = filter(lambda x: isinstance(x, basestring), trybots)
      new_style = filter(lambda x: isinstance(x, tuple), trybots)

      # _ParseBotList's testfilter is set to None otherwise it will complain.
      bot_spec = _ApplyTestFilter(options.testfilter,
                                  _ParseBotList(old_style, None))

      bot_spec.extend(_ApplyTestFilter(options.testfilter, new_style))

  except ImportError:
    pass

  return bot_spec


def _ParseSendChangeOptions(bot_spec, options):
  """Parse common options passed to _SendChangeHTTP, _SendChangeSVN and
  _SendChangeGit.
  """
  values = [
      ('user', options.user),
      ('name', options.name),
  ]
  # A list of options to copy.
  optional_values = (
      'email',
      'revision',
      'root',
      'patchlevel',
      'issue',
      'patchset',
      'target',
      'project',
  )
  for option_name in optional_values:
    value = getattr(options, option_name)
    if value:
      values.append((option_name, value))

  # Not putting clobber to optional_names
  # because it used to have lower-case 'true'.
  if options.clobber:
    values.append(('clobber', 'true'))

  for bot, tests in bot_spec:
    values.append(('bot', ('%s:%s' % (bot, ','.join(tests)))))

  return values


def _SendChangeHTTP(bot_spec, options):
  """Send a change to the try server using the HTTP protocol."""
  if not options.host:
    raise NoTryServerAccess('Please use the --host option to specify the try '
        'server host to connect to.')
  if not options.port:
    raise NoTryServerAccess('Please use the --port option to specify the try '
        'server port to connect to.')

  values = _ParseSendChangeOptions(bot_spec, options)
  values.append(('patch', options.diff))

  url = 'http://%s:%s/send_try_patch' % (options.host, options.port)

  logging.info('Sending by HTTP')
  logging.info(''.join("%s=%s\n" % (k, v) for k, v in values))
  logging.info(url)
  logging.info(options.diff)
  if options.dry_run:
    return

  try:
    logging.info('Opening connection...')
    connection = urllib2.urlopen(url, urllib.urlencode(values))
    logging.info('Done')
  except IOError, e:
    logging.info(str(e))
    if bot_spec and len(e.args) > 2 and e.args[2] == 'got a bad status line':
      raise NoTryServerAccess('%s is unaccessible. Bad --bot argument?' % url)
    else:
      raise NoTryServerAccess('%s is unaccessible. Reason: %s' % (url,
                                                                  str(e.args)))
  if not connection:
    raise NoTryServerAccess('%s is unaccessible.' % url)
  logging.info('Reading response...')
  response = connection.read()
  logging.info('Done')
  if response != 'OK':
    raise NoTryServerAccess('%s is unaccessible. Got:\n%s' % (url, response))

  PrintSuccess(bot_spec, options)

@contextlib.contextmanager
def _TempFilename(name, contents=None):
  """Create a temporary directory, append the specified name and yield.

  In contrast to NamedTemporaryFile, does not keep the file open.
  Deletes the file on __exit__.
  """
  temp_dir = tempfile.mkdtemp(prefix=name)
  try:
    path = os.path.join(temp_dir, name)
    if contents is not None:
      with open(path, 'wb') as f:
        f.write(contents)
    yield path
  finally:
    shutil.rmtree(temp_dir, True)


@contextlib.contextmanager
def _PrepareDescriptionAndPatchFiles(description, options):
  """Creates temporary files with description and patch.

  __enter__ called on the return value returns a tuple of patch_filename and
  description_filename.

  Args:
    description: contents of description file.
    options: patchset options object. Must have attributes: user,
        name (of patch) and diff (contents of patch).
  """
  current_time = str(datetime.datetime.now()).replace(':', '.')
  patch_basename = '%s.%s.%s.diff' % (Escape(options.user),
                                      Escape(options.name), current_time)
  with _TempFilename('description', description) as description_filename:
    with _TempFilename(patch_basename, options.diff) as patch_filename:
      yield patch_filename, description_filename


def _SendChangeSVN(bot_spec, options):
  """Send a change to the try server by committing a diff file on a subversion
  server."""
  if not options.svn_repo:
    raise NoTryServerAccess('Please use the --svn_repo option to specify the'
                            ' try server svn repository to connect to.')

  values = _ParseSendChangeOptions(bot_spec, options)
  description = ''.join("%s=%s\n" % (k, v) for k, v in values)
  logging.info('Sending by SVN')
  logging.info(description)
  logging.info(options.svn_repo)
  logging.info(options.diff)
  if options.dry_run:
    return

  with _PrepareDescriptionAndPatchFiles(description, options) as (
       patch_filename, description_filename):
    if sys.platform == "cygwin":
      # Small chromium-specific issue here:
      # git-try uses /usr/bin/python on cygwin but svn.bat will be used
      # instead of /usr/bin/svn by default. That causes bad things(tm) since
      # Windows' svn.exe has no clue about cygwin paths. Hence force to use
      # the cygwin version in this particular context.
      exe = "/usr/bin/svn"
    else:
      exe = "svn"
    patch_dir = os.path.dirname(patch_filename)
    command = [exe, 'import', '-q', patch_dir, options.svn_repo, '--file',
               description_filename]
    if scm.SVN.AssertVersion("1.5")[0]:
      command.append('--no-ignore')

    try:
      subprocess2.check_call(command)
    except subprocess2.CalledProcessError, e:
      raise NoTryServerAccess(str(e))

  PrintSuccess(bot_spec, options)

def _GetPatchGitRepo(git_url):
  """Gets a path to a Git repo with patches.

  Stores patches in .git/git-try/patches-git directory, a git repo. If it
  doesn't exist yet or its origin URL is different, cleans up and clones it.
  If it existed before, then pulls changes.

  Does not support SVN repo.

  Returns a path to the directory with patches.
  """
  git_dir = scm.GIT.GetGitDir(os.getcwd())
  patch_dir = os.path.join(git_dir, GIT_PATCH_DIR_BASENAME)

  logging.info('Looking for git repo for patches')
  # Is there already a repo with the expected url or should we clone?
  clone = True
  if os.path.exists(patch_dir) and scm.GIT.IsInsideWorkTree(patch_dir):
    existing_url = scm.GIT.Capture(
        ['config', '--local', 'remote.origin.url'],
        cwd=patch_dir)
    clone = existing_url != git_url

  if clone:
    if os.path.exists(patch_dir):
      logging.info('Cleaning up')
      shutil.rmtree(patch_dir, True)
    logging.info('Cloning patch repo')
    scm.GIT.Capture(['clone', git_url, GIT_PATCH_DIR_BASENAME], cwd=git_dir)
    email = scm.GIT.GetEmail(cwd=os.getcwd())
    scm.GIT.Capture(['config', '--local', 'user.email', email], cwd=patch_dir)
  else:
    if scm.GIT.IsWorkTreeDirty(patch_dir):
      logging.info('Work dir is dirty: hard reset!')
      scm.GIT.Capture(['reset', '--hard'], cwd=patch_dir)
    logging.info('Updating patch repo')
    scm.GIT.Capture(['pull', 'origin', 'master'], cwd=patch_dir)

  return os.path.abspath(patch_dir)


def _SendChangeGit(bot_spec, options):
  """Sends a change to the try server by committing a diff file to a GIT repo.

  Creates a temp orphan branch, commits patch.diff, creates a ref pointing to
  that commit, deletes the temp branch, checks master out, adds 'ref' file
  containing the name of the new ref, pushes master and the ref to the origin.

  TODO: instead of creating a temp branch, use git-commit-tree.
  """

  if not options.git_repo:
    raise NoTryServerAccess('Please use the --git_repo option to specify the '
                            'try server git repository to connect to.')

  values = _ParseSendChangeOptions(bot_spec, options)
  comment_subject = '%s.%s' % (options.user, options.name)
  comment_body = ''.join("%s=%s\n" % (k, v) for k, v in values)
  description = '%s\n\n%s' % (comment_subject, comment_body)
  logging.info('Sending by GIT')
  logging.info(description)
  logging.info(options.git_repo)
  logging.info(options.diff)
  if options.dry_run:
    return

  patch_dir = _GetPatchGitRepo(options.git_repo)
  def patch_git(*args):
    return scm.GIT.Capture(list(args), cwd=patch_dir)
  def add_and_commit(filename, comment_filename):
    patch_git('add', filename)
    patch_git('commit', '-F', comment_filename)

  assert scm.GIT.IsInsideWorkTree(patch_dir)
  assert not scm.GIT.IsWorkTreeDirty(patch_dir)

  with _PrepareDescriptionAndPatchFiles(description, options) as (
       patch_filename, description_filename):
    logging.info('Committing patch')

    temp_branch = 'tmp_patch'
    target_ref = 'refs/patches/%s/%s' % (
        Escape(options.user),
        os.path.basename(patch_filename).replace(' ','_'))
    target_filename = os.path.join(patch_dir, 'patch.diff')
    branch_file = os.path.join(patch_dir, GIT_BRANCH_FILE)

    patch_git('checkout', 'master')
    try:
      # Try deleting an existing temp branch, if any.
      try:
        patch_git('branch', '-D', temp_branch)
        logging.debug('Deleted an existing temp branch.')
      except subprocess2.CalledProcessError:
        pass
      # Create a new branch and put the patch there.
      patch_git('checkout', '--orphan', temp_branch)
      patch_git('reset')
      patch_git('clean', '-f')
      shutil.copyfile(patch_filename, target_filename)
      add_and_commit(target_filename, description_filename)
      assert not scm.GIT.IsWorkTreeDirty(patch_dir)

      # Create a ref and point it to the commit referenced by temp_branch.
      patch_git('update-ref', target_ref, temp_branch)

      # Delete the temp ref.
      patch_git('checkout', 'master')
      patch_git('branch', '-D', temp_branch)

      # Update the branch file in the master.
      def update_branch():
        with open(branch_file, 'w') as f:
          f.write(target_ref)
        add_and_commit(branch_file, description_filename)

      update_branch()

      # Push master and target_ref to origin.
      logging.info('Pushing patch')
      for attempt in xrange(_GIT_PUSH_ATTEMPTS):
        try:
          patch_git('push', 'origin', 'master', target_ref)
        except subprocess2.CalledProcessError as e:
          is_last = attempt == _GIT_PUSH_ATTEMPTS - 1
          if is_last:
            raise NoTryServerAccess(str(e))
          # Fetch, reset, update branch file again.
          patch_git('fetch', 'origin')
          patch_git('reset', '--hard', 'origin/master')
          update_branch()
    except subprocess2.CalledProcessError, e:
      # Restore state.
      patch_git('checkout', 'master')
      patch_git('reset', '--hard', 'origin/master')
      raise

  PrintSuccess(bot_spec, options)

def _SendChangeGerrit(bot_spec, options):
  """Posts a try job to a Gerrit change.

  Reads Change-Id from the HEAD commit, resolves the current revision, checks
  that local revision matches the uploaded one, posts a try job in form of a
  message, sets Tryjob-Request label to 1.

  Gerrit message format: starts with !tryjob, optionally followed by a tryjob
  definition in JSON format:
      buildNames: list of strings specifying build names.
  """

  logging.info('Sending by Gerrit')
  if not options.gerrit_url:
    raise NoTryServerAccess('Please use --gerrit_url option to specify the '
                            'Gerrit instance url to connect to')
  gerrit_host = urlparse.urlparse(options.gerrit_url).hostname
  logging.debug('Gerrit host: %s' % gerrit_host)

  def GetChangeId(commmitish):
    """Finds Change-ID of the HEAD commit."""
    CHANGE_ID_RGX = '^Change-Id: (I[a-f0-9]{10,})'
    comment = scm.GIT.Capture(['log', '-1', commmitish, '--format=%b'],
                              cwd=os.getcwd())
    change_id_match = re.search(CHANGE_ID_RGX, comment, re.I | re.M)
    if not change_id_match:
      raise Error('Change-Id was not found in the HEAD commit. Make sure you '
                  'have a Git hook installed that generates and inserts a '
                  'Change-Id into a commit message automatically.')
    change_id = change_id_match.group(1)
    return change_id

  def FormatMessage():
    # Build job definition.
    job_def = {}
    builderNames = [builder for builder, _ in bot_spec]
    if builderNames:
      job_def['builderNames'] = builderNames

    # Format message.
    msg = '!tryjob'
    if job_def:
      msg = '%s %s' % (msg, json.dumps(job_def, sort_keys=True))
    return msg

  def PostTryjob(message):
    logging.info('Posting gerrit message: %s' % message)
    if not options.dry_run:
      # Post a message and set TryJob=1 label.
      try:
        gerrit_util.SetReview(gerrit_host, change_id, msg=message,
                              labels={'Tryjob-Request': 1})
      except gerrit_util.GerritError, e:
        if e.http_status == 400:
          raise Error(e.reason)
        else:
          raise

  head_sha = scm.GIT.Capture(['log', '-1', '--format=%H'], cwd=os.getcwd())

  change_id = GetChangeId(head_sha)

  try:
    # Check that the uploaded revision matches the local one.
    changes = gerrit_util.GetChangeCurrentRevision(gerrit_host, change_id)
  except gerrit_util.GerritAuthenticationError, e:
    raise NoTryServerAccess(e.message)

  assert len(changes) <= 1, 'Multiple changes with id %s' % change_id
  if not changes:
    raise Error('A change %s was not found on the server. Was it uploaded?' %
                change_id)
  logging.debug('Found Gerrit change: %s' % changes[0])
  if changes[0]['current_revision'] != head_sha:
    raise Error('Please upload your latest local changes to Gerrit.')

  # Post a try job.
  message = FormatMessage()
  PostTryjob(message)
  change_url = urlparse.urljoin(options.gerrit_url,
                                '/#/c/%s' % changes[0]['_number'])
  print('A tryjob was posted on change %s' % change_url)

def PrintSuccess(bot_spec, options):
  if not options.dry_run:
    text = 'Patch \'%s\' sent to try server' % options.name
    if bot_spec:
      text += ': %s' % ', '.join(
          '%s:%s' % (b[0], ','.join(b[1])) for b in bot_spec)
    print(text)


def GuessVCS(options, path, file_list):
  """Helper to guess the version control system.

  NOTE: Very similar to upload.GuessVCS. Doesn't look for hg since we don't
  support it yet.

  This examines the path directory, guesses which SCM we're using, and
  returns an instance of the appropriate class.  Exit with an error if we can't
  figure it out.

  Returns:
    A SCM instance. Exits if the SCM can't be guessed.
  """
  __pychecker__ = 'no-returnvalues'
  real_path = path.split('@')[0]
  logging.info("GuessVCS(%s)" % path)
  # Subversion has a .svn in all working directories.
  if os.path.isdir(os.path.join(real_path, '.svn')):
    return SVN(options, path, file_list)

  # Git has a command to test if you're in a git tree.
  # Try running it, but don't die if we don't have git installed.
  try:
    subprocess2.check_output(
        ['git', 'rev-parse', '--is-inside-work-tree'], cwd=real_path,
        stderr=subprocess2.VOID)
    return GIT(options, path, file_list)
  except OSError, e:
    if e.errno != errno.ENOENT:
      raise
  except subprocess2.CalledProcessError, e:
    if e.returncode != errno.ENOENT and e.returncode != 128:
      # ENOENT == 2 = they don't have git installed.
      # 128 = git error code when not in a repo.
      logging.warning('Unexpected error code: %s' % e.returncode)
      raise
  raise NoTryServerAccess(
      ( 'Could not guess version control system for %s.\n'
        'Are you in a working copy directory?') % path)


def GetMungedDiff(path_diff, diff):
  # Munge paths to match svn.
  changed_files = []
  for i in range(len(diff)):
    if diff[i].startswith('--- ') or diff[i].startswith('+++ '):
      new_file = posixpath.join(path_diff, diff[i][4:]).replace('\\', '/')
      if diff[i].startswith('--- '):
        file_path = new_file.split('\t')[0].strip()
        if file_path.startswith('a/'):
          file_path = file_path[2:]
        changed_files.append(('M', file_path))
      diff[i] = diff[i][0:4] + new_file
  return (diff, changed_files)


class OptionParser(optparse.OptionParser):
  def format_epilog(self, _):
    """Removes epilog formatting."""
    return self.epilog or ''


def gen_parser(prog):
  # Parse argv
  parser = OptionParser(usage=USAGE, version=__version__, prog=prog)
  parser.add_option("-v", "--verbose", action="count", default=0,
                    help="Prints debugging infos")
  group = optparse.OptionGroup(parser, "Result and status")
  group.add_option("-u", "--user", default=getpass.getuser(),
                   help="Owner user name [default: %default]")
  group.add_option("-e", "--email",
                   default=os.environ.get('TRYBOT_RESULTS_EMAIL_ADDRESS',
                        os.environ.get('EMAIL_ADDRESS')),
                   help="Email address where to send the results. Use either "
                        "the TRYBOT_RESULTS_EMAIL_ADDRESS environment "
                        "variable or EMAIL_ADDRESS to set the email address "
                        "the try bots report results to [default: %default]")
  group.add_option("-n", "--name",
                   help="Descriptive name of the try job")
  group.add_option("--issue", type='int',
                   help="Update rietveld issue try job status")
  group.add_option("--patchset", type='int',
                   help="Update rietveld issue try job status. This is "
                        "optional if --issue is used, In that case, the "
                        "latest patchset will be used.")
  group.add_option("--dry_run", action='store_true',
                   help="Don't send the try job. This implies --verbose, so "
                        "it will print the diff.")
  parser.add_option_group(group)

  group = optparse.OptionGroup(parser, "Try job options")
  group.add_option(
      "-b", "--bot", action="append",
      help=("IMPORTANT: specify ONE builder per --bot flag. Use it multiple "
            "times to specify multiple builders. ex: "
            "'-bwin_rel:ui_tests,webkit_unit_tests -bwin_layout'. See "
            "the try server waterfall for the builders name and the tests "
            "available. Can also be used to specify gtest_filter, e.g. "
            "-bwin_rel:base_unittests:ValuesTest.*Value"))
  group.add_option("-B", "--print_bots", action="store_true",
                    help="Print bots we would use (e.g. from PRESUBMIT.py)"
                         " and exit.  Do not send patch.  Like --dry_run"
                         " but less verbose.")
  group.add_option("-r", "--revision",
                    help="Revision to use for the try job. If 'auto' is "
                         "specified, it is resolved to the revision a patch is "
                         "generated against (Git only). Default: the "
                         "revision will be determined by the try server; see "
                         "its waterfall for more info")
  group.add_option("-c", "--clobber", action="store_true",
                    help="Force a clobber before building; e.g. don't do an "
                         "incremental build")
  # TODO(maruel): help="Select a specific configuration, usually 'debug' or "
  #                    "'release'"
  group.add_option("--target", help=optparse.SUPPRESS_HELP)

  group.add_option("--project",
                   help="Override which project to use. Projects are defined "
                        "server-side to define what default bot set to use")

  group.add_option(
      "-t", "--testfilter", action="append", default=[],
      help=("Apply a testfilter to all the selected builders. Unless the "
            "builders configurations are similar, use multiple "
            "--bot <builder>:<test> arguments."))

  parser.add_option_group(group)

  group = optparse.OptionGroup(parser, "Patch to run")
  group.add_option("-f", "--file", default=[], dest="files",
                   metavar="FILE", action="append",
                   help="Use many times to list the files to include in the "
                        "try, relative to the repository root")
  group.add_option("--diff",
                   help="File containing the diff to try")
  group.add_option("--url",
                   help="Url where to grab a patch, e.g. "
                        "http://example.com/x.diff")
  group.add_option("-R", "--rietveld_url", default="codereview.appspot.com",
                   metavar="URL",
                   help="Has 2 usages, both refer to the rietveld instance: "
                        "Specify which code review patch to use as the try job "
                        "or rietveld instance to update the try job results "
                        "Default:%default")
  group.add_option("--root",
                   help="Root to use for the patch; base subdirectory for "
                        "patch created in a subdirectory")
  group.add_option("-p", "--patchlevel", type='int', metavar="LEVEL",
                   help="Used as -pN parameter to patch")
  group.add_option("-s", "--sub_rep", action="append", default=[],
                   help="Subcheckout to use in addition. This is mainly "
                        "useful for gclient-style checkouts. In git, checkout "
                        "the branch with changes first. Use @rev or "
                        "@branch to specify the "
                        "revision/branch to diff against. If no @branch is "
                        "given the diff will be against the upstream branch. "
                        "If @branch then the diff is branch..HEAD. "
                        "All edits must be checked in.")
  group.add_option("--no_search", action="store_true",
                   help=("Disable automatic search for gclient or repo "
                        "checkout root."))
  group.add_option("-E", "--exclude", action="append",
                   default=['ChangeLog'], metavar='REGEXP',
                   help="Regexp patterns to exclude files. Default: %default")
  group.add_option("--upstream_branch", action="store",
                   help="Specify the upstream branch to diff against in the "
                        "main checkout")
  parser.add_option_group(group)

  group = optparse.OptionGroup(parser, "Access the try server by HTTP")
  group.add_option("--use_http",
                   action="store_const",
                   const=_SendChangeHTTP,
                   dest="send_patch",
                   help="Use HTTP to talk to the try server [default]")
  group.add_option("-H", "--host",
                   help="Host address")
  group.add_option("-P", "--port", type="int",
                   help="HTTP port")
  parser.add_option_group(group)

  group = optparse.OptionGroup(parser, "Access the try server with SVN")
  group.add_option("--use_svn",
                   action="store_const",
                   const=_SendChangeSVN,
                   dest="send_patch",
                   help="Use SVN to talk to the try server")
  group.add_option("-S", "--svn_repo",
                   metavar="SVN_URL",
                   help="SVN url to use to write the changes in; --use_svn is "
                        "implied when using --svn_repo")
  parser.add_option_group(group)

  group = optparse.OptionGroup(parser, "Access the try server with Git")
  group.add_option("--use_git",
                   action="store_const",
                   const=_SendChangeGit,
                   dest="send_patch",
                   help="Use GIT to talk to the try server")
  group.add_option("-G", "--git_repo",
                   metavar="GIT_URL",
                   help="GIT url to use to write the changes in; --use_git is "
                        "implied when using --git_repo")
  parser.add_option_group(group)

  group = optparse.OptionGroup(parser, "Access the try server with Gerrit")
  group.add_option("--use_gerrit",
                   action="store_const",
                   const=_SendChangeGerrit,
                   dest="send_patch",
                   help="Use Gerrit to talk to the try server")
  group.add_option("--gerrit_url",
                   metavar="GERRIT_URL",
                   help="Gerrit url to post a tryjob to; --use_gerrit is "
                        "implied when using --gerrit_url")
  parser.add_option_group(group)

  return parser


def TryChange(argv,
              change,
              swallow_exception,
              prog=None,
              extra_epilog=None):
  """
  Args:
    argv: Arguments and options.
    change: Change instance corresponding to the CL.
    swallow_exception: Whether we raise or swallow exceptions.
  """
  parser = gen_parser(prog)
  epilog = EPILOG % { 'prog': prog }
  if extra_epilog:
    epilog += extra_epilog
  parser.epilog = epilog

  options, args = parser.parse_args(argv)

  # If they've asked for help, give it to them
  if len(args) == 1 and args[0] == 'help':
    parser.print_help()
    return 0

  # If they've said something confusing, don't spawn a try job until you
  # understand what they want.
  if args:
    parser.error('Extra argument(s) "%s" not understood' % ' '.join(args))

  if options.dry_run:
    options.verbose += 1

  LOG_FORMAT = '%(levelname)s %(filename)s(%(lineno)d): %(message)s'
  if not swallow_exception:
    if options.verbose == 0:
      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)

  logging.debug(argv)

  if (options.patchlevel is not None and
      (options.patchlevel < 0 or options.patchlevel > 10)):
    parser.error(
        'Have you tried --port instead? You probably confused -p and -P.')

  # Strip off any @ in the user, otherwise svn gets confused.
  options.user = options.user.split('@', 1)[0]

  if options.rietveld_url:
    # Try to extract the review number if possible and fix the protocol.
    if not '://' in options.rietveld_url:
      options.rietveld_url = 'http://' + options.rietveld_url
    match = re.match(r'^(.*)/(\d+)/?$', options.rietveld_url)
    if match:
      if options.issue or options.patchset:
        parser.error('Cannot use both --issue and use a review number url')
      options.issue = int(match.group(2))
      options.rietveld_url = match.group(1)

  try:
    changed_files = None
    # Always include os.getcwd() in the checkout settings.
    path = os.getcwd()

    file_list = []
    if options.files:
      file_list = options.files
    elif change:
      file_list = [f.LocalPath() for f in change.AffectedFiles()]

    if options.upstream_branch:
      path += '@' + options.upstream_branch
      # Clear file list so that the correct list will be retrieved from the
      # upstream branch.
      file_list = []

    current_vcs = GuessVCS(options, path, file_list)
    current_vcs.AutomagicalSettings()
    options = current_vcs.options
    vcs_is_git = type(current_vcs) is GIT

    # So far, git_repo doesn't work with SVN
    if options.git_repo and not vcs_is_git:
      parser.error('--git_repo option is supported only for GIT repositories')

    # If revision==auto, resolve it
    if options.revision and options.revision.lower() == 'auto':
      if not vcs_is_git:
        parser.error('--revision=auto is supported only for GIT repositories')
      options.revision = scm.GIT.Capture(
          ['rev-parse', current_vcs.diff_against],
          cwd=path)

    checkouts = [current_vcs]
    for item in options.sub_rep:
      # Pass file_list=None because we don't know the sub repo's file list.
      checkout = GuessVCS(options,
                          os.path.join(current_vcs.checkout_root, item),
                          None)
      if checkout.checkout_root in [c.checkout_root for c in checkouts]:
        parser.error('Specified the root %s two times.' %
                     checkout.checkout_root)
      checkouts.append(checkout)

    can_http = options.port and options.host
    can_svn = options.svn_repo
    can_git = options.git_repo
    can_gerrit = options.gerrit_url
    can_something = can_http or can_svn or can_git or can_gerrit
    # If there was no transport selected yet, now we must have enough data to
    # select one.
    if not options.send_patch and not can_something:
      parser.error('Please specify an access method.')

    # Convert options.diff into the content of the diff.
    if options.url:
      if options.files:
        parser.error('You cannot specify files and --url at the same time.')
      options.diff = urllib2.urlopen(options.url).read()
    elif options.diff:
      if options.files:
        parser.error('You cannot specify files and --diff at the same time.')
      options.diff = gclient_utils.FileRead(options.diff, 'rb')
    elif options.issue and options.patchset is None:
      # Retrieve the patch from rietveld when the diff is not specified.
      # When patchset is specified, it's because it's done by gcl/git-try.
      api_url = '%s/api/%d' % (options.rietveld_url, options.issue)
      logging.debug(api_url)
      contents = json.loads(urllib2.urlopen(api_url).read())
      options.patchset = contents['patchsets'][-1]
      diff_url = ('%s/download/issue%d_%d.diff' %
          (options.rietveld_url,  options.issue, options.patchset))
      diff = GetMungedDiff('', urllib2.urlopen(diff_url).readlines())
      options.diff = ''.join(diff[0])
      changed_files = diff[1]
    else:
      # Use this as the base.
      root = checkouts[0].checkout_root
      diffs = []
      for checkout in checkouts:
        raw_diff = checkout.GenerateDiff()
        if not raw_diff:
          continue
        diff = raw_diff.splitlines(True)
        path_diff = gclient_utils.PathDifference(root, checkout.checkout_root)
        # Munge it.
        diffs.extend(GetMungedDiff(path_diff, diff)[0])
      if not diffs:
        logging.error('Empty or non-existant diff, exiting.')
        return 1
      options.diff = ''.join(diffs)

    if not options.name:
      if options.issue:
        options.name = 'Issue %s' % options.issue
      else:
        options.name = 'Unnamed'
        print('Note: use --name NAME to change the try job name.')

    if not options.email:
      parser.error('Using an anonymous checkout. Please use --email or set '
                   'the TRYBOT_RESULTS_EMAIL_ADDRESS environment variable.')
    print('Results will be emailed to: ' + options.email)

    if options.bot:
      bot_spec = _ApplyTestFilter(
          options.testfilter, _ParseBotList(options.bot, options.testfilter))
    else:
      bot_spec = _GenTSBotSpec(checkouts, change, changed_files, options)

    if options.testfilter:
      bot_spec = _ApplyTestFilter(options.testfilter, bot_spec)

    if any('triggered' in b[0] for b in bot_spec):
      print >> sys.stderr, (
          'ERROR You are trying to send a job to a triggered bot.  This type of'
          ' bot requires an\ninitial job from a parent (usually a builder).  '
          'Instead send your job to the parent.\nBot list: %s' % bot_spec)
      return 1

    if options.print_bots:
      print 'Bots which would be used:'
      for bot in bot_spec:
        if bot[1]:
          print '  %s:%s' % (bot[0], ','.join(bot[1]))
        else:
          print '  %s' % (bot[0])
      return 0

    # Determine sending protocol
    if options.send_patch:
      # If forced.
      senders = [options.send_patch]
    else:
      # Try sending patch using avaialble protocols
      all_senders = [
        (_SendChangeHTTP, can_http),
        (_SendChangeSVN, can_svn),
        (_SendChangeGerrit, can_gerrit),
        (_SendChangeGit, can_git),
      ]
      senders = [sender for sender, can in all_senders if can]

    # Send the patch.
    for sender in senders:
      try:
        sender(bot_spec, options)
        return 0
      except NoTryServerAccess:
        is_last = sender == senders[-1]
        if is_last:
          raise
    assert False, "Unreachable code"
  except Error, e:
    if swallow_exception:
      return 1
    print >> sys.stderr, e
    return 1
  except (gclient_utils.Error, subprocess2.CalledProcessError), e:
    print >> sys.stderr, e
    return 1
  return 0


if __name__ == "__main__":
  fix_encoding.fix_encoding()
  sys.exit(TryChange(None, None, False))
