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

import argparse
import datetime
import os.path
import re
import shutil
import stat
import subprocess
import sys
import urllib.request
import xml.etree.ElementTree
import zipfile

import utils

R8_DEV_BRANCH = '8.6'
R8_VERSION_FILE = os.path.join('src', 'main', 'java', 'com', 'android', 'tools',
                               'r8', 'Version.java')
THIS_FILE_RELATIVE = os.path.join('tools', 'r8_release.py')
GMAVEN_PUBLISHER = '/google/bin/releases/android-devtools/gmaven/publisher/gmaven-publisher'

DESUGAR_JDK_LIBS = 'desugar_jdk_libs'
DESUGAR_JDK_LIBS_CONFIGURATION = DESUGAR_JDK_LIBS + '_configuration'
ANDROID_TOOLS_PACKAGE = 'com.android.tools'

GITHUB_DESUGAR_JDK_LIBS = 'https://github.com/google/desugar_jdk_libs'


def install_gerrit_change_id_hook(checkout_dir):
    with utils.ChangedWorkingDirectory(checkout_dir):
        # Fancy way of getting the string ".git".
        git_dir = subprocess.check_output(['git', 'rev-parse', '--git-dir'
                                          ]).decode('utf-8').strip()
        commit_msg_hooks = '%s/hooks/commit-msg' % git_dir
        if not os.path.exists(os.path.dirname(commit_msg_hooks)):
            os.mkdir(os.path.dirname(commit_msg_hooks))
        # Install commit hook to generate Gerrit 'Change-Id:'.
        urllib.request.urlretrieve(
            'https://gerrit-review.googlesource.com/tools/hooks/commit-msg',
            commit_msg_hooks)
        st = os.stat(commit_msg_hooks)
        os.chmod(commit_msg_hooks,
                 st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)


def checkout_r8(temp, branch):
    subprocess.check_call(['git', 'clone', utils.REPO_SOURCE, temp])
    with utils.ChangedWorkingDirectory(temp):
        subprocess.check_call([
            'git', 'new-branch', '--upstream',
            'origin/%s' % branch, 'dev-release'
        ])
    install_gerrit_change_id_hook(temp)
    return temp


def prepare_release(args):
    if args.version:
        print("Cannot manually specify version when making a dev release.")
        sys.exit(1)

    def make_release(args):
        commithash = args.dev_release

        with utils.TempDir() as temp:
            with utils.ChangedWorkingDirectory(checkout_r8(temp,
                                                           R8_DEV_BRANCH)):
                # Compute the current and new version on the branch.
                result = None
                for line in open(R8_VERSION_FILE, 'r'):
                    result = re.match(
                        r'.*LABEL = "%s\.(\d+)\-dev";' % R8_DEV_BRANCH, line)
                    if result:
                        break
                if not result or not result.group(1):
                    print('Failed to find version label matching %s(\d+)-dev'\
                          % R8_DEV_BRANCH)
                    sys.exit(1)
                try:
                    patch_version = int(result.group(1))
                except ValueError:
                    print('Failed to convert version to integer: %s' %
                          result.group(1))

                old_version = '%s.%s-dev' % (R8_DEV_BRANCH, patch_version)
                version = '%s.%s-dev' % (R8_DEV_BRANCH, patch_version + 1)

                # Verify that the merge point from main is not empty.
                merge_diff_output = subprocess.check_output(
                    ['git', 'diff', 'HEAD..%s' % commithash]).decode('utf-8')
                other_diff = version_change_diff(merge_diff_output, old_version,
                                                 "main")
                if not other_diff:
                    print('Merge point from main (%s)' % commithash, \
                      'is the same as exiting release (%s).' % old_version)
                    sys.exit(1)

                if args.dev_pre_cherry_pick:
                    for pre_commit in args.dev_pre_cherry_pick:
                        subprocess.check_call(
                            ['git', 'cherry-pick', '--no-edit', pre_commit])

                # Merge the desired commit from main on to the branch.
                subprocess.check_call(
                    ['git', 'merge', '--no-ff', '--no-edit', commithash])

                # Rewrite the version, commit and validate.
                sed(old_version, version, R8_VERSION_FILE)

                subprocess.check_call(
                    ['git', 'commit', '-a', '-m',
                     'Version %s' % version])

                version_diff_output = subprocess.check_output(
                    ['git', 'diff', '%s..HEAD' % commithash]).decode('utf-8')

                validate_version_change_diff(version_diff_output, "main",
                                             version)

                cmd = ['git', 'cl', 'upload', '--no-squash', '--bypass-hooks']
                maybe_check_call(args, cmd)

                if args.dry_run:
                    input(
                        'DryRun: check %s for content of version %s [enter to continue]:'
                        % (temp, version))

                return "%s dev version %s from hash %s for review" % (
                    'DryRun: omitted upload of' if args.dry_run else 'Uploaded',
                    version, commithash)

    return make_release


