#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2019 The ChromiumOS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Performs bisection on LLVM based off a .JSON file."""

from __future__ import print_function

import argparse
import enum
import errno
import json
import os
import subprocess
import sys

import chroot
import get_llvm_hash
import git_llvm_rev
import modify_a_tryjob
import update_chromeos_llvm_hash
import update_tryjob_status


class BisectionExitStatus(enum.Enum):
  """Exit code when performing bisection."""

  # Means that there are no more revisions available to bisect.
  BISECTION_COMPLETE = 126


def GetCommandLineArgs():
  """Parses the command line for the command line arguments."""

  # Default path to the chroot if a path is not specified.
  cros_root = os.path.expanduser('~')
  cros_root = os.path.join(cros_root, 'chromiumos')

  # Create parser and add optional command-line arguments.
  parser = argparse.ArgumentParser(
      description='Bisects LLVM via tracking a JSON file.')

  # Add argument for other change lists that want to run alongside the tryjob
  # which has a change list of updating a package's git hash.
  parser.add_argument(
      '--parallel',
      type=int,
      default=3,
      help='How many tryjobs to create between the last good version and '
      'the first bad version (default: %(default)s)')

  # Add argument for the good LLVM revision for bisection.
  parser.add_argument('--start_rev',
                      required=True,
                      type=int,
                      help='The good revision for the bisection.')

  # Add argument for the bad LLVM revision for bisection.
  parser.add_argument('--end_rev',
                      required=True,
                      type=int,
                      help='The bad revision for the bisection.')

  # Add argument for the absolute path to the file that contains information on
  # the previous tested svn version.
  parser.add_argument(
      '--last_tested',
      required=True,
      help='the absolute path to the file that contains the tryjobs')

  # Add argument for the absolute path to the LLVM source tree.
  parser.add_argument(
      '--src_path',
      help='the path to the LLVM source tree to use (used for retrieving the '
      'git hash of each version between the last good version and first bad '
      'version)')

  # Add argument for other change lists that want to run alongside the tryjob
  # which has a change list of updating a package's git hash.
  parser.add_argument(
      '--extra_change_lists',
      type=int,
      nargs='+',
      help='change lists that would like to be run alongside the change list '
      'of updating the packages')

  # Add argument for custom options for the tryjob.
  parser.add_argument('--options',
                      required=False,
                      nargs='+',
                      help='options to use for the tryjob testing')

  # Add argument for the builder to use for the tryjob.
  parser.add_argument('--builder',
                      required=True,
                      help='builder to use for the tryjob testing')

  # Add argument for the description of the tryjob.
  parser.add_argument('--description',
                      required=False,
                      nargs='+',
                      help='the description of the tryjob')

  # Add argument for a specific chroot path.
  parser.add_argument('--chroot_path',
                      default=cros_root,
                      help='the path to the chroot (default: %(default)s)')

  # Add argument for whether to display command contents to `stdout`.
  parser.add_argument('--verbose',
                      action='store_true',
                      help='display contents of a command to the terminal '
                      '(default: %(default)s)')

  # Add argument for whether to display command contents to `stdout`.
  parser.add_argument('--nocleanup',
                      action='store_false',
                      dest='cleanup',
                      help='Abandon CLs created for bisectoin')

  args_output = parser.parse_args()

  assert args_output.start_rev < args_output.end_rev, (
      'Start revision %d is >= end revision %d' %
      (args_output.start_rev, args_output.end_rev))

  if args_output.last_tested and not args_output.last_tested.endswith('.json'):
    raise ValueError('Filed provided %s does not end in ".json"' %
                     args_output.last_tested)

  return args_output


