#!/usr/bin/env python3
# Copyright (c) 2017, 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 jdk
import optparse
import os

import create_maven_release
import gradle
from timing import Timing

try:
    import resource
except ImportError:
    # Not a Unix system. Do what Gandalf tells you not to.
    pass
import json
import shutil
import subprocess
import sys
import utils
import zipfile

ARCHIVE_BUCKET = 'r8-releases'


def parse_options():
    result = optparse.OptionParser()
    result.add_option('--dry-run',
                      '--dry_run',
                      help='Build only, no upload.',
                      default=False,
                      action='store_true')
    result.add_option('--dry-run-output',
                      '--dry_run_output',
                      help='Output directory for \'build only, no upload\'.',
                      type="string",
                      action="store")
    result.add_option(
        '--skip-gradle-build',
        '--skip_gradle_build',
        help='Skip Gradle build. Can only be used for local testing.',
        default=False,
        action='store_true')
    result.add_option('--archive-details',
                      '--archive_details',
                      help='File to store JSON with archive details.',
                      type="string",
                      default=utils.ARCHIVE_DETAILS,
                      action="store")
    return result.parse_args()


def get_version():
    output = subprocess.check_output([
        jdk.GetJavaExecutable(jdk.GetDefaultJdkHome()), '-cp', utils.R8_JAR,
        'com.android.tools.r8.R8', '--version'
    ]).decode('utf-8')
    r8_version = output.splitlines()[0].strip()
    return r8_version.split()[1]


def get_git_branches():
    return subprocess.check_output(['git', 'show', '-s', '--pretty=%d', 'HEAD'])


def get_git_hash():
    return subprocess.check_output(['git', 'rev-parse',
                                    'HEAD']).decode('utf-8').strip()


def check_main(version):
    branches = subprocess.check_output(
        ['git', 'branch', '-r', '--contains', 'HEAD']).decode('utf-8')
    # CL runs from gerrit does not have a branch, we always treat them as main
    # commits to archive these to the hash based location
    if len(branches) == 0:
        return True
    if not version == 'main':
        # Sanity check, we don't want to archive on top of release builds EVER
        # Note that even though we branch, we never push the bots to build the same
        # commit as main on a branch since we always change the version to
        # not be just 'main' (or we crash here :-)).
        if 'origin/main' in branches:
            raise Exception('We are seeing origin/main in a commit that '
                            'don\'t have \'main\' as version')
        return False
    if not 'origin/main' in branches:
        raise Exception('We are not seeing origin/main '
                        'in a commit that have \'main\' as version')
    return True


def get_storage_path(version_or_path, is_main):
    archive_dir = 'raw/main' if is_main else 'raw'
    return '%s/%s' % (archive_dir, version_or_path)


def get_storage_destination(storage_prefix, version_or_path, file_name,
                            is_main):
    # We archive main commits under raw/main instead of directly under raw
    version_dir = get_version_destination(storage_prefix, version_or_path,
                                          is_main)
    return '%s/%s' % (version_dir, file_name)


def get_version_destination(storage_prefix, version_or_path, is_main):
    storage_path = get_storage_path(version_or_path, is_main)
    return '%s%s/%s' % (storage_prefix, ARCHIVE_BUCKET, storage_path)


def get_upload_destination(version_or_path, file_name, is_main):
    return get_storage_destination('gs://', version_or_path, file_name, is_main)


def get_url(version_or_path, file_name, is_main):
    return get_storage_destination('https://storage.googleapis.com/',
                                   version_or_path, file_name, is_main)


def get_maven_url(is_main):
    return get_version_destination('https://storage.googleapis.com/', '',
                                   is_main)


def set_r_limit_to_max():
    if not utils.is_bot() or utils.IsWindows():
        return
    (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
    resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard))