def maybe_tag(args, version):
    maybe_check_call(args,
                     ['git', 'tag', '-a', version, '-m',
                      '"%s"' % version])
    maybe_check_call(args, ['git', 'push', 'origin', 'refs/tags/%s' % version])


def version_change_diff(diff, old_version, new_version):
    invalid_line = None
    for line in str(diff).splitlines():
        if line.startswith('-  ') and \
            line != '-  public static final String LABEL = "%s";' % old_version:
            invalid_line = line
        elif line.startswith('+  ') and \
            line != '+  public static final String LABEL = "%s";' % new_version:
            invalid_line = line
    return invalid_line


def validate_version_change_diff(version_diff_output, old_version, new_version):
    invalid = version_change_diff(version_diff_output, old_version, new_version)
    if invalid:
        print("Unexpected diff:")
        print("=" * 80)
        print(version_diff_output)
        print("=" * 80)
        accept_string = 'THE DIFF IS OK!'
        answer = input("Accept the additonal diff as part of the release? "
                       "Type '%s' to accept: " % accept_string)
        if answer != accept_string:
            print("You did not type '%s'" % accept_string)
            print('Aborting dev release for %s' % version)
            sys.exit(1)


def maybe_check_call(args, cmd):
    if args.dry_run:
        print('DryRun:', ' '.join(cmd))
    else:
        print(' '.join(cmd))
        return subprocess.check_call(cmd)


def update_prebuilds(r8_checkout, version, checkout, keepanno=False):
    path = os.path.join(r8_checkout, 'tools', 'update_prebuilds_in_android.py')
    commit_arg = '--commit_hash=' if len(version) == 40 else '--version='
    cmd = [path, '--targets=lib', '--maps', commit_arg + version, checkout]
    if keepanno:
        cmd.append("--keepanno")
    subprocess.check_call(cmd)


def release_studio_or_aosp(r8_checkout,
                           path,
                           options,
                           git_message,
                           keepanno=False):
    with utils.ChangedWorkingDirectory(path):
        if not options.use_existing_work_branch:
            subprocess.call(['repo', 'abandon', 'update-r8'])
        if not options.no_sync:
            subprocess.check_call(['repo', 'sync', '-cq', '-j', '16'])

        prebuilts_r8 = os.path.join(path, 'prebuilts', 'r8')

        if not options.use_existing_work_branch:
            with utils.ChangedWorkingDirectory(prebuilts_r8):
                subprocess.check_call(['repo', 'start', 'update-r8'])

        update_prebuilds(r8_checkout, options.version, path, keepanno)

        with utils.ChangedWorkingDirectory(prebuilts_r8):
            if not options.use_existing_work_branch:
                subprocess.check_call(
                    ['git', 'commit', '-a', '-m', git_message])
            else:
                print('Not committing when --use-existing-work-branch. ' +
                      'Commit message should be:\n\n' + git_message + '\n')
            # Don't upload if requested not to, or if changes are not committed due
            # to --use-existing-work-branch
            if not options.no_upload and not options.use_existing_work_branch:
                process = subprocess.Popen(
                    ['repo', 'upload', '.', '--verify', '--current-branch'],
                    stdin=subprocess.PIPE)
                return process.communicate(input=b'y\n')[0]


def prepare_aosp(args):
    assert args.version

    if (not args.legacy_release):
        print("Please use the new release process, see go/r8-release-prebuilts. "
            + "If for some reason the legacy release process is needed "
            + "pass --legacy-release")
        sys.exit(1)

    assert os.path.exists(args.aosp), "Could not find AOSP path %s" % args.aosp

    def release_aosp(options):
        print("Releasing for AOSP")
        if options.dry_run:
            return 'DryRun: omitting AOSP release for %s' % options.version

        git_message = ("""Update D8 and R8 to %s

Version: %s
This build IS NOT suitable for preview or public release.

Built here: go/r8-releases/raw/%s

Test: TARGET_PRODUCT=aosp_arm64 m -j core-oj""" %
                       (args.version, args.version, args.version))
        # Fixes to Android U branch is based of 8.2.2-dev where the keepanno library
        # is not built.
        keepanno = not args.version.startswith('8.2.2-udc')
        return release_studio_or_aosp(utils.REPO_ROOT,
                                      args.aosp,
                                      options,
                                      git_message,
                                      keepanno=keepanno)

    return release_aosp


def prepare_maven(args):
    assert args.version

    def release_maven(options):
        gfile = '/bigstore/r8-releases/raw/%s/r8lib.zip' % args.version
        release_id = gmaven_publisher_stage(options, [gfile])

        print("Staged Release ID " + release_id + ".\n")
        gmaven_publisher_stage_redir_test_info(
            release_id, "com.android.tools:r8:%s" % args.version, "r8lib.jar")

        print
        answer = input("Continue with publishing [y/N]:")

        if answer != 'y':
            print('Aborting release to Google maven')
            sys.exit(1)

        gmaven_publisher_publish(args, release_id)

        print("")
        print("Published. Use the email workflow for approval.")

    return release_maven


