# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Script to create the Chrome Updater Installer archive.

  This script is used to create an archive of all the files required for a
  Chrome Updater install in appropriate directory structure. It reads
  updater.release file as input, creates updater.7z uncompressed archive, and
  generates the updater.packed.7z compressed archive.

"""

import ConfigParser
import glob
import optparse
import os
import shutil
import subprocess
import sys

# Directory name inside the uncompressed archive where all the files are.
UPDATER_DIR = "bin"

# Suffix to uncompressed full archive file, appended to options.output_name.
ARCHIVE_SUFFIX = ".7z"

# compressed full archive suffix, will be prefixed by options.output_name.
COMPRESSED_ARCHIVE_SUFFIX = ".packed.7z"
TEMP_ARCHIVE_DIR = "temp_installer_archive"

g_archive_inputs = []


def CompressUsingLZMA(build_dir, compressed_file, input_file, verbose):
  lzma_exec = GetLZMAExec(build_dir)
  cmd = [
      lzma_exec,
      'a',
      '-t7z',
      # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe
      # pre-filter). These arguments are the similar to what the Chrome mini
      # installer is using.
      '-m0=BCJ2',
      '-m1=LZMA:d27:fb128',
      '-m2=LZMA:d22:fb128:mf=bt2',
      '-m3=LZMA:d22:fb128:mf=bt2',
      '-mb0:1',
      '-mb0s1:2',
      '-mb0s2:3',
      os.path.abspath(compressed_file),
      os.path.abspath(input_file),
  ]
  if os.path.exists(compressed_file):
    os.remove(compressed_file)
  RunSystemCommand(cmd, verbose)


def CopyAllFilesToStagingDir(config, staging_dir, build_dir):
  """Copies the files required for installer archive.
  """
  CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, build_dir)


def CopySectionFilesToStagingDir(config, section, staging_dir, src_dir):
  """Copies installer archive files specified in section from src_dir to
  staging_dir. This method reads section from config and copies all the
  files specified from src_dir to staging dir.
  """
  for option in config.options(section):
    src_subdir = option.replace('\\', os.sep)
    dst_dir = os.path.join(staging_dir, config.get(section, option))
    dst_dir = dst_dir.replace('\\', os.sep)
    src_paths = glob.glob(os.path.join(src_dir, src_subdir))
    if src_paths and not os.path.exists(dst_dir):
      os.makedirs(dst_dir)
    for src_path in src_paths:
      print(src_path)
      dst_path = os.path.join(dst_dir, os.path.basename(src_path))
      if not os.path.exists(dst_path):
        g_archive_inputs.append(src_path)
        print('paths src_path={0}, dest_dir={1}'.format(src_path, dst_dir))
        shutil.copy(src_path, dst_dir)


def GetLZMAExec(build_dir):
  if sys.platform == 'win32':
    lzma_exec = os.path.join(build_dir, "..", "..", "third_party", "lzma_sdk",
                             "Executable", "7za.exe")
  else:
    lzma_exec = '7zr'  # Use system 7zr.
  return lzma_exec


def MakeStagingDirectory(staging_dir):
  """Creates a staging path for installer archive. If directory exists already,
  deletes the existing directory.
  """
  file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR)
  if os.path.exists(file_path):
    shutil.rmtree(file_path)
  os.makedirs(file_path)
  return file_path


def Readconfig(input_file):
  """Reads config information from input file after setting default value of
  global variables.
  """
  variables = {}
  variables['UpdaterDir'] = UPDATER_DIR
  config = ConfigParser.SafeConfigParser(variables)
  config.read(input_file)
  return config


def RunSystemCommand(cmd, verbose):
  """Runs |cmd|, prints the |cmd| and its output if |verbose|; otherwise
  captures its output and only emits it on failure.
  """
  if verbose:
    print 'Running', cmd

  try:
    # Run |cmd|, redirecting stderr to stdout in order for captured errors to be
    # inline with corresponding stdout.
    output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
    if verbose:
      print output
  except subprocess.CalledProcessError as e:
    raise Exception("Error while running cmd: %s\n"
                    "Exit code: %s\n"
                    "Command output:\n%s" % (e.cmd, e.returncode, e.output))


def CreateArchiveFile(options, staging_dir):
  """Creates a new installer archive file after deleting any existing old file.
  """
  # First create an uncompressed archive file for the current build (updater.7z)
  lzma_exec = GetLZMAExec(options.build_dir)
  archive_file = os.path.join(options.output_dir,
                              options.output_name + ARCHIVE_SUFFIX)

  if options.depfile:
    # If a depfile was requested, do the glob of the staging dir and generate
    # a list of dependencies in .d format. We list the files that were copied
    # into the staging dir, not the files that are actually in the staging dir
    # because the ones in the staging dir will never be edited, and we want
    # to have the build be triggered when the thing-that-was-copied-there
    # changes.

    def PathFixup(path):
      """Fixes path for depfile format: backslash to forward slash, and
      backslash escaping for spaces."""
      return path.replace('\\', '/').replace(' ', '\\ ')

    # Gather the list of files in the staging dir that will be zipped up. We
    # only gather this list to make sure that g_archive_inputs is complete (i.e.
    # that there's not file copies that got missed).
    staging_contents = []
    for root, files in os.walk(os.path.join(staging_dir, UPDATER_DIR)):
      for filename in files:
        staging_contents.append(PathFixup(os.path.join(root, filename)))

    # Make sure there's an archive_input for each staging dir file.
    for staging_file in staging_contents:
      for archive_input in g_archive_inputs:
        archive_rel = PathFixup(archive_input)
        if (os.path.basename(staging_file).lower() == os.path.basename(
            archive_rel).lower()):
          break
      else:
        raise Exception('Did not find an archive input file for "%s"' %
                        staging_file)

    # Finally, write the depfile referencing the inputs.
    with open(options.depfile, 'wb') as f:
      f.write(
          PathFixup(os.path.relpath(archive_file, options.build_dir)) +
          ': \\\n')
      f.write('  ' + ' \\\n  '.join(PathFixup(x) for x in g_archive_inputs))

  # It is important to use abspath to create the path to the directory because
  # if you use a relative path without any .. sequences then 7za.exe uses the
  # entire relative path as part of the file paths in the archive. If you have
  # a .. sequence or an absolute path then only the last directory is stored as
  # part of the file paths in the archive, which is what we want.
  cmd = [
      lzma_exec,
      'a',
      '-t7z',
      archive_file,
      os.path.abspath(os.path.join(staging_dir, UPDATER_DIR)),
      '-mx0',
  ]
  # There does not seem to be any way in 7za.exe to override existing file so
  # we always delete before creating a new one.
  if not os.path.exists(archive_file):
    RunSystemCommand(cmd, options.verbose)
  elif options.skip_rebuild_archive != "true":
    os.remove(archive_file)
    RunSystemCommand(cmd, options.verbose)

  # Do not compress the archive when skip_archive_compression is specified.
  if options.skip_archive_compression:
    compressed_file = os.path.join(
        options.output_dir, options.output_name + COMPRESSED_ARCHIVE_SUFFIX)
    if os.path.exists(compressed_file):
      os.remove(compressed_file)
    return os.path.basename(archive_file)

  compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX
  compressed_archive_file_path = os.path.join(options.output_dir,
                                              compressed_archive_file)
  CompressUsingLZMA(options.build_dir, compressed_archive_file_path,
                    archive_file, options.verbose)

  return compressed_archive_file


_RESOURCE_FILE_HEADER = """\
// This file is automatically generated by create_installer_archive.py.
// It contains the resource entries that are going to be linked inside the exe.
// For each file to be linked there should be two lines:
// - The first line contains the output filename (without path) and the
// type of the resource ('BN' - not compressed , 'BL' - LZ compressed,
// 'B7' - LZMA compressed)
// - The second line contains the path to the input file. Uses '/' to
// separate path components.
"""


def CreateResourceInputFile(output_dir, archive_file, resource_file_path,
                            component_build, staging_dir):
  """Creates resource input file for installer target."""

  # An array of (file, type, path) tuples of the files to be included.
  resources = [(archive_file, 'B7', os.path.join(output_dir, archive_file))]

  with open(resource_file_path, 'w') as f:
    f.write(_RESOURCE_FILE_HEADER)
    for (file, type, path) in resources:
      f.write('\n%s  %s\n    "%s"\n' % (file, type, path.replace("\\", "/")))


def ParseDLLsFromDeps(build_dir, runtime_deps_file):
  """Parses the runtime_deps file and returns the set of DLLs in it, relative
  to build_dir."""
  build_dlls = set()
  args = open(runtime_deps_file).read()
  for l in args.splitlines():
    if os.path.splitext(l)[1] == ".dll":
      build_dlls.add(os.path.join(build_dir, l))
  return build_dlls


# Copies component build DLLs for the setup to be able to find those DLLs at
# run-time.
# This is meant for developer builds only and should never be used to package
# an official build.
def DoComponentBuildTasks(staging_dir, build_dir, setup_runtime_deps):
  installer_dir = os.path.join(staging_dir, UPDATER_DIR)
  if not os.path.exists(installer_dir):
    os.mkdir(installer_dir)

  setup_component_dlls = ParseDLLsFromDeps(build_dir, setup_runtime_deps)

  for setup_component_dll in setup_component_dlls:
    g_archive_inputs.append(setup_component_dll)
    shutil.copy(setup_component_dll, installer_dir)


def main(options):
  """Main method that reads input file, creates archive file and writes
  resource input file.
  """
  config = Readconfig(options.input_file)

  staging_dir = MakeStagingDirectory(options.staging_dir)

  # Copy the files from the build dir.
  CopyAllFilesToStagingDir(config, staging_dir, options.build_dir)

  if options.component_build == '1':
    DoComponentBuildTasks(staging_dir, options.build_dir,
                          options.setup_runtime_deps)

  # Name of the archive file built (for example - updater.7z)
  archive_file = CreateArchiveFile(options, staging_dir)
  CreateResourceInputFile(options.output_dir, archive_file,
                          options.resource_file_path,
                          options.component_build == '1', staging_dir)


def _ParseOptions():
  parser = optparse.OptionParser()
  parser.add_option(
      '-i',
      '--input_file',
      help='Input file describing which files to archive.')
  parser.add_option(
      '-b',
      '--build_dir',
      help='Build directory. The paths in input_file are relative to this.')
  parser.add_option(
      '--staging_dir',
      help='Staging directory where intermediate files and directories '
      'will be created')
  parser.add_option(
      '-o',
      '--output_dir',
      help='The output directory where the archives will be written. '
      'Defaults to the build_dir.')
  parser.add_option(
      '--resource_file_path',
      help='The path where the resource file will be output. ')
  parser.add_option(
      '-s',
      '--skip_rebuild_archive',
      default="False",
      help='Skip re-building updater.7z archive if it exists.')
  parser.add_option(
      '-n',
      '--output_name',
      default='updater',
      help='Name used to prefix names of generated archives.')
  parser.add_option(
      '--component_build',
      default='0',
      help='Whether this archive is packaging a component build.')
  parser.add_option(
      '--skip_archive_compression',
      action='store_true',
      default=False,
      help='Turn off compression of updater.7z into updater.packed.7z and '
      'helpfully delete any old updater.packed.7z in |output_dir|.')
  parser.add_option(
      '--depfile',
      help='Generate a depfile with the given name listing the implicit inputs '
      'to the archive process that can be used with a build system.')
  parser.add_option(
      '--setup_runtime_deps',
      help='A file listing runtime dependencies for setup.exe. This will be '
      'used to get a list of DLLs to archive in a component build.')
  parser.add_option(
      '-v', '--verbose', action='store_true', dest='verbose', default=False)

  options, _ = parser.parse_args()
  if not options.build_dir:
    parser.error('You must provide a build dir.')

  options.build_dir = os.path.normpath(options.build_dir)

  if not options.staging_dir:
    parser.error('You must provide a staging dir.')

  if not options.input_file:
    parser.error('You must provide an input file')

  is_component_build = options.component_build == '1'
  if is_component_build and not options.setup_runtime_deps:
    parser.error("updater_runtime_deps must be specified for a component build")

  if not options.output_dir:
    options.output_dir = options.build_dir

  return options


if '__main__' == __name__:
  options = _ParseOptions()
  if options.verbose:
    print sys.argv
  sys.exit(main(options))
