#!/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.EnsureDepFromGoogleCloudStorage(utils.JAVA11_SHA_FILE,
                                          'Java 11 runtime')
    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)
            subprocess.check_call([
                './gradlew',
                '-Dorg.gradle.java.home=%s' % jdk.GetJdk11Home(),
                '-Dmaven.repo.local=%s' % m2,
                'release',
                'test',
                'publishToMavenLocal',
            ])
            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())
