# 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 ucompressed 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))
