#!/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.JAVA8_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-8.
            m2 = os.path.join(temp, 'm2')
            os.mkdir(m2)
            env = os.environ.copy()
            env["JAVA_HOME"] = jdk.GetJdk8Home()
            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())
