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

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',
                    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('--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('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_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
  if len(args) != 1 and not options.cl and not desugar:
    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

  commit = None if (options.cl or desugar)  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())
