#!/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('--archive-hash',
                      required=True,
                      metavar=('<main hash>'),
                      help='The hash to use for archiving a smali build')
  result.add_argument('--version',
                      required=True,
                      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.archive_hash or not options.version):
    raise Exception('Both --archive-hash and --version are required')

  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):
      assert options.archive_hash
      subprocess.check_call(['git', 'checkout', options.archive_hash])

      # 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 version != options.version:
        raise Exception(
            'Commit % has version %s, expected version %s'
            % (options.archive_hash, version, options.version))
      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', '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())
