#!/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 git_utils
import optparse
import os
import re
import subprocess
import sys
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 parse_options():
    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, '
                      'or the CL and patch number, e.g., 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')
    (options, args) = result.parse_args()
    if not options.cl.startswith('http'):
        [cl_number, patch_number] = [int(x) for x in options.cl.split('/')]
        options.cl = 'https://r8-review.googlesource.com/c/r8/+/%s/%s' % (
            cl_number, patch_number)
    return (options, 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)
    print(
        "Check that tag %s is created and pushed to the remote (e.g by running"
        % version)
    print()
    print("  git ls-remote origin refs/tags/%s in a smali checkout)" % version)
    print()
    print("in a smali checkout)")
    print()
    answer = input("Is tag %s present? [y/N]:" % version)
    if answer != 'y':
        print('Aborting smali release build')
        sys.exit(1)
    cmd = [
        'bb', 'add',
        'r8/ci/%s' % SMALI_BOT, '-p',
        'test_options=["--version", "%s"]' % version
    ]
    subprocess.check_call(cmd)


def trigger_cl(builders, cl_url):
    # Fixup internal urls to make bb happy.
    fixed_url = cl_url.replace('r8-review.git.corp.google.com',
                               'r8-review.googlesource.com')
    for builder in builders:
        cmd = ['bb', 'add', 'r8/ci/%s' % builder, '-cl', fixed_url]
        subprocess.check_call(cmd)


def main():
    (options, args) = parse_options()
    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 0

    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)
        return 0
    else:
        assert commit
        trigger_builders(builders, commit)
        return 0


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