#!/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 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()

  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.
      m2 = os.path.join(temp, 'm2')
      os.mkdir(m2)
      subprocess.check_call(
          ['./gradlew', '-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())
