#!/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. Pass empty email and
      # password to bypass authentication; this additionally
      # guarantees rietveld will not allow any changes.
      rietveld_obj = rietveld.ReadOnlyRietveld(url, email='', password='')
    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())
