#!/usr/bin/env python3
# Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

# Convenience script for triggering bots on specific commits.

import json
import git_utils
import optparse
import os
import re
import subprocess
import sys
import urllib
from urllib.request import urlopen
import utils

LUCI_SCHEDULE = os.path.join(utils.REPO_ROOT, 'infra', 'config', 'global',
                             'generated', 'luci-scheduler.cfg')
# Trigger lines have the format:
#   triggers: "BUILDER_NAME"
TRIGGERS_RE = r'^  triggers: "(\w.*)"'

DESUGAR_JDK11_BOT = 'lib_desugar-archive-jdk11'
DESUGAR_JDK11_LEGACY_BOT = 'lib_desugar-archive-jdk11-legacy'
DESUGAR_JDK8_BOT = 'lib_desugar-archive-jdk8'
SMALI_BOT = 'smali'

def ParseOptions():
  result = optparse.OptionParser()
  result.add_option('--release',
                    help='Run on the release branch builders.',
                    default=False, action='store_true')
  result.add_option('--cl',
                    metavar=('<url>'),
                    help='Run the specified cl on the bots. This should be '
                    'the full url, e.g., '
                    'https://r8-review.googlesource.com/c/r8/+/37420/1')
  result.add_option('--desugar-jdk11',
                    help='Run the jdk11 library desugar and archiving bot.',
                    default=False, action='store_true')
  result.add_option('--desugar-jdk11-legacy',
                    help='Run the jdk11 legacy library desugar and archiving bot.',
                    default=False, action='store_true')
  result.add_option('--desugar-jdk8',
                    help='Run the jdk8 library desugar and archiving bot.',
                    default=False, action='store_true')
  result.add_option('--smali',
                    metavar=('<version>'),
                    help='Build smali version <version>.')

  result.add_option('--builder', help='Trigger specific builder')
  return result.parse_args()

def get_builders():

  is_release = False
  main_builders = []
  release_builders = []
  with open(LUCI_SCHEDULE, 'r') as fp:
    lines = fp.readlines()
    for line in lines:
      if 'branch-gitiles' in line:
        is_release = True
      if 'main-gitiles-trigger' in line:
        is_release = False
      match = re.match(TRIGGERS_RE, line)
      if match:
        builder = match.group(1)
        if is_release:
          assert 'release' in builder, builder
          release_builders.append(builder)
        else:
          assert 'release' not in builder, builder
          main_builders.append(builder)
  print('Desugar jdk11 builder:\n  ' + DESUGAR_JDK11_BOT)
  print('Desugar jdk11 legacy builder:\n  ' + DESUGAR_JDK11_LEGACY_BOT)
  print('Desugar jdk8 builder:\n  ' + DESUGAR_JDK8_BOT)
  print('Smali builder:\n  ' + SMALI_BOT)
  print('Main builders:\n  ' + '\n  '.join(main_builders))
  print('Release builders:\n  ' + '\n  '.join(release_builders))
  return (main_builders, release_builders)

def sanity_check_url(url):
  a = urlopen(url)
  if a.getcode() != 200:
    raise Exception('Url: %s \n returned %s' % (url, a.getcode()))

def trigger_builders(builders, commit):
  commit_url = 'https://r8.googlesource.com/r8/+/%s' % commit
  sanity_check_url(commit_url)
  for builder in builders:
    cmd = ['bb', 'add', 'r8/ci/%s' % builder , '-commit', commit_url]
    subprocess.check_call(cmd)

def trigger_smali_builder(version):
  utils.check_basic_semver_version(
    version,
    'use semantic version of the smali version to built (pre-releases are not supported)',
    allowPrerelease = False)
  cmd = [
      'bb',
      'add',
      'r8/ci/%s' % SMALI_BOT,
      '-p',
      'test_options=["--version", "%s"]' % version
  ]
  subprocess.check_call(cmd)

def trigger_cl(builders, cl_url):
  for builder in builders:
    cmd = ['bb', 'add', 'r8/ci/%s' % builder , '-cl', cl_url]
    subprocess.check_call(cmd)

def Main():
  (options, args) = ParseOptions()
  desugar = options.desugar_jdk11 or options.desugar_jdk11_legacy or options.desugar_jdk8
  requires_commit = not options.cl and not desugar and not options.smali
  if len(args) != 1 and requires_commit:
    print('Takes exactly one argument, the commit to run')
    return 1

  if options.cl and options.release:
    print('You can\'t run cls on the release bots')
    return 1

  if options.cl and desugar:
    print('You can\'t run cls on the desugar bot')
    return 1

  if options.cl and options.smali:
    print('You can\'t run cls on the smali bot')
    return 1

  if options.smali:
    if not options.release:
      print('Only release versions of smali can be built')
      return 1

    trigger_smali_builder(options.smali)
    return

  commit = None if not requires_commit else args[0]
  (main_builders, release_builders) = get_builders()
  builders = release_builders if options.release else main_builders
  if options.builder:
    builder = options.builder
    assert builder in main_builders or builder in release_builders
    builders = [options.builder]
  if desugar:
    assert options.desugar_jdk11 or options.desugar_jdk11_legacy or options.desugar_jdk8
    if options.desugar_jdk11:
      builders = [DESUGAR_JDK11_BOT]
    elif options.desugar_jdk11_legacy:
      builders = [DESUGAR_JDK11_LEGACY_BOT]
    else:
      builders = [DESUGAR_JDK8_BOT]
    commit = git_utils.GetHeadRevision(utils.REPO_ROOT, use_main=True)
  if options.cl:
    trigger_cl(builders, options.cl)
  else:
    assert commit
    trigger_builders(builders, commit)

if __name__ == '__main__':
  sys.exit(Main())
