#!/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.
"""Commit queue executable.

Reuse Rietveld and the Chromium Try Server to process and automatically commit
patches.
"""

import logging
import logging.handlers
import optparse
import os
import shutil
import signal
import socket
import sys
import tempfile
import time

import find_depot_tools  # pylint: disable=W0611
import checkout
import fix_encoding
import rietveld
import subprocess2

import async_push
import cq_alerts
import creds
import errors
import projects
import sig_handler


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


class OnlyIssueRietveld(rietveld.Rietveld):
  """Returns a single issue for end-to-end in prod testing."""
  def __init__(self, url, email, password, extra_headers, only_issue):
    super(OnlyIssueRietveld, self).__init__(url, email, password, extra_headers)
    self._only_issue = only_issue

  def get_pending_issues(self):
    """If it's set to return a single issue, only return this one."""
    if self._only_issue:
      return [self._only_issue]
    return []

  def get_issue_properties(self, issue, messages):
    """Hacks the result to fake that the issue has the commit bit set."""
    data = super(OnlyIssueRietveld, self).get_issue_properties(issue, messages)
    if issue == self._only_issue:
      data['commit'] = True
    return data

  def set_flag(self, issue, patchset, flag, value):
    if issue == self._only_issue and flag == 'commit' and value == 'False':
      self._only_issue = None
    return super(OnlyIssueRietveld, self).set_flag(issue, patchset, flag, value)


class FakeCheckout(object):
  def __init__(self):
    self.project_path = os.getcwd()
    self.project_name = os.path.basename(self.project_path)

  @staticmethod
  def prepare(_revision):
    logging.info('FakeCheckout is syncing')
    return unicode('FAKE')

  @staticmethod
  def apply_patch(*_args):
    logging.info('FakeCheckout is applying a patch')

  @staticmethod
  def commit(*_args):
    logging.info('FakeCheckout is committing patch')
    return 'FAKED'

  @staticmethod
  def get_settings(_key):
    return None

  @staticmethod
  def revisions(*_args):
    return None


def AlertOnUncleanCheckout():
  """Sends an alert if the cq is running live with local edits."""
  diff = subprocess2.capture(['gclient', 'diff'], cwd=ROOT_DIR).strip()
  if diff:
    cq_alerts.SendAlert(
        'CQ running with local diff.',
        ('Ruh-roh! Commit queue was started with an unclean checkout.\n\n'
         '$ gclient diff\n%s' % diff))


def SetupLogging(options):
  """Configures the logging module."""
  logging.getLogger().setLevel(logging.DEBUG)
  if options.verbose:
    level = logging.DEBUG
  else:
    level = logging.INFO
  console_logging = logging.StreamHandler()
  console_logging.setFormatter(logging.Formatter(
      '%(asctime)s %(levelname)7s %(message)s'))
  console_logging.setLevel(level)
  logging.getLogger().addHandler(console_logging)

  log_directory = 'logs-' + options.project
  if not os.path.exists(log_directory):
    os.mkdir(log_directory)

  logging_rotating_file = logging.handlers.RotatingFileHandler(
      filename=os.path.join(log_directory, 'commit_queue.log'),
      maxBytes= 10*1024*1024,
      backupCount=50)
  logging_rotating_file.setLevel(logging.DEBUG)
  logging_rotating_file.setFormatter(logging.Formatter(
      '%(asctime)s %(levelname)-8s %(module)15s(%(lineno)4d): %(message)s'))
  logging.getLogger().addHandler(logging_rotating_file)


class SignalInterrupt(Exception):
  """Exception that indicates being interrupted by a caught signal."""
  
  def __init__(self, signal_set=None, *args, **kwargs):
    super(SignalInterrupt, self).__init__(*args, **kwargs)
    self.signal_set = signal_set


def SaveDatabaseCopyForDebugging(db_path):
  """Saves database file for debugging. Returns name of the saved file."""
  with tempfile.NamedTemporaryFile(
      dir=os.path.dirname(db_path),
      prefix='db.debug.',
      suffix='.json',
      delete=False) as tmp_file:
    with open(db_path) as db_file:
      shutil.copyfileobj(db_file, tmp_file)
    return tmp_file.name