# ------------------------------------------------------ column 70 --v
def git_message_dev(version, bugs):
    return """Update D8 R8 to %s

This is a development snapshot, it's fine to use for studio canary
build, but not for BETA or release, for those we would need a release
version of R8 binaries. This build IS suitable for preview release
but IS NOT suitable for public release.

Built here: go/r8-releases/raw/%s
Test: ./gradlew check
Bug: %s""" % (version, version, '\nBug: '.join(map(bug_fmt, bugs)))


def git_message_release(version, bugs):
    return """D8 R8 version %s

Built here: go/r8-releases/raw/%s/
Test: ./gradlew check

Bug: %s""" % (version, version, '\nBug: '.join(map(bug_fmt, bugs)))


def bug_fmt(bug):
    return "b/%s" % bug


def prepare_studio(args):
    assert args.version
    assert os.path.exists(args.studio), ("Could not find STUDIO path %s" %
                                         args.studio)
    if (not args.legacy_release):
        print("Please use the new release process, see go/r8-release-prebuilts. "
            + "If for some reason the legacy release process is needed "
            + "pass --legacy-release")
        sys.exit(1)

    def release_studio(options):
        print("Releasing for STUDIO")
        if options.dry_run:
            return 'DryRun: omitting studio release for %s' % options.version

        if 'dev' in options.version:
            git_message = git_message_dev(options.version, options.bug)
            r8_checkout = utils.REPO_ROOT
            return release_studio_or_aosp(r8_checkout, args.studio, options,
                                          git_message)
        else:
            with utils.TempDir() as temp:
                checkout_r8(temp,
                            options.version[0:options.version.rindex('.')])
                git_message = git_message_release(options.version, options.bug)
                return release_studio_or_aosp(temp, args.studio, options,
                                              git_message)

    return release_studio


def g4_cp(old, new, file):
    subprocess.check_call('g4 cp {%s,%s}/%s' % (old, new, file), shell=True)


def g4_open(file):
    if not os.access(file, os.W_OK):
        subprocess.check_call('g4 open %s' % file, shell=True)


def g4_change(version):
    message = f'Update R8 to {version}'
    if version == 'main':
        message = f'DO NOT SUBMIT: {message}'
    return subprocess.check_output(
        f'g4 change --desc "{message}\n"',
        shell=True).decode('utf-8')


def get_cl_id(c4_change_output):
    startIndex = c4_change_output.find('Change ') + len('Change ')
    endIndex = c4_change_output.find(' ', startIndex)
    cl = c4_change_output[startIndex:endIndex]
    assert cl.isdigit()
    return cl


def sed(pattern, replace, path):
    with open(path, "r") as sources:
        lines = sources.readlines()
    with open(path, "w") as sources:
        for line in lines:
            sources.write(re.sub(pattern, replace, line))

def download_file(version, file, dst):
    if version == 'main':
        src = os.path.join(utils.LIBS, file)
        if os.path.exists(src):
            shutil.copyfile(src, dst)
        else:
            print(f"WARNING: no file found for {src}. Skipping.")
        return
    dir = 'raw' if len(version) != 40 else 'raw/main'
    urllib.request.urlretrieve(
        ('https://storage.googleapis.com/r8-releases/%s/%s/%s' %
         (dir, version, file)), dst)


def download_gfile(gfile, dst):
    if not gfile.startswith('/bigstore/r8-releases'):
        print('Unexpected gfile prefix for %s' % gfile)
        sys.exit(1)

    urllib.request.urlretrieve(
        'https://storage.googleapis.com/%s' % gfile[len('/bigstore/'):], dst)


def blaze_run(target):
    return subprocess.check_output('blaze run %s' % target,
                                   shell=True,
                                   stderr=subprocess.STDOUT).decode('utf-8')


