#!/usr/bin/env python3
# Copyright (c) 2023, 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 os
import re
try:
    import resource
except ImportError:
    # Not a Unix system. Do what Gandalf tells you not to.
    pass
import shutil
import subprocess
import sys

import jdk
import utils

ARCHIVE_BUCKET = 'r8-releases'
REPO = 'https://github.com/google/smali'
NO_DRYRUN_OUTPUT = object()


def checkout(temp):
    subprocess.check_call(['git', 'clone', REPO, temp])
    return temp


def parse_options():
    result = argparse.ArgumentParser(description='Release Smali')
    result.add_argument('--version',
                        metavar=('<version>'),
                        help='The version of smali to archive.')
    result.add_argument('--dry-run',
                        '--dry_run',
                        nargs='?',
                        help='Build only, no upload.',
                        metavar='<output directory>',
                        default=None,
                        const=NO_DRYRUN_OUTPUT)
    result.add_argument('--checkout', help='Use existing checkout.')
    return result.parse_args()


def set_rlimit_to_max():
    (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
    resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard))


def Main():
    options = parse_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.checkout and not options.dry_run:
        raise Exception('Using local checkout is only allowed with --dry-run')
    if not options.checkout and not options.version:
        raise Exception(
            'Option --version is required (when not using local checkout)')

    if utils.is_bot() and not utils.IsWindows():
        set_rlimit_to_max()

    utils.DownloadFromGoogleCloudStorage(utils.JAVA11_SHA_FILE)
    with utils.TempDir() as temp:
        # Resolve dry run location to support relative directories.
        dry_run_output = None
        if options.dry_run and options.dry_run != NO_DRYRUN_OUTPUT:
            if not os.path.isdir(options.dry_run):
                os.mkdir(options.dry_run)
            dry_run_output = os.path.abspath(options.dry_run)

        checkout_dir = options.checkout if options.checkout else checkout(temp)
        with utils.ChangedWorkingDirectory(checkout_dir):
            if options.version:
                output = subprocess.check_output(
                    ['git', 'tag', '-l', options.version])
                if len(output) == 0:
                    raise Exception(
                        'Repository does not have a release tag for version %s'
                        % options.version)
                subprocess.check_call(['git', 'checkout', options.version])

            # Find version from `build.gradle`.
            for line in open(os.path.join('build.gradle'), 'r'):
                result = re.match(r'^version = \'(\d+)\.(\d+)\.(\d+)\'', line)
                if result:
                    break
            version = '%s.%s.%s' % (result.group(1), result.group(2),
                                    result.group(3))
            if options.version and version != options.version:
                message = 'version %s, expected version %s' % (version,
                                                               options.version)
                if (options.checkout):
                    raise Exception('Checkout %s has %s' %
                                    (options.checkout, message))
                else:
                    raise Exception('Tag % has %s' % (options.version, message))

            print('Building version: %s' % version)

            # Build release to local Maven repository compiling with JDK-11.
            m2 = os.path.join(temp, 'm2')
            os.mkdir(m2)
            env = os.environ.copy()
            env["JAVA_HOME"] = jdk.GetJdk11Home()
            subprocess.check_call([
                './gradlew',
                '-Dmaven.repo.local=%s' % m2, 'release', 'test',
                'publishToMavenLocal',
            ], env=env)
            base = os.path.join('com', 'android', 'tools', 'smali')

            # Check that the local maven repository only has the single version directory in
            # each artifact directory.
            for name in [
                    'smali-util', 'smali-dexlib2', 'smali', 'smali-baksmali'
            ]:
                dirnames = next(os.walk(os.path.join(m2, base, name)),
                                (None, None, []))[1]
                if not dirnames or len(dirnames) != 1 or dirnames[0] != version:
                    raise Exception('Found unexpected directory %s in %s' %
                                    (dirnames, name))

            # Build an archive with the relevant content of the local maven repository.
            m2_filtered = os.path.join(temp, 'm2_filtered')
            shutil.copytree(
                m2,
                m2_filtered,
                ignore=shutil.ignore_patterns('maven-metadata-local.xml'))
            maven_release_archive = shutil.make_archive(
                'smali-maven-release-%s' % version, 'zip', m2_filtered, base)

            # Collect names of the fat jars.
            fat_jars = list(
                map(lambda prefix: '%s-%s-fat.jar' % (prefix, version),
                    ['smali/build/libs/smali', 'baksmali/build/libs/baksmali']))

            # Copy artifacts.
            files = [maven_release_archive]
            files.extend(fat_jars)
            if options.dry_run:
                if dry_run_output:
                    print('Dry run, not actually uploading. Copying to %s:' %
                          dry_run_output)
                    for file in files:
                        destination = os.path.join(dry_run_output,
                                                   os.path.basename(file))
                        shutil.copyfile(file, destination)
                        print("  %s" % destination)
                else:
                    print('Dry run, not actually uploading. Generated files:')
                    for file in files:
                        print("  %s" % os.path.basename(file))
            else:
                destination_prefix = 'gs://%s/smali/%s' % (ARCHIVE_BUCKET,
                                                           version)
                if utils.cloud_storage_exists(destination_prefix):
                    raise Exception(
                        'Target archive directory %s already exists' %
                        destination_prefix)
                for file in files:
                    destination = '%s/%s' % (destination_prefix,
                                             os.path.basename(file))
                    if utils.cloud_storage_exists(destination):
                        raise Exception('Target %s already exists' %
                                        destination)
                    utils.upload_file_to_cloud_storage(file, destination)
                public_url = 'https://storage.googleapis.com/%s/smali/%s' % (
                    ARCHIVE_BUCKET, version)
                print('Artifacts available at: %s' % public_url)

    print("Done!")


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