#!/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.
  # TODO(phajdan.jr): This used to be 70s. Investigate lowering it again.
  socket.setdefaulttimeout(60.0 * 15)

  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')
  parser.add_option(
      '--rietveld',
      default='https://codereview.chromium.org',
      help='Rietveld server 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 = options.rietveld
    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())