def prepare_google3(args):
    assert args.version
    # Check if an existing client exists.
    if not args.use_existing_work_branch:
        check_no_google3_client(args, args.p4_client)

    def release_google3(options):
        print("Releasing for Google 3")
        if options.dry_run:
            return 'DryRun: omitting g3 release for %s' % options.version

        google3_base = subprocess.check_output(
            ['p4', 'g4d', '-f', args.p4_client]).decode('utf-8').rstrip()
        third_party_r8 = os.path.join(google3_base, 'third_party', 'java', 'r8')
        today = datetime.date.today()
        with utils.ChangedWorkingDirectory(third_party_r8):
            # download files
            g4_open('full.jar')
            g4_open('src.jar')
            g4_open('lib.jar')
            g4_open('lib.jar.map')
            g4_open('desugar_jdk_libs_configuration.jar')
            g4_open('threading-module-blocking.jar')
            g4_open('threading-module-single-threaded.jar')
            download_file(options.version,
                          'r8-full-exclude-deps.jar',
                          'full.jar')
            download_file(options.version,
                          'r8-src.jar',
                          'src.jar')
            download_file(options.version,
                          'r8lib-exclude-deps.jar',
                          'lib.jar')
            download_file(options.version,
                          'r8lib-exclude-deps.jar.map',
                          'lib.jar.map')
            download_file(options.version,
                          'desugar_jdk_libs_configuration.jar',
                          'desugar_jdk_libs_configuration.jar')
            download_file(options.version,
                          'threading-module-blocking.jar',
                          'threading-module-blocking.jar')
            download_file(options.version,
                          'threading-module-single-threaded.jar',
                          'threading-module-single-threaded.jar')
            if options.version != 'main':
                g4_open('METADATA')
                metadata_path = os.path.join(third_party_r8, 'METADATA')
                match_count = 0
                match_count_expected = 10
                version_match_regexp = r'[1-9]\.[0-9]{1,2}\.[0-9]{1,3}-dev'
                for line in open(metadata_path, 'r'):
                    result = re.search(version_match_regexp, line)
                    if result:
                        match_count = match_count + 1
                if match_count != match_count_expected:
                    print(f"""WARNING:
                    Could not find the previous -dev release string to replace in METADATA.
                    Expected to find it mentioned {match_count_expected} times, but found
                    {match_count} occurrences. Please update {metadata_path} manually and
                    run again with options --google3 --use-existing-work-branch.
                    """)
                    sys.exit(1)
                sed(version_match_regexp, options.version, metadata_path)
                sed(r'\{ year.*\}',
                    f'{{ year: {today.year} month: {today.month} day: {today.day} }}',
                    metadata_path)
            subprocess.check_output('chmod u+w *', shell=True)

        with utils.ChangedWorkingDirectory(google3_base):
            blaze_result = blaze_run('//third_party/java/r8:d8 -- --version')

            assert options.version in blaze_result

            if not options.no_upload:
                change_result = g4_change(options.version)
                change_result += 'Run \'(g4d ' + args.p4_client \
                                 + ' && tap_presubmit -p all --train -c ' \
                                 + get_cl_id(change_result) + ')\' for running TAP global' \
                                 + ' presubmit using the train.\n' \
                                 + 'Run \'(g4d ' + args.p4_client \
                                 + ' && tap_presubmit -p all --notrain --detach --email' \
                                 + ' --skip_flaky_targets --skip_already_failing -c ' \
                                 + get_cl_id(change_result) + ')\' for running an isolated' \
                                 + ' TAP global presubmit.'
                return change_result

    return release_google3


def update_desugar_library_in_studio(args):
    assert os.path.exists(args.studio), ("Could not find STUDIO path %s" %
                                         args.studio)

    def make_release(args):
        library_version = args.update_desugar_library_in_studio[0]
        configuration_version = args.update_desugar_library_in_studio[1]
        change_name = 'update-desugar-library-dependencies'

        with utils.ChangedWorkingDirectory(args.studio):
            if not args.use_existing_work_branch:
                subprocess.call(['repo', 'abandon', change_name])
            if not args.no_sync:
                subprocess.check_call(['repo', 'sync', '-cq', '-j', '16'])

            cmd = [
                'tools/base/bazel/bazel', 'run',
                '//tools/base/bazel:add_dependency', '--',
                '--repo=https://maven.google.com com.android.tools:desugar_jdk_libs:%s'
                % library_version
            ]
            utils.PrintCmd(cmd)
            subprocess.check_call(" ".join(cmd), shell=True)
            cmd = ['tools/base/bazel/bazel', 'shutdown']
            utils.PrintCmd(cmd)
            subprocess.check_call(cmd)

        prebuilts_tools = os.path.join(args.studio, 'prebuilts', 'tools')
        with utils.ChangedWorkingDirectory(prebuilts_tools):
            if not args.use_existing_work_branch:
                with utils.ChangedWorkingDirectory(prebuilts_tools):
                    subprocess.check_call(['repo', 'start', change_name])
            m2_dir = os.path.join('common', 'm2', 'repository', 'com',
                                  'android', 'tools')
            subprocess.check_call([
                'git', 'add',
                os.path.join(m2_dir, DESUGAR_JDK_LIBS, library_version)
            ])
            subprocess.check_call([
                'git', 'add',
                os.path.join(m2_dir, DESUGAR_JDK_LIBS_CONFIGURATION,
                             configuration_version)
            ])

            git_message = ("""Update library desugaring dependencies

  com.android.tools:desugar_jdk_libs:%s
  com.android.tools:desugar_jdk_libs_configuration:%s

Bug: %s
Test: L8ToolTest, L8DexDesugarTest""" %
                           (library_version, configuration_version,
                            '\nBug: '.join(map(bug_fmt, args.bug))))

            if not args.use_existing_work_branch:
                subprocess.check_call(
                    ['git', 'commit', '-a', '-m', git_message])
            else:
                print('Not committing when --use-existing-work-branch. ' +
                      'Commit message should be:\n\n' + git_message + '\n')
            # Don't upload if requested not to, or if changes are not committed due
            # to --use-existing-work-branch
            if not args.no_upload and not args.use_existing_work_branch:
                process = subprocess.Popen(['repo', 'upload', '.', '--verify'],
                                           stdin=subprocess.PIPE)
                return process.communicate(input='y\n')[0]

    return make_release


