#!/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 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():
  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())
