#!/usr/bin/env python
# Copyright (c) 2019, 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.

# This script is designed to run on a buildbot to build from the source
# of https://github.com/google/desugar_jdk_libs and publish to the
# r8-release Cloud Storage Bucket.
#
# These files are uploaded:
#
#   raw/desugar_jdk_libs/<VERSION>/desugar_jdk_libs.jar
#   raw/desugar_jdk_libs/<VERSION>/desugar_jdk_libs.zip
#   raw/com/android/tools/desugar_jdk_libs/<VERSION>/desugar_jdk_libs-<VERSION>.jar
#
# The first two are the raw jar file and the maven compatible zip file. The
# third is the raw jar file placed and named so that the URL
# http://storage.googleapis.com/r8-releases/raw can be treated as a maven
# repository to fetch the artifact com.android.tools:desugar_jdk_libs:1.0.0

import archive
import defines
import git_utils
import optparse
import os
import re
import shutil
import subprocess
import sys
import utils
import zipfile

if defines.IsLinux():
  JDK8_JAVAC = os.path.join(
      defines.THIRD_PARTY, 'openjdk', 'jdk8', 'linux-x86', 'bin', 'javac')
elif defines.IsOsX():
  JDK8_JAVAC = os.path.join(
      defines.THIRD_PARTY, 'openjdk', 'jdk8', 'darwin-x86', 'bin', 'javac')
elif defines.IsWindows():
  raise Exception('Cannot compile using JDK8 on Windows hence cannot archive.')

CONVERSION_FOLDER = os.path.join(
    defines.REPO_ROOT, 'src', 'test', 'desugaredLibraryConversions')

VERSION_FILE = 'VERSION.txt'
LIBRARY_NAME = 'desugar_jdk_libs'

def ParseOptions(argv):
  result = optparse.OptionParser()
  result.add_option('--dry-run', '--dry_run',
      help='Running on bot, use third_party dependency.',
      default=False,
      action='store_true')
  result.add_option('--dry-run-output', '--dry_run_output',
      help='Output directory for dry run.',
      type="string", action="store")
  result.add_option('--github-account', '--github_account',
      help='GitHub account to clone from.',
      default="google",
      type="string", action="store")
  (options, args) = result.parse_args(argv)
  return (options, args)


def GetVersion():
  with open(VERSION_FILE, 'r') as version_file:
    lines = version_file.readlines()
    if len(lines) != 1:
      raise Exception('Version file '
          + VERSION_FILE + ' is expected to have exactly one line')
    version = lines[0].strip()
    if (version == '1.0.1'):
      raise Exception('Version file ' + VERSION_FILE + 'cannot have version 1.0.1')
    if (version == '1.0.0'):
      version = '1.0.1'
    utils.check_basic_semver_version(
        version, 'in version file ' + VERSION_FILE)
    return version


def Upload(options, file_name, storage_path, destination, is_master):
  print('Uploading %s to %s' % (file_name, destination))
  if options.dry_run:
    if options.dry_run_output:
      dry_run_destination = \
          os.path.join(options.dry_run_output, os.path.basename(file_name))
      print('Dry run, not actually uploading. Copying to '
        + dry_run_destination)
      shutil.copyfile(file_name, dry_run_destination)
    else:
      print('Dry run, not actually uploading')
  else:
    utils.upload_file_to_cloud_storage(file_name, destination)
    print('File available at: %s' %
        destination.replace('gs://', 'http://storage.googleapis.com/', 1))

def GetFilesInFolder(folder):
  resulting_files = []
  for root, dirs, files in os.walk(folder):
    for name in files:
      resulting_files.append(os.path.join(root, name))
  assert len(resulting_files) > 0
  return resulting_files