def prepare_desugar_library(args):

    def make_release(args):
        library_version = args.desugar_library[0]
        configuration_version = args.desugar_library[1]

        # TODO(b/237636871): Cleanup and generalize.
        if (not (library_version.startswith('1.1') or
                 library_version.startswith('1.2') or
                 library_version.startswith('2.0'))):
            print(
                "Release script does not support desugared library version %s" %
                library_version)
            sys.exit(1)

        postfixes = ['']
        if library_version.startswith('1.2'):
            postfixes = ['_legacy']
        if library_version.startswith('2.0'):
            postfixes = ['_minimal', '', '_nio']

        with utils.TempDir() as temp:
            with utils.ChangedWorkingDirectory(temp):
                artifacts = []
                for postfix in postfixes:
                    group_postfix = ('' if postfix == '_legacy' else postfix)
                    archive_postfix = (postfix
                                       if library_version.startswith('1.1') else
                                       '_jdk11' + postfix)
                    library_jar = DESUGAR_JDK_LIBS + postfix + '.jar'
                    library_archive = DESUGAR_JDK_LIBS + archive_postfix + '.zip'
                    configuration_archive = DESUGAR_JDK_LIBS_CONFIGURATION + archive_postfix + '.zip'
                    library_gfile = ('/bigstore/r8-releases/raw/%s/%s/%s' %
                                     (DESUGAR_JDK_LIBS + group_postfix,
                                      library_version, library_archive))
                    configuration_gfile = (
                        '/bigstore/r8-releases/raw/main/%s/%s' %
                        (configuration_version, configuration_archive))

                    download_gfile(library_gfile, library_archive)
                    download_gfile(configuration_gfile, configuration_archive)
                    check_configuration(configuration_archive, group_postfix)
                    artifacts.append(library_gfile)
                    artifacts.append(configuration_gfile)

                release_id = gmaven_publisher_stage(args, artifacts)

                print("Staged Release ID " + release_id + ".\n")
                library_artifact_id = \
                    '%s:%s:%s' % (ANDROID_TOOLS_PACKAGE, DESUGAR_JDK_LIBS, library_version)
                gmaven_publisher_stage_redir_test_info(release_id,
                                                       library_artifact_id,
                                                       library_jar)

                print("")
                answer = input("Continue with publishing [y/N]:")

                if answer != 'y':
                    print('Aborting release to Google maven')
                    sys.exit(1)

                gmaven_publisher_publish(args, release_id)

                print("")
                print("Published. Use the email workflow for approval.")

    return make_release


def check_configuration(configuration_archive, postfix):
    zip = zipfile.ZipFile(configuration_archive)
    zip.extractall()
    dirs = os.listdir(
        os.path.join('com', 'android', 'tools',
                     DESUGAR_JDK_LIBS_CONFIGURATION + postfix))
    if len(dirs) != 1:
        print('Unexpected archive content, %s' + dirs)
        sys.exit(1)

    version = dirs[0]
    pom_file = os.path.join(
        'com', 'android', 'tools', DESUGAR_JDK_LIBS_CONFIGURATION + postfix,
        version,
        '%s-%s.pom' % (DESUGAR_JDK_LIBS_CONFIGURATION + postfix, version))
    version_from_pom = extract_version_from_pom(pom_file)
    if version != version_from_pom:
        print('Version mismatch, %s != %s' % (version, version_from_pom))
        sys.exit(1)


def check_no_google3_client(args, client_name):
    if not args.use_existing_work_branch:
        clients = subprocess.check_output('g4 myclients',
                                          shell=True).decode('utf-8')
        if ':%s:' % client_name in clients:
            if args.delete_work_branch:
                subprocess.check_call('g4 citc -d -f %s' % client_name,
                                      shell=True)
            else:
                print(("Remove the existing '%s' client before continuing " +
                       "(force delete: 'g4 citc -d -f %s'), " +
                       "or use either --use-existing-work-branch or " +
                       "--delete-work-branch.") % (client_name, client_name))
                sys.exit(1)


def extract_version_from_pom(pom_file):
    ns = "http://maven.apache.org/POM/4.0.0"
    xml.etree.ElementTree.register_namespace('', ns)
    tree = xml.etree.ElementTree.ElementTree()
    tree.parse(pom_file)
    return tree.getroot().find("{%s}version" % ns).text


GMAVEN_PUBLISH_STAGE_RELEASE_ID_PATTERN = re.compile(
    'Release ID = ([0-9a-f\-]+)')