def print_resource_info():
    if utils.IsWindows():
        return
    (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
    print('INFO: Open files soft limit: %s' % soft)
    print('INFO: Open files hard limit: %s' % hard)


# Ensure all archived artifacts has been built before archiving.
# The target tasks postfixed by 'lib' depend on the actual target task so
# building it invokes the original task first.
# The '-Pno_internal' flag is important because we generate the lib based on uses in tests.
def run_gradle_build(options, timing):
    if options.skip_gradle_build:
        return
    timing.begin("Download deps")
    gradle.run_gradle([utils.GRADLE_TASK_DOWNLOAD_DEPS, '-Pno_internal'])
    timing.end()
    timing.begin("Build consolidated license")
    gradle.run_gradle([utils.GRADLE_TASK_CONSOLIDATED_LICENSE, '-Pno_internal'])
    timing.end()
    timing.begin("Build keep anno")
    gradle.run_gradle([
        utils.GRADLE_TASK_KEEP_ANNO_JAR,
        utils.GRADLE_TASK_KEEP_ANNO_DOC,
        utils.GRADLE_TASK_KEEP_ANNO_LEGACY_JAR,
        utils.GRADLE_TASK_KEEP_ANNO_ANDROIDX_JAR,
        '-Pno_internal',
    ])
    timing.end()
    timing.begin("Build process keep rules")
    gradle.run_gradle([
        utils.GRADLE_TASK_PROCESS_KEEP_RULES_LIB_JAR,
        '-Pno_internal',
    ])
    timing.end()
    timing.begin("Build R8")
    gradle.run_gradle([
        utils.GRADLE_TASK_R8,
        utils.GRADLE_TASK_R8LIB,
        utils.GRADLE_TASK_R8LIB_NO_DEPS,
        utils.GRADLE_TASK_THREADING_MODULE_BLOCKING,
        utils.GRADLE_TASK_THREADING_MODULE_SINGLE_THREADED,
        '-Pno_internal',
    ])
    timing.end()
    timing.begin("Build source jar")
    gradle.run_gradle([utils.GRADLE_TASK_SOURCE_JAR, '-Pno_internal'])
    timing.end()
    timing.begin("Build swiss army knife")
    gradle.run_gradle([utils.GRADLE_TASK_SWISS_ARMY_KNIFE, '-Pno_internal'])
    timing.end()
    timing.begin("Build keepanno tools")
    gradle.run_gradle([
        utils.GRADLE_TASK_KEEPANNOTOOLS,
        utils.GRADLE_TASK_KEEPANNOTOOLSLIB,
        '-Pno_internal',
    ])
    timing.end()


def rsync_dir(src_dir, version_or_path, dst_dir, is_main, options):
    destination = get_upload_destination(version_or_path, dst_dir, is_main)
    print(f'RSyncing {src_dir} to {destination}')
    if options.dry_run:
        if options.dry_run_output:
            dry_run_destination = os.path.join(options.dry_run_output,
                                               version_or_path, dst_dir)
            print(
                f'Dry run, not actually syncing. Copying to {dry_run_destination}'
            )
            shutil.copytree(src_dir, dry_run_destination)
        else:
            print('Dry run, not actually uploading')
    else:
        utils.rsync_directory_to_cloud_storage(src_dir, destination)
        print(
            f'Directory available at: {get_url(version_or_path, dst_dir, is_main)}'
        )


def upload_dir(src_dir, version_or_path, dst_dir, is_main, options):
    destination = get_upload_destination(version_or_path, dst_dir, is_main)
    print(f'Uploading {src_dir} to {destination}')
    if options.dry_run:
        if options.dry_run_output:
            dry_run_destination = os.path.join(options.dry_run_output,
                                               version_or_path, dst_dir)
            print(
                f'Dry run, not actually uploading. Copying to {dry_run_destination}'
            )
            shutil.copytree(src_dir, dry_run_destination)
        else:
            print('Dry run, not actually uploading')
    else:
        utils.upload_directory_to_cloud_storage(src_dir, destination)
        print(
            f'Directory available at: {get_url(version_or_path, dst_dir, is_main)}'
        )


def main():
    (options, args) = parse_options()
    run(options)


def run(options):
    if not utils.is_bot() and not options.dry_run:
        raise Exception('You are not a bot, don\'t archive builds. ' +
                        'Use --dry-run to test locally')
    if (options.dry_run_output and
        (not os.path.exists(options.dry_run_output) or
         not os.path.isdir(options.dry_run_output))):
        raise Exception(options.dry_run_output +
                        ' does not exist or is not a directory')
    if options.skip_gradle_build and not options.dry_run:
        raise Exception(
            'Using --skip-gradle-build only supported with --dry-run')

    timing = Timing()
    set_r_limit_to_max()
    print_resource_info()
    run_gradle_build(options, timing)

    version = get_version()
    is_main = check_main(version)
    if is_main:
        # On main we use the git hash to archive with
        print('On main, using git hash for archiving')
        version = get_git_hash()

    with utils.TempDir() as temp:
        timing.begin("Generate r8 maven zip")
        version_file = os.path.join(temp, 'r8-version.properties')
        with open(version_file, 'w') as version_writer:
            version_writer.write('version.sha=' + get_git_hash() + '\n')
            version_writer.write('version.version=' + version + '\n')
            if not os.environ.get('SWARMING_BOT_ID') and not options.dry_run:
                raise Exception('Environment variable SWARMING_BOT_ID not set')

            releaser = \
                ("releaser=<local developer build>\n" if options.dry_run
                  else 'releaser=go/r8bot ('
                      + (os.environ.get('SWARMING_BOT_ID') or 'foo') + ')\n')
            version_writer.write(releaser)
            version_writer.write('version-file.version.code=1\n')

        create_maven_release.generate_r8_maven_zip(
            utils.MAVEN_ZIP_LIB,
            version_file=version_file,
            skip_gradle_build=options.skip_gradle_build)
        timing.end()

        # Create maven release of the desugar_jdk_libs configuration. This requires
        # an r8.jar with dependencies to have been built.
        timing.begin("Generate desugar configuration maven zip")
        create_maven_release.generate_desugar_configuration_maven_zip(
            utils.DESUGAR_CONFIGURATION_MAVEN_ZIP, utils.DESUGAR_CONFIGURATION,
            utils.DESUGAR_IMPLEMENTATION,
            utils.LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP)
        create_maven_release.generate_desugar_configuration_maven_zip(
            utils.DESUGAR_CONFIGURATION_JDK11_LEGACY_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11_LEGACY,
            utils.DESUGAR_IMPLEMENTATION_JDK11,
            utils.LIBRARY_DESUGAR_CONVERSIONS_LEGACY_ZIP)

        create_maven_release.generate_desugar_configuration_maven_zip(
            utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL,
            utils.DESUGAR_IMPLEMENTATION_JDK11,
            utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
        create_maven_release.generate_desugar_configuration_maven_zip(
            utils.DESUGAR_CONFIGURATION_JDK11_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11,
            utils.DESUGAR_IMPLEMENTATION_JDK11,
            utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
        create_maven_release.generate_desugar_configuration_maven_zip(
            utils.DESUGAR_CONFIGURATION_JDK11_NIO_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11_NIO,
            utils.DESUGAR_IMPLEMENTATION_JDK11,
            utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
        timing.end()

        destination = get_version_destination('gs://', version, is_main)
        if utils.cloud_storage_exists(destination) and not options.dry_run:
            raise Exception('Target archive directory %s already exists' %
                            destination)

        # Create pom file for our maven repository that we build for testing.
        timing.begin("Create pom file")
        default_pom_file = os.path.join(temp, 'r8.pom')
        create_maven_release.write_default_r8_pom_file(default_pom_file,
                                                       version)
        gradle.run_gradle([
            ':dist:spdxSbom', '-PspdxVersion=' + version,
            '-PspdxRevision=' + get_git_hash()
        ])
        timing.end()

        # Upload keep-anno javadoc to a fixed "docs" location.
        timing.begin("Uploade keep-anno Javadoc")
        if is_main:
            version_or_path = 'docs'
            dst_dir = 'keepanno/javadoc'
            rsync_dir(utils.KEEPANNO_ANNOTATIONS_DOC, version_or_path, dst_dir,
                      is_main, options)
        timing.end()

        # Upload directories.
        timing.begin("Upload directories")
        dirs_for_archiving = [
            (utils.KEEPANNO_ANNOTATIONS_DOC, 'keepanno/javadoc'),
        ]
        for (src_dir, dst_dir) in dirs_for_archiving:
            upload_dir(src_dir, version, dst_dir, is_main, options)
        timing.end()

        # Upload files.
        timing.begin("Upload files")
        lib_jars = [
            utils.KEEPANNOTOOLSLIB_JAR,
            utils.PROCESS_KEEP_RULES_LIB_JAR,
            utils.R8LIB_JAR,
            utils.R8LIB_EXCLUDE_DEPS_JAR,
        ]
        for_archiving = []
        for lib_jar in lib_jars:
            for_archiving.append(lib_jar)
            for_archiving.append(lib_jar + '.map')
            for_archiving.append(lib_jar + '_map.zip')
        for_archiving.extend([
            utils.R8_JAR, utils.R8_FULL_EXCLUDE_DEPS_JAR, utils.MAVEN_ZIP_LIB,
            utils.THREADING_MODULE_BLOCKING_JAR,
            utils.THREADING_MODULE_SINGLE_THREADED_JAR, utils.KEEPANNOTOOLS_JAR,
            utils.DESUGAR_CONFIGURATION, utils.DESUGAR_CONFIGURATION_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11_LEGACY,
            utils.DESUGAR_CONFIGURATION_JDK11_LEGACY_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11_MINIMAL_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11_MAVEN_ZIP,
            utils.DESUGAR_CONFIGURATION_JDK11_NIO_MAVEN_ZIP, utils.R8_SRC_JAR,
            utils.KEEPANNO_ANNOTATIONS_JAR,
            utils.KEEPANNO_LEGACY_ANNOTATIONS_JAR,
            utils.KEEPANNO_ANDROIDX_ANNOTATIONS_JAR, utils.GENERATED_LICENSE,
            'd8_r8/dist/build/spdx/r8.spdx.json',
            'src/keepradius/proto/keepradius.proto',
            'src/keepradius/proto/keepradiussummary.proto',
            'src/libanalyzer/proto/libraryanalyzerresult.proto'
        ])
        for file in for_archiving:
            file_name = os.path.basename(file)
            tagged_jar = os.path.join(temp, file_name)
            shutil.copyfile(file, tagged_jar)
            if file_name.endswith(
                    '.jar') and not file_name.endswith('-src.jar'):
                with zipfile.ZipFile(tagged_jar, 'a') as f:
                    f.write(version_file, os.path.basename(version_file))
            destination = get_upload_destination(version, file_name, is_main)
            print('Uploading %s to %s' % (tagged_jar, destination))
            if options.dry_run:
                if options.dry_run_output:
                    dry_run_destination = os.path.join(options.dry_run_output,
                                                       version, file_name)
                    print('Dry run, not actually uploading. Copying to ' +
                          dry_run_destination)
                    shutil.copyfile(tagged_jar, dry_run_destination)
                else:
                    print('Dry run, not actually uploading')
            else:
                utils.upload_file_to_cloud_storage(tagged_jar, destination)
                print('File available at: %s' %
                      get_url(version, file_name, is_main))

            # Upload R8 to a maven compatible location.
            if file == utils.R8_JAR:
                maven_dst = get_upload_destination(
                    utils.get_maven_path('r8', version), 'r8-%s.jar' % version,
                    is_main)
                maven_pom_dst = get_upload_destination(
                    utils.get_maven_path('r8', version), 'r8-%s.pom' % version,
                    is_main)
                if options.dry_run:
                    print('Dry run, not actually creating maven repo for R8')
                else:
                    utils.upload_file_to_cloud_storage(tagged_jar, maven_dst)
                    utils.upload_file_to_cloud_storage(default_pom_file,
                                                       maven_pom_dst)
                    print('Maven repo root available at: %s' %
                          get_maven_url(is_main))

            # Upload R8LIB to latest on dev channel, this is used by godbolt.
            if (version.endswith('-dev') and
                (file == utils.R8LIB_JAR or
                 file == utils.KEEPANNO_ANNOTATIONS_JAR)):
                latest_dst = get_upload_destination('latest-dev', file_name,
                                                    is_main)
                print('Uploading %s to %s' % (tagged_jar, latest_dst))
                if options.dry_run:
                    print('Dry run, not actually uploading')
                else:
                    utils.upload_file_to_cloud_storage(tagged_jar, latest_dst)

            # Upload desugar_jdk_libs configuration to a maven compatible location.
            if file == utils.DESUGAR_CONFIGURATION:
                jar_basename = 'desugar_jdk_libs_configuration.jar'
                jar_version_name = 'desugar_jdk_libs_configuration-%s.jar' % version
                maven_dst = get_upload_destination(
                    utils.get_maven_path('desugar_jdk_libs_configuration',
                                         version), jar_version_name, is_main)

                with utils.TempDir() as tmp_dir:
                    desugar_jdk_libs_configuration_jar = os.path.join(
                        tmp_dir, jar_version_name)
                    create_maven_release.generate_jar_with_desugar_configuration(
                        utils.DESUGAR_CONFIGURATION,
                        utils.DESUGAR_IMPLEMENTATION,
                        utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP,
                        desugar_jdk_libs_configuration_jar)

                    if options.dry_run:
                        print('Dry run, not actually creating maven repo for ' +
                              'desugar configuration.')
                        if options.dry_run_output:
                            shutil.copyfile(
                                desugar_jdk_libs_configuration_jar,
                                os.path.join(options.dry_run_output,
                                             jar_version_name))
                    else:
                        utils.upload_file_to_cloud_storage(
                            desugar_jdk_libs_configuration_jar, maven_dst)
                        print('Maven repo root available at: %s' %
                              get_maven_url(is_main))
                        # Also archive the jar as non maven destination for Google3
                        jar_destination = get_upload_destination(
                            version, jar_basename, is_main)
                        utils.upload_file_to_cloud_storage(
                            desugar_jdk_libs_configuration_jar, jar_destination)

            # TODO(b/237636871): Refactor this to avoid the duplication of what is above.
            # Upload desugar_jdk_libs JDK-11 legacyconfiguration to a maven compatible location.
            if file == utils.DESUGAR_CONFIGURATION_JDK11_LEGACY:
                jar_basename = 'desugar_jdk_libs_configuration.jar'
                jar_version_name = 'desugar_jdk_libs_configuration-%s-jdk11-legacy.jar' % version
                maven_dst = get_upload_destination(
                    utils.get_maven_path('desugar_jdk_libs_configuration',
                                         version), jar_version_name, is_main)

                with utils.TempDir() as tmp_dir:
                    desugar_jdk_libs_configuration_jar = os.path.join(
                        tmp_dir, jar_version_name)
                    create_maven_release.generate_jar_with_desugar_configuration(
                        utils.DESUGAR_CONFIGURATION_JDK11_LEGACY,
                        utils.DESUGAR_IMPLEMENTATION_JDK11,
                        utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP,
                        desugar_jdk_libs_configuration_jar)

                    if options.dry_run:
                        print('Dry run, not actually creating maven repo for ' +
                              'desugar configuration.')
                        if options.dry_run_output:
                            shutil.copyfile(
                                desugar_jdk_libs_configuration_jar,
                                os.path.join(options.dry_run_output,
                                             jar_version_name))
                    else:
                        utils.upload_file_to_cloud_storage(
                            desugar_jdk_libs_configuration_jar, maven_dst)
                        print('Maven repo root available at: %s' %
                              get_maven_url(is_main))
                        # Also archive the jar as non maven destination for Google3
                        jar_destination = get_upload_destination(
                            version, jar_basename, is_main)
                        utils.upload_file_to_cloud_storage(
                            desugar_jdk_libs_configuration_jar, jar_destination)

        # Write the archive details JSON (for the LUCI recipie to read).
        archive_details = {
            'is_main': is_main,
            'version': version,
            'bucket': ARCHIVE_BUCKET,
            'bucket_path': get_storage_path(version, is_main)
        }
        with open(options.archive_details, "w") as f:
            json.dump(archive_details, f, indent=4)

        timing.end()
        timing.report()


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