def main():
  # Set a default timeout for sockets. This is critical when talking to remote
  # services like AppEngine and buildbot.
  socket.setdefaulttimeout(70.0)

  parser = optparse.OptionParser(
      description=sys.modules['__main__'].__doc__)
  project_choices = projects.supported_projects()
  parser.add_option('-v', '--verbose', action='store_true')
  parser.add_option(
      '--no-dry-run',
      action='store_false',
      dest='dry_run',
      default=True,
      help='Run for real instead of dry-run mode which is the default. '
      'WARNING: while the CQ won\'t touch rietveld in dry-run mode, the '
      'Try Server will. So it is recommended to use --only-issue')
  parser.add_option(
      '--only-issue',
      type='int',
      help='Limits to a single issue. Useful for live testing; WARNING: it '
      'will fake that the issue has the CQ bit set, so only try with an '
      'issue you don\'t mind about.')
  parser.add_option(
      '--fake',
      action='store_true',
      help='Run with a fake checkout to speed up testing')
  parser.add_option(
      '--no-try',
      action='store_true',
      help='Don\'t send try jobs.')
  parser.add_option(
      '-p',
      '--poll-interval',
      type='int',
      default=10,
      help='Minimum delay between each polling loop, default: %default')
  parser.add_option(
      '--query-only',
      action='store_true',
      help='Return internal state')
  parser.add_option(
      '--project',
      choices=project_choices,
      help='Project to run the commit queue against: %s' %
           ', '.join(project_choices))
  parser.add_option(
      '-u',
      '--user',
      default='commit-bot@chromium.org',
      help='User to use instead of %default')
  options, args = parser.parse_args()
  if args:
    parser.error('Unsupported args: %s' % args)
  if not options.project:
    parser.error('Need to pass a valid project to --project.\nOptions are: %s' %
        ', '.join(project_choices))

  SetupLogging(options)
  try:
    work_dir = os.path.join(ROOT_DIR, 'workdir')
    # Use our specific subversion config.
    checkout.SvnMixIn.svn_config = checkout.SvnConfig(
        os.path.join(ROOT_DIR, 'subversion_config'))

    url = 'https://codereview.chromium.org'
    gaia_creds = creds.Credentials(os.path.join(work_dir, '.gaia_pwd'))
    if options.dry_run:
      logging.debug('Dry run - skipping SCM check.')
      if options.only_issue:
        parser.error('--only-issue is not supported with dry run')
      else:
        print('Using read-only Rietveld')
      # Make sure rietveld is not modified.
      rietveld_obj = rietveld.ReadOnlyRietveld(
          url,
          options.user,
          gaia_creds.get(options.user),
          None)
    else:
      AlertOnUncleanCheckout()
      print('WARNING: The Commit Queue is going to commit stuff')
      if options.only_issue:
        print('Using only issue %d' % options.only_issue)
        rietveld_obj = OnlyIssueRietveld(
            url,
            options.user,
            gaia_creds.get(options.user),
            None,
            options.only_issue)
      else:
        rietveld_obj = rietveld.Rietveld(
            url,
            options.user,
            gaia_creds.get(options.user),
            None)

    pc = projects.load_project(
        options.project,
        options.user,
        work_dir,
        rietveld_obj,
        options.no_try)

    if options.dry_run:
      if options.fake:
        # Disable the checkout.
        print 'Using no checkout'
        pc.context.checkout = FakeCheckout()
      else:
        print 'Using read-only checkout'
        pc.context.checkout = checkout.ReadOnlyCheckout(pc.context.checkout)
      # Save pushed events on disk.
      print 'Using read-only chromium-status interface'
      pc.context.status = async_push.AsyncPushStore()

    landmine_path = os.path.join(work_dir,
                                 pc.context.checkout.project_name + '.landmine')
    db_path = os.path.join(work_dir, pc.context.checkout.project_name + '.json')
    if os.path.isfile(db_path):
      if os.path.isfile(landmine_path):
        debugging_path = SaveDatabaseCopyForDebugging(db_path)
        os.remove(db_path)
        logging.warning(('Deleting database because previous shutdown '
                        'was unclean. The copy of the database is saved '
                        'as %s.') % debugging_path)
      else:
        try:
          pc.load(db_path)
        except ValueError as e:
          debugging_path = SaveDatabaseCopyForDebugging(db_path)
          os.remove(db_path)
          logging.warning(('Failed to parse database (%r), deleting it. '
                          'The copy of the database is saved as %s.') %
                          (e, debugging_path))
          raise e

    # Create a file to indicate unclean shutdown.
    with open(landmine_path, 'w'):
      pass

    sig_handler.installHandlers(
        signal.SIGINT,
        signal.SIGHUP
    )

    # Sync every 5 minutes.
    SYNC_DELAY = 5*60
    try:
      if options.query_only:
        pc.look_for_new_pending_commit()
        pc.update_status()
        print(str(pc.queue))
        os.remove(landmine_path)
        return 0

      now = time.time()
      next_loop = now + options.poll_interval
      # First sync is on second loop.
      next_sync = now + options.poll_interval * 2
      while True:
        # In theory, we would gain in performance to parallelize these tasks. In
        # practice I'm not sure it matters.
        pc.look_for_new_pending_commit()
        pc.process_new_pending_commit()
        pc.update_status()
        pc.scan_results()
        if sig_handler.getTriggeredSignals():
          raise SignalInterrupt(signal_set=sig_handler.getTriggeredSignals())
        # Save the db at each loop. The db can easily be in the 1mb range so
        # it's slowing down the CQ a tad but it in the 100ms range even for that
        # size.
        pc.save(db_path)

        # More than a second to wait and due to sync.
        now = time.time()
        if (next_loop - now) >= 1 and (next_sync - now) <= 0:
          if sys.stdout.isatty():
            sys.stdout.write('Syncing while waiting                \r')
            sys.stdout.flush()
          try:
            pc.context.checkout.prepare(None)
          except subprocess2.CalledProcessError as e:
            # Don't crash, most of the time it's the svn server that is dead.
            # How fun. Send a stack trace to annoy the maintainer.
            errors.send_stack(e)
          next_sync = time.time() + SYNC_DELAY

        now = time.time()
        next_loop = max(now, next_loop)
        while True:
          # Abort if any signals are set
          if sig_handler.getTriggeredSignals():
            raise SignalInterrupt(signal_set=sig_handler.getTriggeredSignals())
          delay = next_loop - now
          if delay <= 0:
            break
          if sys.stdout.isatty():
            sys.stdout.write('Sleeping for %1.1f seconds          \r' % delay)
            sys.stdout.flush()
          time.sleep(min(delay, 0.1))
          now = time.time()
        if sys.stdout.isatty():
          sys.stdout.write('Running (please do not interrupt)   \r')
          sys.stdout.flush()
        next_loop = time.time() + options.poll_interval
    except:  # Catch all fatal exit conditions.
      logging.exception('CQ loop terminating')
      raise
    finally:
      logging.warning('Saving db...')
      pc.save(db_path)
      pc.close()
      logging.warning('db save successful.')
  except SignalInterrupt:
    # This is considered a clean shutdown: we only throw this exception
    # from selected places in the code where the database should be
    # in a known and consistent state.
    os.remove(landmine_path)

    print 'Bye bye (SignalInterrupt)'
    # 23 is an arbitrary value to signal loop.sh that it must stop looping.
    return 23
  except KeyboardInterrupt:
    # This is actually an unclean shutdown. Do not remove the landmine file.
    # One example of this is user hitting ctrl-c twice at an arbitrary point
    # inside the CQ loop. There are no guarantees about consistent state
    # of the database then.

    print 'Bye bye (KeyboardInterrupt - this is considered unclean shutdown)'
    # 23 is an arbitrary value to signal loop.sh that it must stop looping.
    return 23
  except errors.ConfigurationError as e:
    parser.error(str(e))
    return 1

  # CQ generally doesn't exit by itself, but if we ever get here, it looks
  # like a clean shutdown so remove the landmine file.
  # TODO(phajdan.jr): Do we ever get here?
  os.remove(landmine_path)
  return 0


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