def gmaven_publisher_stage(args, gfiles):
    if args.dry_run:
        print('Dry-run, would have staged %s' % gfiles)
        return 'dry-run-release-id'

    print("Staging: %s" % ', '.join(gfiles))
    print("")

    cmd = [GMAVEN_PUBLISHER, 'stage', '--gfile', ','.join(gfiles)]
    output = subprocess.check_output(cmd)

    # Expect output to contain:
    # [INFO] 06/19/2020 09:35:12 CEST: >>>>>>>>>> Staged
    # [INFO] 06/19/2020 09:35:12 CEST: Release ID = 9171d015-18f6-4a90-9984-1c362589dc1b
    # [INFO] 06/19/2020 09:35:12 CEST: Stage Path = /bigstore/studio_staging/maven2/sgjesse/9171d015-18f6-4a90-9984-1c362589dc1b

    matches = GMAVEN_PUBLISH_STAGE_RELEASE_ID_PATTERN.findall(
        output.decode("utf-8"))
    if matches == None or len(matches) > 1:
        print("Could not determine the release ID from the gmaven_publisher " +
              "output. Expected a line with 'Release ID = <release id>'.")
        print("Output was:")
        print(output)
        sys.exit(1)

    print(output)

    release_id = matches[0]
    return release_id


def gmaven_publisher_stage_redir_test_info(release_id, artifact, dst):

    redir_command = ("/google/data/ro/teams/android-devtools-infra/tools/redir "
                     + "--alsologtostderr " +
                     "--gcs_bucket_path=/bigstore/gmaven-staging/${USER}/%s " +
                     "--port=1480") % release_id

    get_command = (
        "mvn org.apache.maven.plugins:maven-dependency-plugin:2.4:get " +
        "-Dmaven.repo.local=/tmp/maven_repo_local " +
        "-DremoteRepositories=http://localhost:1480 " + "-Dartifact=%s " +
        "-Ddest=%s") % (artifact, dst)

    print("""To test the staged content with 'redir' run:

%s

Then add the following repository to settings.gradle.kts (Kotlin Script) to
search the 'redir' repository:

dependencyResolutionManagement {
  repositories {
    maven {
      url = uri("http://localhost:1480")
      isAllowInsecureProtocol = true
    }
  }
}

or the following to settings.gradle (Groovy);

dependencyResolutionManagement {
  repositories {
    maven {
      url 'http://localhost:1480'
      allowInsecureProtocol true
    }
  }
}

and add the following repository to gradle.build.kts (Kotlin Script) for the
staged version:

coreLibraryDesugaring("%s") {
  isChanging = true
}

or the following to settings.gradle (Groovy);

dependencies {
  coreLibraryDesugaring('%s') {
    changing = true
  }
}

Use this commands to get artifact from 'redir':

rm -rf /tmp/maven_repo_local
%s
""" % (redir_command, artifact, artifact, get_command))


def gmaven_publisher_publish(args, release_id):
    if args.dry_run:
        print('Dry-run, would have published %s' % release_id)
        return

    cmd = [GMAVEN_PUBLISHER, 'publish', release_id]
    output = subprocess.check_output(cmd)


def branch_change_diff(diff, old_version, new_version):
    invalid_line = None
    for line in str(diff).splitlines():
        if line.startswith('-R8') and \
            line != "-R8_DEV_BRANCH = '%s'" % old_version:
            print(line)
            invalid_line = line
        elif line.startswith('+R8') and \
            line != "+R8_DEV_BRANCH = '%s'" % new_version:
            print(line)
            invalid_line = line
    return invalid_line


def validate_branch_change_diff(version_diff_output, old_version, new_version):
    invalid = branch_change_diff(version_diff_output, old_version, new_version)
    if invalid:
        print("")
        print(
            "The diff for the branch change in tools/release.py is not as expected:"
        )
        print("")
        print("=" * 80)
        print(version_diff_output)
        print("=" * 80)
        print("")
        print("Validate the uploaded CL before landing.")
        print("")