def GetRemainingRange(start, end, tryjobs):
  """Gets the start and end intervals in 'json_file'.

  Args:
    start: The start version of the bisection provided via the command line.
    end: The end version of the bisection provided via the command line.
    tryjobs: A list of tryjobs where each element is in the following format:
    [
        {[TRYJOB_INFORMATION]},
        {[TRYJOB_INFORMATION]},
        ...,
        {[TRYJOB_INFORMATION]}
    ]

  Returns:
    The new start version and end version for bisection, a set of revisions
    that are 'pending' and a set of revisions that are to be skipped.

  Raises:
    ValueError: The value for 'status' is missing or there is a mismatch
    between 'start' and 'end' compared to the 'start' and 'end' in the JSON
    file.
    AssertionError: The new start version is >= than the new end version.
  """

  if not tryjobs:
    return start, end, {}, {}

  # Verify that each tryjob has a value for the 'status' key.
  for cur_tryjob_dict in tryjobs:
    if not cur_tryjob_dict.get('status', None):
      raise ValueError('"status" is missing or has no value, please '
                       'go to %s and update it' % cur_tryjob_dict['link'])

  all_bad_revisions = [end]
  all_bad_revisions.extend(
      cur_tryjob['rev'] for cur_tryjob in tryjobs
      if cur_tryjob['status'] == update_tryjob_status.TryjobStatus.BAD.value)

  # The minimum value for the 'bad' field in the tryjobs is the new end
  # version.
  bad_rev = min(all_bad_revisions)

  all_good_revisions = [start]
  all_good_revisions.extend(
      cur_tryjob['rev'] for cur_tryjob in tryjobs
      if cur_tryjob['status'] == update_tryjob_status.TryjobStatus.GOOD.value)

  # The maximum value for the 'good' field in the tryjobs is the new start
  # version.
  good_rev = max(all_good_revisions)

  # The good version should always be strictly less than the bad version;
  # otherwise, bisection is broken.
  assert good_rev < bad_rev, ('Bisection is broken because %d (good) is >= '
                              '%d (bad)' % (good_rev, bad_rev))

  # Find all revisions that are 'pending' within 'good_rev' and 'bad_rev'.
  #
  # NOTE: The intent is to not launch tryjobs between 'good_rev' and 'bad_rev'
  # that have already been launched (this set is used when constructing the
  # list of revisions to launch tryjobs for).
  pending_revisions = {
      tryjob['rev']
      for tryjob in tryjobs
      if tryjob['status'] == update_tryjob_status.TryjobStatus.PENDING.value
      and good_rev < tryjob['rev'] < bad_rev
  }

  # Find all revisions that are to be skipped within 'good_rev' and 'bad_rev'.
  #
  # NOTE: The intent is to not launch tryjobs between 'good_rev' and 'bad_rev'
  # that have already been marked as 'skip' (this set is used when constructing
  # the list of revisions to launch tryjobs for).
  skip_revisions = {
      tryjob['rev']
      for tryjob in tryjobs
      if tryjob['status'] == update_tryjob_status.TryjobStatus.SKIP.value
      and good_rev < tryjob['rev'] < bad_rev
  }

  return good_rev, bad_rev, pending_revisions, skip_revisions


def GetCommitsBetween(start, end, parallel, src_path, pending_revisions,
                      skip_revisions):
  """Determines the revisions between start and end."""

  with get_llvm_hash.LLVMHash().CreateTempDirectory() as temp_dir:
    # We have guaranteed contiguous revision numbers after this,
    # and that guarnatee simplifies things considerably, so we don't
    # support anything before it.
    assert start >= git_llvm_rev.base_llvm_revision, f'{start} was too long ago'

    with get_llvm_hash.CreateTempLLVMRepo(temp_dir) as new_repo:
      if not src_path:
        src_path = new_repo
      index_step = (end - (start + 1)) // (parallel + 1)
      if not index_step:
        index_step = 1
      revisions = [
          rev for rev in range(start + 1, end, index_step)
          if rev not in pending_revisions and rev not in skip_revisions
      ]
      git_hashes = [
          get_llvm_hash.GetGitHashFrom(src_path, rev) for rev in revisions
      ]
      return revisions, git_hashes


def Bisect(revisions, git_hashes, bisect_state, last_tested, update_packages,
           chroot_path, patch_metadata_file, extra_change_lists, options,
           builder, verbose):
  """Adds tryjobs and updates the status file with the new tryjobs."""

  try:
    for svn_revision, git_hash in zip(revisions, git_hashes):
      tryjob_dict = modify_a_tryjob.AddTryjob(update_packages, git_hash,
                                              svn_revision, chroot_path,
                                              patch_metadata_file,
                                              extra_change_lists, options,
                                              builder, verbose, svn_revision)

      bisect_state['jobs'].append(tryjob_dict)
  finally:
    # Do not want to lose progress if there is an exception.
    if last_tested:
      new_file = '%s.new' % last_tested
      with open(new_file, 'w') as json_file:
        json.dump(bisect_state, json_file, indent=4, separators=(',', ': '))

      os.rename(new_file, last_tested)