def Main(argv):
  (options, args) = ParseOptions(argv)
  if (len(args) > 0):
    raise Exception('Unsupported arguments')
  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.dry_run_output and
      (not os.path.exists(options.dry_run_output) or
       not os.path.isdir(options.dry_run_output))):
    raise Exception(options.dry_run_output
        + ' does not exist or is not a directory')

  if utils.is_bot():
    archive.SetRLimitToMax()

  # Make sure bazel is extracted in third_party.
  utils.DownloadFromGoogleCloudStorage(utils.BAZEL_SHA_FILE)
  utils.DownloadFromGoogleCloudStorage(utils.JAVA8_SHA_FILE)

  # Only handling versioned desugar_jdk_libs.
  is_master = False

  with utils.TempDir() as checkout_dir:
    git_utils.GitClone(
      'https://github.com/'
          + options.github_account + '/' + LIBRARY_NAME, checkout_dir)
    with utils.ChangedWorkingDirectory(checkout_dir):
      version = GetVersion()

      destination = archive.GetVersionDestination(
          'gs://', LIBRARY_NAME + '/' + version, is_master)
      if utils.cloud_storage_exists(destination) and not options.dry_run:
        raise Exception(
            'Target archive directory %s already exists' % destination)

      bazel = os.path.join(utils.BAZEL_TOOL, 'lib', 'bazel', 'bin', 'bazel')
      cmd = [bazel, 'build', '--host_force_python=PY2', 'maven_release']
      utils.PrintCmd(cmd)
      subprocess.check_call(cmd)
      cmd = [bazel, 'shutdown']
      utils.PrintCmd(cmd)
      subprocess.check_call(cmd)

      # Compile the stubs for conversion files compilation.
      stub_compiled_folder = os.path.join(checkout_dir, 'stubs')
      os.mkdir(stub_compiled_folder)
      all_stubs = GetFilesInFolder(os.path.join(CONVERSION_FOLDER, 'stubs'))
      cmd = [JDK8_JAVAC, '-d', stub_compiled_folder] + all_stubs
      utils.PrintCmd(cmd)
      subprocess.check_call(cmd)

      # Compile the conversion files.
      conversions_compiled_folder = os.path.join(checkout_dir, 'conversions')
      os.mkdir(conversions_compiled_folder)
      all_conversions = GetFilesInFolder(
          os.path.join(CONVERSION_FOLDER, 'conversions'))
      cmd = [JDK8_JAVAC, '-cp', stub_compiled_folder, '-d',
             conversions_compiled_folder] + all_conversions
      utils.PrintCmd(cmd)
      subprocess.check_call(cmd)

      # Locate the library jar and the maven zip with the jar from the
      # bazel build.
      library_jar = os.path.join(
          'bazel-bin', 'src', 'share', 'classes', 'java', 'libjava.jar')
      maven_zip = os.path.join('bazel-bin', LIBRARY_NAME +'.zip')

      # Make a writable copy of the jar.
      jar_folder = os.path.join(checkout_dir, 'jar')
      os.mkdir(jar_folder)
      shutil.copy(library_jar, jar_folder)
      library_jar = os.path.join(jar_folder,'libjava.jar')
      os.chmod(library_jar, 0o777)

      # Add conversion classes into the jar.
      all_compiled_conversions = GetFilesInFolder(conversions_compiled_folder)
      with zipfile.ZipFile(library_jar, mode='a', allowZip64=True) as jar:
        for clazz in all_compiled_conversions:
          jar.write(clazz,arcname=os.path.relpath(
              clazz,
              conversions_compiled_folder),
              compress_type = zipfile.ZIP_DEFLATED)

      storage_path = LIBRARY_NAME + '/' + version
      # Upload the jar file with the library.
      destination = archive.GetUploadDestination(
          storage_path, LIBRARY_NAME + '.jar', is_master)
      Upload(options, library_jar, storage_path, destination, is_master)

      # Upload the maven zip file with the library.
      destination = archive.GetUploadDestination(
          storage_path, LIBRARY_NAME + '.zip', is_master)
      Upload(options, maven_zip, storage_path, destination, is_master)

      # Upload the jar file for accessing GCS as a maven repro.
      maven_destination = archive.GetUploadDestination(
          utils.get_maven_path('desugar_jdk_libs', version),
          'desugar_jdk_libs-%s.jar' % version,
          is_master)
      if options.dry_run:
        print('Dry run, not actually creating maven repo')
      else:
        utils.upload_file_to_cloud_storage(library_jar, maven_destination)
        print('Maven repo root available at: %s' % archive.GetMavenUrl(is_master))


if __name__ == '__main__':
  sys.exit(Main(sys.argv[1:]))