def prepare_branch(args):
    if (len(args.new_dev_branch) < 1 or len(args.new_dev_branch) > 2):
        print("One or two arguments required for --new-dev-branch")
        sys.exit(1)
    branch_version = args.new_dev_branch[0]

    current_semver = utils.check_basic_semver_version(
        R8_DEV_BRANCH, ", current release branch version should be x.y", 2)
    semver = utils.check_basic_semver_version(
        branch_version, ", release branch version should be x.y", 2)
    if not semver.larger_than(current_semver):
        print('New branch version "' + branch_version +
              '" must be strictly larger than the current "' + R8_DEV_BRANCH +
              '"')
        sys.exit(1)

    def make_branch(options):
        with utils.TempDir() as temp:
            subprocess.check_call(['git', 'clone', utils.REPO_SOURCE, temp])
            with utils.ChangedWorkingDirectory(temp):
                if len(options.new_dev_branch) == 1:
                    # Calculate the usual branch hash.
                    subprocess.check_call(['git',  'fetch', 'origin', R8_DEV_BRANCH])
                    hashes = subprocess.check_output(
                      ['git',
                      'show',
                      '-s',
                      '--pretty=%P',
                      'origin/%s~1' % R8_DEV_BRANCH]).decode('utf-8').strip()
                    if (len(hashes.split()) != 2):
                        print('Expected two parent hashes for commit origin/%s~1'
                            % R8_DEV_BRANCH)
                        sys.exit(0)
                    commithash = hashes.split()[1]
                    print()
                    print('Calculated branch hash: %s' % commithash)
                    print('Please double check that this is the correct branch hash. It'
                        ' is obtained as the second parent of origin/%s~1.' % R8_DEV_BRANCH)
                    print('If not rerun the script passing an explicit hash to branch from.')
                else:
                    commithash = options.new_dev_branch[1]
                    print()
                    print('Using explicit branch hash %s' % commithash)
                print()
                print('Use the Gerrit admin UI at'
                     ' https://r8-review.googlesource.com/admin/repos/r8,branches'
                     ' to create the %s branch from %s.' % (branch_version, commithash))
                answer = input("Branch created in Gerrit UI? [y/N]:")
                if answer != 'y':
                    print('Aborting preparing branch for %s' % branch_version)
                    sys.exit(1)

                # Fetch and checkout the new branch created through the Gerrit UI.
                subprocess.check_call(['git',  'fetch', 'origin', branch_version])
                subprocess.check_call(['git', 'checkout', branch_version])

                # Rewrite the version on the branch, commit and validate.
                old_version = 'main'
                full_version = branch_version + '.0-dev'
                version_prefix = 'public static final String LABEL = "'
                sed(version_prefix + old_version, version_prefix + full_version,
                    R8_VERSION_FILE)

                subprocess.check_call(
                    ['git', 'commit', '-a', '-m',
                     'Version %s' % full_version])

                version_diff_output = subprocess.check_output(
                    ['git', 'diff', '%s..HEAD' % commithash])

                validate_version_change_diff(version_diff_output, old_version,
                                             full_version)

                if options.dry_run:
                    input(
                        'DryRun: check %s for content of version %s [enter to continue]:'
                        % (temp, branch_version))

                # Double check that we want to create a new release branch.
                if not options.dry_run:
                    answer = input('Continue with branch for %s [y/N]:' %
                                   branch_version)
                    if answer != 'y':
                        print('Aborting preparing branch for %s' % branch_version)
                        sys.exit(1)

                maybe_check_call(
                    options,
                    ['git', 'cl', 'upload', '--bypass-hooks'])

                print(
                    'Updating tools/r8_release.py to make new dev releases on %s'
                    % branch_version)

                subprocess.check_call(
                    ['git', 'new-branch', 'update-release-script'])

                # Check this file for the setting of the current dev branch.
                result = None
                for line in open(THIS_FILE_RELATIVE, 'r'):
                    result = re.match(r"^R8_DEV_BRANCH = '(\d+).(\d+)'", line)
                    if result:
                        break
                if not result or not result.group(1):
                    print('Failed to find version label in %s' %
                          THIS_FILE_RELATIVE)
                    sys.exit(1)

                # Update this file with the new dev branch.
                sed(
                    "R8_DEV_BRANCH = '%s.%s" %
                    (result.group(1), result.group(2)),
                    "R8_DEV_BRANCH = '%s.%s" %
                    (str(semver.major), str(semver.minor)), THIS_FILE_RELATIVE)

                message = \
                    'Prepare %s for branch %s' % (THIS_FILE_RELATIVE, branch_version)
                subprocess.check_call(['git', 'commit', '-a', '-m', message])

                branch_diff_output = subprocess.check_output(
                    ['git', 'diff', 'HEAD~'])

                validate_branch_change_diff(branch_diff_output, R8_DEV_BRANCH,
                                            branch_version)

                if options.dry_run:
                    input(
                        'DryRun: check %s for content of version main [enter to continue]:'
                        % temp)

                maybe_check_call(options,
                                 ['git', 'cl', 'upload', '-f', '-m', message])

                print('')
                print('Make sure to send out the two branch change CL for review'
                      ' (on %s and main).' % branch_version)
                print('')

    return make_branch