def LoadStatusFile(last_tested, start, end):
  """Loads the status file for bisection."""

  try:
    with open(last_tested) as f:
      return json.load(f)
  except IOError as err:
    if err.errno != errno.ENOENT:
      raise

  return {'start': start, 'end': end, 'jobs': []}


def main(args_output):
  """Bisects LLVM commits.

  Raises:
    AssertionError: The script was run inside the chroot.
  """

  chroot.VerifyOutsideChroot()
  patch_metadata_file = 'PATCHES.json'
  start = args_output.start_rev
  end = args_output.end_rev

  bisect_state = LoadStatusFile(args_output.last_tested, start, end)
  if start != bisect_state['start'] or end != bisect_state['end']:
    raise ValueError(
        f'The start {start} or the end {end} version provided is '
        f'different than "start" {bisect_state["start"]} or "end" '
        f'{bisect_state["end"]} in the .JSON file')

  # Pending and skipped revisions are between 'start_rev' and 'end_rev'.
  start_rev, end_rev, pending_revs, skip_revs = GetRemainingRange(
      start, end, bisect_state['jobs'])

  revisions, git_hashes = GetCommitsBetween(start_rev, end_rev,
                                            args_output.parallel,
                                            args_output.src_path, pending_revs,
                                            skip_revs)

  # No more revisions between 'start_rev' and 'end_rev', so
  # bisection is complete.
  #
  # This is determined by finding all valid revisions between 'start_rev'
  # and 'end_rev' and that are NOT in the 'pending' and 'skipped' set.
  if not revisions:
    if pending_revs:
      # Some tryjobs are not finished which may change the actual bad
      # commit/revision when those tryjobs are finished.
      no_revisions_message = (f'No revisions between start {start_rev} '
                              f'and end {end_rev} to create tryjobs\n')

      if pending_revs:
        no_revisions_message += ('The following tryjobs are pending:\n' +
                                 '\n'.join(str(rev)
                                           for rev in pending_revs) + '\n')

      if skip_revs:
        no_revisions_message += ('The following tryjobs were skipped:\n' +
                                 '\n'.join(str(rev)
                                           for rev in skip_revs) + '\n')

      raise ValueError(no_revisions_message)

    print(f'Finished bisecting for {args_output.last_tested}')
    if args_output.src_path:
      bad_llvm_hash = get_llvm_hash.GetGitHashFrom(args_output.src_path,
                                                   end_rev)
    else:
      bad_llvm_hash = get_llvm_hash.LLVMHash().GetLLVMHash(end_rev)
    print(f'The bad revision is {end_rev} and its commit hash is '
          f'{bad_llvm_hash}')
    if skip_revs:
      skip_revs_message = ('\nThe following revisions were skipped:\n' +
                           '\n'.join(str(rev) for rev in skip_revs))
      print(skip_revs_message)

    if args_output.cleanup:
      # Abandon all the CLs created for bisection
      gerrit = os.path.join(args_output.chroot_path, 'chromite/bin/gerrit')
      for build in bisect_state['jobs']:
        try:
          subprocess.check_output(
              [gerrit, 'abandon', str(build['cl'])],
              stderr=subprocess.STDOUT,
              encoding='utf-8')
        except subprocess.CalledProcessError as err:
          # the CL may have been abandoned
          if 'chromite.lib.gob_util.GOBError' not in err.output:
            raise

    return BisectionExitStatus.BISECTION_COMPLETE.value

  for rev in revisions:
    if update_tryjob_status.FindTryjobIndex(rev,
                                            bisect_state['jobs']) is not None:
      raise ValueError(f'Revision {rev} exists already in "jobs"')

  Bisect(revisions, git_hashes, bisect_state, args_output.last_tested,
         update_chromeos_llvm_hash.DEFAULT_PACKAGES, args_output.chroot_path,
         patch_metadata_file, args_output.extra_change_lists,
         args_output.options, args_output.builder, args_output.verbose)


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