#!/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.

"""Applies an issue from Rietveld.
"""

import getpass
import json
import logging
import optparse
import os
import subprocess
import sys
import urllib2

import breakpad  # pylint: disable=W0611

import annotated_gclient
import auth
import checkout
import fix_encoding
import gclient_utils
import rietveld
import scm

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


class Unbuffered(object):
  """Disable buffering on a file object."""
  def __init__(self, stream):
    self.stream = stream

  def write(self, data):
    self.stream.write(data)
    self.stream.flush()

  def __getattr__(self, attr):
    return getattr(self.stream, attr)


def main():
  # TODO(pgervais): This function is way too long. Split.
  sys.stdout = Unbuffered(sys.stdout)
  parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
  parser.add_option(
      '-v', '--verbose', action='count', default=0,
      help='Prints debugging infos')
  parser.add_option(
      '-e', '--email',
      help='Email address to access rietveld.  If not specified, anonymous '
           'access will be used.')
  parser.add_option(
      '-E', '--email-file',
      help='File containing the email address to access rietveld. '
           'If not specified, anonymous access will be used.')
  parser.add_option(
      '-k', '--private-key-file',
      help='Path to file containing a private key in p12 format for OAuth2 '
           'authentication with "notasecret" password (as generated by Google '
           'Cloud Console).')
  parser.add_option(
      '-i', '--issue', type='int', help='Rietveld issue number')
  parser.add_option(
      '-p', '--patchset', type='int', help='Rietveld issue\'s patchset number')
  parser.add_option(
      '-r',
      '--root_dir',
      default=os.getcwd(),
      help='Root directory to apply the patch')
  parser.add_option(
      '-s',
      '--server',
      default='http://codereview.chromium.org',
      help='Rietveld server')
  parser.add_option('--no-auth', action='store_true',
                    help='Do not attempt authenticated requests.')
  parser.add_option('--revision-mapping', default='{}',
                    help='When running gclient, annotate the got_revisions '
                         'using the revision-mapping.')
  parser.add_option('-f', '--force', action='store_true',
                    help='Really run apply_issue, even if .update.flag '
                         'is detected.')
  parser.add_option('-b', '--base_ref', help='DEPRECATED do not use.')
  parser.add_option('--whitelist', action='append', default=[],
                    help='Patch only specified file(s).')
  parser.add_option('--blacklist', action='append', default=[],
                    help='Don\'t patch specified file(s).')
  parser.add_option('-d', '--ignore_deps', action='store_true',
                    help='Don\'t run gclient sync on DEPS changes.')

  auth.add_auth_options(parser)
  options, args = parser.parse_args()
  auth_config = auth.extract_auth_config_from_options(options)

  if options.whitelist and options.blacklist:
    parser.error('Cannot specify both --whitelist and --blacklist')

  if options.email and options.email_file:
    parser.error('-e and -E options are incompatible')

  if (os.path.isfile(os.path.join(os.getcwd(), 'update.flag'))
      and not options.force):
    print 'update.flag file found: bot_update has run and checkout is already '
    print 'in a consistent state. No actions will be performed in this step.'
    return 0
  logging.basicConfig(
      format='%(levelname)5s %(module)11s(%(lineno)4d): %(message)s',
      level=[logging.WARNING, logging.INFO, logging.DEBUG][
          min(2, options.verbose)])
  if args:
    parser.error('Extra argument(s) "%s" not understood' % ' '.join(args))
  if not options.issue:
    parser.error('Require --issue')
  options.server = options.server.rstrip('/')
  if not options.server:
    parser.error('Require a valid server')

  options.revision_mapping = json.loads(options.revision_mapping)

  # read email if needed
  if options.email_file:
    if not os.path.exists(options.email_file):
      parser.error('file does not exist: %s' % options.email_file)
    with open(options.email_file, 'rb') as f:
      options.email = f.read().strip()

  print('Connecting to %s' % options.server)
  # Always try un-authenticated first, except for OAuth2
  if options.private_key_file:
    # OAuth2 authentication
    obj = rietveld.JwtOAuth2Rietveld(options.server,
                                     options.email,
                                     options.private_key_file)
    properties = obj.get_issue_properties(options.issue, False)
  else:
    # Passing None as auth_config disables authentication.
    obj = rietveld.Rietveld(options.server, None)
    properties = None
    # Bad except clauses order (HTTPError is an ancestor class of
    # ClientLoginError)
    # pylint: disable=E0701
    try:
      properties = obj.get_issue_properties(options.issue, False)
    except urllib2.HTTPError as e:
      if e.getcode() != 302:
        raise
      if options.no_auth:
        exit('FAIL: Login detected -- is issue private?')
      # TODO(maruel): A few 'Invalid username or password.' are printed first,
      # we should get rid of those.
    except rietveld.upload.ClientLoginError as e:
      # Fine, we'll do proper authentication.
      pass
    if properties is None:
      obj = rietveld.Rietveld(options.server, auth_config, options.email)
      try:
        properties = obj.get_issue_properties(options.issue, False)
      except rietveld.upload.ClientLoginError as e:
        print('Accessing the issue requires proper credentials.')
        return 1

  if not options.patchset:
    options.patchset = properties['patchsets'][-1]
    print('No patchset specified. Using patchset %d' % options.patchset)

  issues_patchsets_to_apply = [(options.issue, options.patchset)]

  # Temporary comment out the below while we try to figure out what to do with
  # patchset dependencies on trybots.
  # TODO(rmistry): Uncomment the below after a solution is found.
  # depends_on_info = obj.get_depends_on_patchset(options.issue,
  #                                               options.patchset)
  # while depends_on_info:
  #   depends_on_issue = int(depends_on_info['issue'])
  #   depends_on_patchset = int(depends_on_info['patchset'])
  #   try:
  #     depends_on_info = obj.get_depends_on_patchset(depends_on_issue,
  #                                                   depends_on_patchset)
  #     issues_patchsets_to_apply.insert(0, (depends_on_issue,
  #                                          depends_on_patchset))
  #   except urllib2.HTTPError:
  #     print ('The patchset that was marked as a dependency no longer '
  #            'exists: %s/%d/#ps%d' % (
  #                options.server, depends_on_issue, depends_on_patchset))
  #     print 'Therefore it is likely that this patch will not apply cleanly.'
  #     print
  #     depends_on_info = None

  num_issues_patchsets_to_apply = len(issues_patchsets_to_apply)
  if num_issues_patchsets_to_apply > 1:
    print
    print 'apply_issue.py found %d dependent CLs.' % (
        num_issues_patchsets_to_apply - 1)
    print 'They will be applied in the following order:'
    num = 1
    for issue_to_apply, patchset_to_apply in issues_patchsets_to_apply:
      print '  #%d %s/%d/#ps%d' % (
          num, options.server, issue_to_apply, patchset_to_apply)
      num += 1
    print

  for issue_to_apply, patchset_to_apply in issues_patchsets_to_apply:
    issue_url = '%s/%d/#ps%d' % (options.server, issue_to_apply,
                                 patchset_to_apply)
    print('Downloading patch from %s' % issue_url)
    try:
      patchset = obj.get_patch(issue_to_apply, patchset_to_apply)
    except urllib2.HTTPError as e:
      print(
          'Failed to fetch the patch for issue %d, patchset %d.\n'
          'Try visiting %s/%d') % (
              issue_to_apply, patchset_to_apply,
              options.server, issue_to_apply)
      return 1
    if options.whitelist:
      patchset.patches = [patch for patch in patchset.patches
                          if patch.filename in options.whitelist]
    if options.blacklist:
      patchset.patches = [patch for patch in patchset.patches
                          if patch.filename not in options.blacklist]
    for patch in patchset.patches:
      print(patch)
    full_dir = os.path.abspath(options.root_dir)
    scm_type = scm.determine_scm(full_dir)
    if scm_type == 'svn':
      scm_obj = checkout.SvnCheckout(full_dir, None, None, None, None)
    elif scm_type == 'git':
      scm_obj = checkout.GitCheckout(full_dir, None, None, None, None)
    elif scm_type == None:
      scm_obj = checkout.RawCheckout(full_dir, None, None)
    else:
      parser.error('Couldn\'t determine the scm')

    # TODO(maruel): HACK, remove me.
    # When run a build slave, make sure buildbot knows that the checkout was
    # modified.
    if options.root_dir == 'src' and getpass.getuser() == 'chrome-bot':
      # See sourcedirIsPatched() in:
      # http://src.chromium.org/viewvc/chrome/trunk/tools/build/scripts/slave/
      #    chromium_commands.py?view=markup
      open('.buildbot-patched', 'w').close()

    print('\nApplying the patch from %s' % issue_url)
    try:
      scm_obj.apply_patch(patchset, verbose=True)
    except checkout.PatchApplicationFailed as e:
      print(str(e))
      print('CWD=%s' % os.getcwd())
      print('Checkout path=%s' % scm_obj.project_path)
      return 1

  if ('DEPS' in map(os.path.basename, patchset.filenames)
      and not options.ignore_deps):
    gclient_root = gclient_utils.FindGclientRoot(full_dir)
    if gclient_root and scm_type:
      print(
          'A DEPS file was updated inside a gclient checkout, running gclient '
          'sync.')
      gclient_path = os.path.join(BASE_DIR, 'gclient')
      if sys.platform == 'win32':
        gclient_path += '.bat'
      with annotated_gclient.temp_filename(suffix='gclient') as f:
        cmd = [
            gclient_path, 'sync',
            '--nohooks',
            '--delete_unversioned_trees',
            ]
        if scm_type == 'svn':
          cmd.extend(['--revision', 'BASE'])
        if options.revision_mapping:
          cmd.extend(['--output-json', f])

        retcode = subprocess.call(cmd, cwd=gclient_root)

        if retcode == 0 and options.revision_mapping:
          revisions = annotated_gclient.parse_got_revision(
              f, options.revision_mapping)
          annotated_gclient.emit_buildprops(revisions)

        return retcode
  return 0


if __name__ == "__main__":
  fix_encoding.fix_encoding()
  try:
    sys.exit(main())
  except KeyboardInterrupt:
    sys.stderr.write('interrupted\n')
    sys.exit(1)
