# Copyright (c) 2011-2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Module that handles interactions with a Validation Pool.

The validation pool is the set of commits that are ready to be validated i.e.
ready for the commit queue to try.
"""

import json
import logging
import time
import urllib
from xml.dom import minidom

from chromite.buildbot import constants
from chromite.buildbot import gerrit_helper
from chromite.buildbot import lkgm_manager
from chromite.buildbot import patch as cros_patch
from chromite.lib import cros_build_lib

_BUILD_DASHBOARD = 'http://build.chromium.org/p/chromiumos'
_BUILD_INT_DASHBOARD = 'http://uberchromegw.corp.google.com/i/chromeos'


def _RunCommand(cmd, dryrun):
  """Runs the specified shell cmd if dryrun=False."""
  if dryrun:
    logging.info('Would have run: %s', ' '.join(cmd))
  else:
    cros_build_lib.RunCommand(cmd, error_ok=True)


class TreeIsClosedException(Exception):
  """Raised when the tree is closed and we wanted to submit changes."""
  def __init__(self):
    super(TreeIsClosedException, self).__init__(
        'TREE IS CLOSED.  PLEASE SET TO OPEN OR THROTTLED TO COMMIT')


class FailedToSubmitAllChangesException(Exception):
  """Raised if we fail to submit any changes."""
  def __init__(self, changes):
    super(FailedToSubmitAllChangesException, self).__init__(
        'FAILED TO SUBMIT ALL CHANGES:  Could not verify that changes %s were '
        'submitted' % ' '.join(str(c) for c in changes))


class NoMatchingChangeFoundException(Exception):
  """Raised if we try to apply a non-existent change."""
  pass


def MarkChangeFailedInflight(change):
  """Set an appropriate error message for an inflight apply failure."""
  change.apply_error_message = (
      'Your change conflicted with another change being tested '
      'in the last validation pool.  Please re-sync, rebase and '
      're-upload.')
  return change


def MarkChangeFailedToT(change):
  """Set an appropriate error message for a ToT apply failure."""
  change.apply_error_message = (
      'Your change no longer cleanly applies against ToT.  '
      'Please re-sync, rebase, and re-upload your change.')
  return change


class HelperPool(object):
  """Pool of allowed GerritHelpers to be used by CQ/PatchSeries."""

  def __init__(self, internal=None, external=None):
    """Initialize this instance with the given handlers.

    Most likely you want the classmethod SimpleCreate which takes boolean
    options.

    If a given handler is None, then it's disabled; else the passed in
    object is used.

    """
    self._external = external
    self._internal = internal

  @classmethod
  def SimpleCreate(cls, internal=True, external=True):
    """Classmethod helper for creating a HelperPool from boolean options.

    Args:
      internal: If True, allow access to a GerritHelper for internal.
      external: If True, allow access to a GerritHelper for external.
    Returns:
      An appropriately configured HelperPool instance.
    """
    external = gerrit_helper.GerritHelper(internal=False) if external else None
    internal = gerrit_helper.GerritHelper(internal=True) if internal else None
    return cls(internal=internal, external=external)

  def ForChange(self, change):
    """Return the helper to use for a particular change.

    If no helper is configured, an Exception is raised.
    """
    if change.internal:
      if self._internal:
        return self._internal
    elif self._external:
      return self._external

    raise AssertionError(
        'Asked for an internal=%r helper, but none are allowed in this '
        'configuration.  This strongly points at the possibility of an '
        'internal bug.'
        % (change.internal,))

  def __iter__(self):
    for helper in (self._external, self._internal):
      if helper:
        yield helper


class PatchSeries(object):

  """Class representing a set of patches applied to a repository."""

  def __init__(self, helper_pool=None):
    self._content_merging = {}
    if helper_pool is None:
      helper_pool = HelperPool.SimpleCreate(internal=True, external=True)
    self._helper_pool = helper_pool

  def IsContentMerging(self, change, manifest):
    """Discern if the given change has Content Merging enabled in gerrit.

    Raises:
      AssertionError: If the gerrit helper requested is disallowed.
      GerritException: If there is a failure in querying gerrit.
    Returns:
      True if the change's project has content merging enabled, False if not.
    """
    helper = self._helper_pool.ForChange(change)

    if not helper.version.startswith('2.1'):
      return manifest.ProjectIsContentMerging(change.project)

    # Fallback to doing gsql trickery to get it; note this requires admin
    # access.
    projects = self._content_merging.get(helper)
    if projects is None:
      projects = helper.FindContentMergingProjects()
      self._content_merging[helper] = projects

    return change.project in projects

  def Apply(self, buildroot, changes, dryrun=False):
    """Applies changes from pool into the directory specified by the buildroot.

    This method applies changes in the order specified.  It also respects
    dependency order.

    Returns:
      A tuple of changes-applied, changes that failed against tot, and
      changes that failed inflight.
    """
    # Sets are used for performance reasons where changes_list is used to
    # maintain ordering when applying changes.
    changes_that_failed_to_apply_against_other_changes = set()
    changes_that_failed_to_apply_to_tot = set()
    changes_applied = set()
    changes_list = []

    # Used by content merging checks when we're operating against
    # >=gerrit-2.2.
    manifest = cros_build_lib.ManifestCheckout.Cached(buildroot)

    # Maps Change numbers to GerritPatch object for lookup of dependent
    # changes.
    change_map = dict((change.id, change) for change in changes)
    for change in changes:
      logging.debug('Trying change %s', change.id)
      helper = self._helper_pool.ForChange(change)
      # We've already attempted this change because it was a dependent change
      # of another change that was ready.
      if (change in changes_that_failed_to_apply_to_tot or
          change in changes_applied):
        continue

      # Change stacks consists of the change plus its dependencies in the order
      # that they should be applied.
      change_stack = [change]
      apply_chain = True
      deps = []

      dependency_exc = None

      # TODO(sosa): Modify helper logic to allows deps to be specified across
      # different gerrit instances.
      try:
        deps.extend(change.GerritDependencies(buildroot))
        deps.extend(change.PaladinDependencies(buildroot))
      except cros_patch.MissingChangeIDException as dependency_exc:
        change.apply_error_message = (
            'Could not apply change %s because change has a Gerrit Dependency '
            'that does not contain a ChangeId.  Please remove this dependency '
            'or update the dependency with a ChangeId.' % change.id)
      except cros_patch.BrokenCQDepends as dependency_exc:
        change.apply_error_message = (
            'Could not apply change %s because change has a malformed '
            'CQ-DEPEND. CQ-DEPEND must either be the long form Change-ID, '
            'or the change number.' % change.id)
      except cros_patch.BrokenChangeID as dependency_exc:
        change.apply_error_message = (
            'Could not apply change %s because a parent change has a malformed '
            'Change-ID.  Please fix and retry.' % change.id)

      if dependency_exc:
        logging.error(change.apply_error_message)
        logging.error(str(dependency_exc))
        changes_that_failed_to_apply_to_tot.add(change)
        apply_chain = False
        continue

      for dep in deps:
        dep_change = change_map.get(dep)
        if not dep_change:
          # The dep may have been committed already.
          try:
            if not helper.IsChangeCommitted(dep, must_match=False):
              message = ('Could not apply change %s because dependent '
                         'change %s is not ready to be committed.' % (
                          change.id, dep))
              logging.info(message)
              change.apply_error_message = message
              changes_that_failed_to_apply_to_tot.add(change)
              apply_chain = False
              break
          except gerrit_helper.QueryNotSpecific:
            message = ('Change %s could not be handled due to its dependency '
                       '%s matching multiple branches.' % (change.id, dep))
            logging.info(message)
            change.apply_error_message = message
            changes_that_failed_to_apply_to_tot.add(change)
            apply_chain = False
            break
        else:
          change_stack.insert(0, dep_change)

      # Should we apply the chain -- i.e. all deps are ready.
      if not apply_chain:
        continue

      # Apply changes in change_stack.  For chains that were aborted early,
      # we still want to apply changes in change_stack because they were
      # ready to be committed (o/w wouldn't have been in the change_map).
      for change in change_stack:
        try:
          if change in changes_applied:
            continue
          elif change in changes_that_failed_to_apply_to_tot:
            break

          # If we're in dryrun mode, then 3way is always allowed.
          # Otherwise, allow 3way only if the gerrit project allows it.
          trivial = False if dryrun else not self.IsContentMerging(change,
                                                                   manifest)

          change.Apply(buildroot, trivial=trivial)

        except cros_patch.ApplyPatchException as e:
          if e.inflight:
            changes_that_failed_to_apply_against_other_changes.add(
                MarkChangeFailedInflight(change))
          else:
            changes_that_failed_to_apply_to_tot.add(
                MarkChangeFailedToT(change))

        except cros_patch.PatchException, e:
          changes_that_failed_to_apply_to_tot.add(MarkChangeFailedToT(change))
        else:
          # We applied the change successfully.
          changes_applied.add(change)
          changes_list.append(change)
          cros_build_lib.PrintBuildbotLink(str(change), change.url)
          continue
        break

    logging.debug('Done investigating changes.  Applied %s',
                  ' '.join([c.id for c in changes_list]))

    return (changes_list,
            changes_that_failed_to_apply_to_tot,
            changes_that_failed_to_apply_against_other_changes)


class ValidationPool(object):
  """Class that handles interactions with a validation pool.

  This class can be used to acquire a set of commits that form a pool of
  commits ready to be validated and committed.

  Usage:  Use ValidationPool.AcquirePool -- a static
  method that grabs the commits that are ready for validation.
  """

  GLOBAL_DRYRUN = False

  def __init__(self, overlays, build_number, builder_name, is_master, dryrun,
               changes=None, non_os_changes=None,
               conflicting_changes=None, helper_pool=None):
    """Initializes an instance by setting default valuables to instance vars.

    Generally use AcquirePool as an entry pool to a pool rather than this
    method.

    Args:
      overlays:  One of constants.VALID_OVERLAYS.
      build_number:  Build number for this validation attempt.
      builder_name:  Builder name on buildbot dashboard.
      is_master: True if this is the master builder for the Commit Queue.
      dryrun: If set to True, do not submit anything to Gerrit.
    Optional Args:
      changes: List of changes for this validation pool.
      non_manifest_changes: List of changes that are part of this validation
        pool but aren't part of the cros checkout.
      changes_that_failed_to_apply_earlier: Changes that failed to apply but
        we're keeping around because they conflict with other changes in
        flight.
      helper_pool: A HelperPool instance.  If not specified, a HelperPool
        instance is created with it's access limit discerned via looking at
        overlays.
    """

    if helper_pool is None:
      helper_pool = self.GetGerritHelpersForOverlays(overlays)
    self._helper_pool = helper_pool

    # These instances can be instantiated via both older, or newer pickle
    # dumps.  Thus we need to assert the given args since we may be getting
    # a value we no longer like (nor work with).
    if overlays not in constants.VALID_OVERLAYS:
      raise ValueError("Unknown/unsupported overlay: %r" % (overlays,))

    if not isinstance(build_number, int):
      raise ValueError("Invalid build_number: %r" % (build_number,))

    if not isinstance(builder_name, basestring):
      raise ValueError("Invalid builder_name: %r" % (builder_name,))

    for changes_name, changes_value in (
        ('changes', changes), ('non_os_changes', non_os_changes),
        ('conflicting_changes', conflicting_changes)):
      if changes_value is None:
        continue
      if not all(isinstance(x, cros_patch.GitRepoPatch) for x in changes_value):
        raise ValueError(
            'Invalid %s: all elements must be a GitRepoPatch derivative, got %r'
            % (changes_name, changes_value))


    build_dashboard = self.GetBuildDashboardForOverlays(overlays)

    self.build_log = '%s/builders/%s/builds/%s' % (
        build_dashboard, builder_name, str(build_number))

    self.is_master = bool(is_master)
    self.dryrun = bool(dryrun) or self.GLOBAL_DRYRUN

    # See optional args for types of changes.
    self.changes = changes or []
    self.non_manifest_changes = non_os_changes or []
    self.changes_that_failed_to_apply_earlier = conflicting_changes or []

    # Private vars only used for pickling.
    self._overlays = overlays
    self._build_number = build_number
    self._builder_name = builder_name
    self._patch_series = PatchSeries(helper_pool=helper_pool)

  @staticmethod
  def GetBuildDashboardForOverlays(overlays):
    """Discern the dashboard to use based on the given overlay."""
    if overlays in [constants.PRIVATE_OVERLAYS, constants.BOTH_OVERLAYS]:
      return _BUILD_INT_DASHBOARD
    return _BUILD_DASHBOARD

  @staticmethod
  def GetGerritHelpersForOverlays(overlays):
    """Discern the allowed GerritHelpers to use based on the given overlay."""
    # TODO(sosa): Remove False case once overlays logic has stabilized on TOT.
    internal = external = False
    if overlays in [constants.PUBLIC_OVERLAYS, constants.BOTH_OVERLAYS, False]:
      external = True

    if overlays in [constants.PRIVATE_OVERLAYS, constants.BOTH_OVERLAYS]:
      internal = True

    return HelperPool.SimpleCreate(internal=internal, external=external)

  def __reduce__(self):
    """Used for pickling to re-create validation pool."""
    return (
        self.__class__,
        (
            self._overlays, self._build_number, self._builder_name,
            self.is_master, self.dryrun, self.changes,
            self.non_manifest_changes,
            self.changes_that_failed_to_apply_earlier))

  @classmethod
  def _IsTreeOpen(cls, max_timeout=600):
    """Returns True if the tree is open or throttled.

    At the highest level this function checks to see if the Tree is Open.
    However, it also does a robustified wait as the server hosting the tree
    status page is known to be somewhat flaky and these errors can be handled
    with multiple retries.  In addition, it waits around for the Tree to Open
    based on |max_timeout| to give a greater chance of returning True as it
    expects callees to want to do some operation based on a True value.
    If a caller is not interested in this feature they should set |max_timeout|
    to 0.
    """

    # Limit sleep interval to the set of 1-30
    sleep_timeout = min(max(max_timeout / 5, 1), 30)

    def _SleepWithExponentialBackOff(current_sleep):
      """Helper function to sleep with exponential backoff."""
      time.sleep(current_sleep)
      return current_sleep * 2

    def _CanSubmit(status_url):
      """Returns the JSON dictionary response from the status url."""
      max_attempts = 5
      current_sleep = 1
      for _ in range(max_attempts):
        try:
          # Check for successful response code.
          response = urllib.urlopen(status_url)
          if response.getcode() == 200:
            data = json.load(response)
            return data['general_state'] in ('open', 'throttled')

        # We remain robust against IOError's and retry.
        except IOError:
          pass

        current_sleep = _SleepWithExponentialBackOff(current_sleep)
      else:
        # We go ahead and say the tree is open if we can't get the status.
        logging.warn('Could not get a status from %s', status_url)
        return True

    # Check before looping with timeout.
    status_url = 'https://chromiumos-status.appspot.com/current?format=json'
    start_time = time.time()

    if _CanSubmit(status_url):
      return True
    # Loop until either we run out of time or the tree is open.
    while time.time() - start_time < max_timeout:
      if _CanSubmit(status_url):
        return True
      time.sleep(sleep_timeout)

    return False

  @classmethod
  def AcquirePool(cls, overlays, buildroot, build_number, builder_name, dryrun):
    """Acquires the current pool from Gerrit.

    Polls Gerrit and checks for which change's are ready to be committed.

    Args:
      overlays:  One of constants.VALID_OVERLAYS.
      buildroot: The location of the buildroot used to filter projects.
      build_number: Corresponding build number for the build.
      builder_name:  Builder name on buildbot dashboard.
      dryrun: Don't submit anything to gerrit.
    Returns:
      ValidationPool object.
    Raises:
      TreeIsClosedException: if the tree is closed.
    """
    # We choose a longer wait here as we haven't committed to anything yet. By
    # doing this here we can reduce the number of builder cycles.
    if dryrun or cls._IsTreeOpen(max_timeout=3600):
      # Only master configurations should call this method.
      pool = ValidationPool(overlays, build_number, builder_name, True, dryrun)
      # Iterate through changes from all gerrit instances we care about.
      for helper in cls.GetGerritHelpersForOverlays(overlays):
        raw_changes = helper.GrabChangesReadyForCommit()
        changes, non_manifest_changes = ValidationPool._FilterNonCrosProjects(
            raw_changes, buildroot)
        pool.changes.extend(changes)
        pool.non_manifest_changes.extend(non_manifest_changes)

      return pool
    else:
      raise TreeIsClosedException()

  @classmethod
  def AcquirePoolFromManifest(cls, manifest, overlays, build_number,
                              builder_name, is_master, dryrun):
    """Acquires the current pool from a given manifest.

    Args:
      manifest: path to the manifest where the pool resides.
      overlays:  One of constants.VALID_OVERLAYS.
      build_number: Corresponding build number for the build.
      builder_name:  Builder name on buildbot dashboard.
      is_master: Boolean that indicates whether this is a pool for a master.
        config or not.
      dryrun: Don't submit anything to gerrit.
    Returns:
      ValidationPool object.
    """
    pool = ValidationPool(overlays, build_number, builder_name, is_master,
                          dryrun)
    manifest_dom = minidom.parse(manifest)
    pending_commits = manifest_dom.getElementsByTagName(
        lkgm_manager.PALADIN_COMMIT_ELEMENT)
    for pending_commit in pending_commits:
      project = pending_commit.getAttribute(lkgm_manager.PALADIN_PROJECT_ATTR)
      change = pending_commit.getAttribute(lkgm_manager.PALADIN_CHANGE_ID_ATTR)
      commit = pending_commit.getAttribute(lkgm_manager.PALADIN_COMMIT_ATTR)

      for helper in cls.GetGerritHelpersForOverlays(overlays):
        try:
          patch = helper.GrabPatchFromGerrit(project, change, commit)
          pool.changes.append(patch)
          break
        except gerrit_helper.QueryHasNoResults:
          pass
      else:
        raise NoMatchingChangeFoundException(
            'Could not find change defined by %s' % pending_commit)

    return pool

  @staticmethod
  def _FilterNonCrosProjects(changes, buildroot):
    """Filters changes to a tuple of relevant changes.

    There are many code reviews that are not part of Chromium OS and/or
    only relevant on a different branch. This method returns a tuple of (
    relevant reviews in a manifest, relevant reviews not in the manifest). Note
    that this function must be run while chromite is checked out in a
    repo-managed checkout.

    Args:
      changes:  List of GerritPatch objects.
      buildroot:  Buildroot containing manifest to filter against.

    Returns tuple of
      relevant reviews in a manifest, relevant reviews not in the manifest.
    """

    def IsCrosReview(change):
      return (change.project.startswith('chromiumos') or
              change.project.startswith('chromeos'))

    # First we filter to only Chromium OS repositories.
    changes = [c for c in changes if IsCrosReview(c)]

    handler = cros_build_lib.ManifestCheckout.Cached(buildroot)
    projects = handler.projects

    changes_in_manifest = []
    changes_not_in_manifest = []
    for change in changes:
      branch = handler.default.get('revision')
      patch_branch = 'refs/heads/%s' % change.tracking_branch
      project = projects.get(change.project)
      if project:
        branch = project.get('revision') or branch

      if branch == patch_branch:
        if project:
          changes_in_manifest.append(change)
        else:
          changes_not_in_manifest.append(change)
      else:
        logging.info('Filtered change %s', change)

    return changes_in_manifest, changes_not_in_manifest

  def ApplyPoolIntoRepo(self, buildroot):
    """Applies changes from pool into the directory specified by the buildroot.

    This method applies changes in the order specified.  It also respects
    dependency order.
    Returns:

    True if we managed to apply any changes.
    """
    try:
      applied, failed_tot, failed_inflight = self._patch_series.Apply(
          buildroot, self.changes, self.dryrun)
    except (KeyboardInterrupt, RuntimeError, SystemExit):
      raise
    except Exception, e:
      cros_build_lib.Error(
          "Unhandled Exception occured during CQ's Apply: %s\n"
          "Failing the entire series to prevent CQ from going into an "
          "infinite loop hanging on these CLs.\n"
          "Affected patches: %s"
          % (e, ' '.join(x.change_id for x in self.changes)))
      self.HandleApplicationFailure(self.changes)
      raise

    if self.is_master:
      for change in applied:
        self.HandleApplied(change)

    if failed_tot:
      logging.info('Changes %s could not be applied cleanly.',
                  ' '.join([c.id for c in failed_tot]))
      self.HandleApplicationFailure(failed_tot)
    self.changes_that_failed_to_apply_earlier.extend(failed_inflight)
    self.changes = applied

    return bool(self.changes)

  # Note: All submit code, all gerrit code, and basically everything other
  # than patch resolution/applying needs to use .change_id from patch objects.
  # Basically all code from this point forward.

  def _SubmitChanges(self, changes):
    """Submits given changes to Gerrit.

    Args:
      changes: GerritPatch's to submit.

    Raises:
      TreeIsClosedException: if the tree is closed.
      FailedToSubmitAllChangesException: if we can't submit a change.
    """
    assert self.is_master, 'Non-master builder calling SubmitPool'
    changes_that_failed_to_submit = []
    # We use the default timeout here as while we want some robustness against
    # the tree status being red i.e. flakiness, we don't want to wait too long
    # as validation can become stale.
    if self.dryrun or ValidationPool._IsTreeOpen():
      for change in changes:
        was_change_submitted = False
        logging.info('Change %s will be submitted', change)
        try:
          self.SubmitChange(change)
          was_change_submitted = self._helper_pool.ForChange(
              change).IsChangeCommitted(str(change.gerrit_number), self.dryrun)
        except cros_build_lib.RunCommandError:
          logging.error('gerrit review --submit failed for change.')
        finally:
          if not was_change_submitted:
            logging.error('Could not submit %s', str(change))
            self.HandleCouldNotSubmit(change)
            changes_that_failed_to_submit.append(change)

      if changes_that_failed_to_submit:
        raise FailedToSubmitAllChangesException(changes_that_failed_to_submit)

    else:
      raise TreeIsClosedException()

  def SubmitChange(self, change):
    """Submits patch using Gerrit Review."""
    cmd = self._helper_pool.ForChange(change).GetGerritReviewCommand(
        ['--submit', '%s,%s' % (change.gerrit_number, change.patch_number)])

    _RunCommand(cmd, self.dryrun)

  def SubmitNonManifestChanges(self):
    """Commits changes to Gerrit from Pool that aren't part of the checkout.

    Raises:
      TreeIsClosedException: if the tree is closed.
      FailedToSubmitAllChangesException: if we can't submit a change.
    """
    self._SubmitChanges(self.non_manifest_changes)

  def SubmitPool(self):
    """Commits changes to Gerrit from Pool.  This is only called by a master.

    Raises:
      TreeIsClosedException: if the tree is closed.
      FailedToSubmitAllChangesException: if we can't submit a change.
    """
    self._SubmitChanges(self.changes)
    if self.changes_that_failed_to_apply_earlier:
      self.HandleApplicationFailure(self.changes_that_failed_to_apply_earlier)

  def HandleApplicationFailure(self, changes):
    """Handles changes that were not able to be applied cleanly.

    Args:
      changes: GerritPatch's to handle.
    """
    for change in changes:
      logging.info('Change %s did not apply cleanly.', change.change_id)
      if self.is_master:
        self.HandleCouldNotApply(change)

  def HandleValidationFailure(self):
    """Handles failed changes by removing them from next Validation Pools."""
    logging.info('Validation failed for all changes.')
    for change in self.changes:
      logging.info('Validation failed for change %s.', change)
      self.HandleCouldNotVerify(change)

  def HandleValidationTimeout(self):
    """Handles changes that timed out."""
    logging.info('Validation timed out for all changes.')
    for change in self.changes:
      logging.info('Validation timed out for change %s.', change)
      self._SendNotification(change,
          'The Commit Queue timed out while verifying your change in '
          '%(build_log)s . This means that a supporting builder did not '
          'finish building your change within the specified timeout. If you '
          'believe this happened in error, just re-mark your commit as ready. '
          'Your change will then get automatically retried.')
      self._helper_pool.ForChange(change).RemoveCommitReady(
          change, dryrun=self.dryrun)

  def _SendNotification(self, change, msg):
    msg %= {'build_log':self.build_log}
    PaladinMessage(msg, change, self._helper_pool.ForChange(change)).Send(
        self.dryrun)

  def HandleCouldNotSubmit(self, change):
    """Handler that is called when Paladin can't submit a change.

    This should be rare, but if an admin overrides the commit queue and commits
    a change that conflicts with this change, it'll apply, build/validate but
    receive an error when submitting.

    Args:
      change: GerritPatch instance to operate upon.
    """
    self._SendNotification(change,
        'The Commit Queue failed to submit your change in %(build_log)s . '
        'This can happen if you submitted your change or someone else '
        'submitted a conflicting change while your change was being tested.')
    self._helper_pool.ForChange(change).RemoveCommitReady(
        change, dryrun=self.dryrun)

  def HandleCouldNotVerify(self, change):
    """Handler for when Paladin fails to validate a change.

    This handler notifies set Verified-1 to the review forcing the developer
    to re-upload a change that works.  There are many reasons why this might be
    called e.g. build or testing exception.

    Args:
      change: GerritPatch instance to operate upon.
    """
    self._SendNotification(change,
        'The Commit Queue failed to verify your change in %(build_log)s . '
        'If you believe this happened in error, just re-mark your commit as '
        'ready. Your change will then get automatically retried.')
    self._helper_pool.ForChange(change).RemoveCommitReady(
        change, dryrun=self.dryrun)

  def HandleCouldNotApply(self, change):
    """Handler for when Paladin fails to apply a change.

    This handler notifies set CodeReview-2 to the review forcing the developer
    to re-upload a rebased change.

    Args:
      change: GerritPatch instance to operate upon.
    """
    msg = 'The Commit Queue failed to apply your change in %(build_log)s . '
    # This is written this way to protect against bugs in CQ itself.  We log
    # it both to the build output, and mark the change w/ it.
    extra_msg = getattr(change, 'apply_error_message', None)
    if extra_msg is None:
      logging.error(
          'Change %s was passed to HandleCouldNotApply without an appropriate '
          'apply_error_message set.  Internal bug.', change)
      extra_msg = (
          'Internal CQ issue: extra error info was not given,  Please contact '
          'the build team and ensure they are aware of this specific change '
          'failing.')

    msg += extra_msg
    self._SendNotification(change, msg)
    self._helper_pool.ForChange(change).RemoveCommitReady(
        change, dryrun=self.dryrun)

  def HandleApplied(self, change):
    """Handler for when Paladin successfully applies a change.

    This handler notifies a developer that their change is being tried as
    part of a Paladin run defined by a build_log.

    Args:
      change: GerritPatch instance to operate upon.
    """
    self._SendNotification(change,
        'The Commit Queue has picked up your change. '
        'You can follow along at %(build_log)s .')


class PaladinMessage():
  """An object that is used to send messages to developers about their changes.
  """
  # URL where Paladin documentation is stored.
  _PALADIN_DOCUMENTATION_URL = ('http://www.chromium.org/developers/'
                                'tree-sheriffs/sheriff-details-chromium-os/'
                                'commit-queue-overview')

  def __init__(self, message, patch, helper):
    self.message = message
    self.patch = patch
    self.helper = helper

  def _ConstructPaladinMessage(self):
    """Adds any standard Paladin messaging to an existing message."""
    return self.message + (' Please see %s for more information.' %
                           self._PALADIN_DOCUMENTATION_URL)

  def Send(self, dryrun):
    """Sends the message to the developer."""
    cmd = self.helper.GetGerritReviewCommand(
        ['-m', '"%s"' % self._ConstructPaladinMessage(),
         '%s,%s' % (self.patch.gerrit_number, self.patch.patch_number)])
    _RunCommand(cmd, dryrun)