def parse_options():
    result = argparse.ArgumentParser(description='Release r8')
    group = result.add_mutually_exclusive_group()
    group.add_argument('--dev-release',
                       metavar=('<main hash>'),
                       help='The hash to use for the new dev version of R8')
    group.add_argument(
        '--version',
        metavar=('<version>'),
        help=
        'The new version of R8 (e.g., 1.4.51) to release to selected channels')
    group.add_argument(
        '--desugar-library',
        nargs=2,
        metavar=('<version>', '<configuration hash>'),
        help='The new version of com.android.tools:desugar_jdk_libs')
    group.add_argument(
        '--update-desugar-library-in-studio',
        nargs=2,
        metavar=('<version>', '<configuration version>'),
        help='Update studio mirror of com.android.tools:desugar_jdk_libs')
    group.add_argument(
        '--new-dev-branch',
        nargs='+',
        metavar=('<version>', '<branch hash>'),
        help=('Prepare new branch for a version line (e.g. 8.0)'
             ' Suggested branch hash is calculated '
             ' if not explicitly specified'))
    result.add_argument('--dev-pre-cherry-pick',
                        metavar=('<main hash(s)>'),
                        default=[],
                        action='append',
                        help='List of commits to cherry pick before doing full '
                        'merge, mostly used for reverting cherry picks')
    result.add_argument('--no-sync',
                        '--no_sync',
                        default=False,
                        action='store_true',
                        help='Do not sync repos before uploading')
    result.add_argument('--bug',
                        metavar=('<bug(s)>'),
                        default=[],
                        action='append',
                        help='List of bugs for release version')
    result.add_argument('--no-bugs',
                        default=False,
                        action='store_true',
                        help='Allow Studio release without specifying any bugs')
    result.add_argument(
        '--studio',
        metavar=('<path>'),
        help='Release for studio by setting the path to a studio '
        'checkout')
    result.add_argument('--legacy-release',
                        default=False,
                        action='store_true',
                        help='Allow Studio/AOSP release using the legacy process')
    result.add_argument('--aosp',
                        metavar=('<path>'),
                        help='Release for aosp by setting the path to the '
                        'checkout')
    result.add_argument('--maven',
                        default=False,
                        action='store_true',
                        help='Release to Google Maven')
    result.add_argument('--google3',
                        default=False,
                        action='store_true',
                        help='Release for google 3')
    result.add_argument('--p4-client',
                        default='update-r8',
                        metavar=('<client name>'),
                        help='P4 client name for google 3')
    result.add_argument(
        '--use-existing-work-branch',
        '--use_existing_work_branch',
        default=False,
        action='store_true',
        help='Use existing work branch/CL in aosp/studio/google3')
    result.add_argument('--delete-work-branch',
                        '--delete_work_branch',
                        default=False,
                        action='store_true',
                        help='Delete CL in google3')
    result.add_argument('--bypass-hooks',
                        '--bypass_hooks',
                        default=False,
                        action='store_true',
                        help="Bypass hooks when uploading")
    result.add_argument('--no-upload',
                        '--no_upload',
                        default=False,
                        action='store_true',
                        help="Don't upload for code review")
    result.add_argument(
        '--dry-run',
        default=False,
        action='store_true',
        help='Only perform non-commiting tasks and print others.')
    result.add_argument('--dry-run-output',
                        '--dry_run_output',
                        default=os.getcwd(),
                        metavar=('<path>'),
                        help='Location for dry run output.')
    args = result.parse_args()
    if (len(args.bug) > 0 and args.no_bugs):
        print("Use of '--bug' and '--no-bugs' are mutually exclusive")
        sys.exit(1)

    if (args.studio and args.version and not 'dev' in args.version and
            args.bug == [] and not args.no_bugs):
        print("When releasing a release version to Android Studio add the " +
              "list of bugs by using '--bug'")
        sys.exit(1)

    if args.version and not 'dev' in args.version and args.google3:
        print("WARNING: You should not roll a release version into google 3")

    return args


def main():
    args = parse_options()
    targets_to_run = []

    if args.new_dev_branch:
        if args.google3 or args.studio or args.aosp:
            print('Cannot create a branch and roll at the same time.')
            sys.exit(1)
        targets_to_run.append(prepare_branch(args))

    if args.dev_release:
        if args.google3 or args.studio or args.aosp:
            print('Cannot create a dev release and roll at the same time.')
            sys.exit(1)
        targets_to_run.append(prepare_release(args))

    utils.check_gcert()

    if args.google3:
        targets_to_run.append(prepare_google3(args))
    if args.studio and not args.update_desugar_library_in_studio:
        targets_to_run.append(prepare_studio(args))
    if args.aosp:
        targets_to_run.append(prepare_aosp(args))
    if args.maven:
        targets_to_run.append(prepare_maven(args))

    if args.desugar_library:
        targets_to_run.append(prepare_desugar_library(args))

    if args.update_desugar_library_in_studio:
        if not args.studio:
            print("--studio required")
            sys.exit(1)
        if args.bug == []:
            print(
                "Update studio mirror of com.android.tools:desugar_jdk_libs " +
                "requires at least one bug by using '--bug'")
            sys.exit(1)
        targets_to_run.append(update_desugar_library_in_studio(args))

    final_results = []
    for target_closure in targets_to_run:
        final_results.append(target_closure(args))

    print('\n\n**************************************************************')
    print('PRINTING SUMMARY')
    print('**************************************************************\n\n')

    for result in final_results:
        if result is not None:
            print(result)


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