# Copyright 2016 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.

import argparse
import fnmatch
import logging
import os
import shutil
import subprocess
import sys
import tempfile


THIS_DIR = os.path.abspath(os.path.dirname(__file__))
ROOT_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..'))

DEVNULL = open(os.devnull, 'w')


def _check_call(argv, **kwargs):
  """Wrapper for subprocess.check_call that adds logging."""
  logging.info('running %r', argv)
  subprocess.check_call(argv, **kwargs)


def get_target_git_version():
  """Returns git version that should be installed."""
  if os.path.exists(os.path.join(ROOT_DIR, '.git_bleeding_edge')):
    git_version_file = 'git_version_bleeding_edge.txt'
  else:
    git_version_file = 'git_version.txt'
  with open(os.path.join(THIS_DIR, git_version_file)) as f:
    return f.read().strip()


def clean_up_old_git_installations(git_directory):
  """Removes git installations other than |git_directory|."""
  for entry in fnmatch.filter(os.listdir(ROOT_DIR), 'git-*_bin'):
    full_entry = os.path.join(ROOT_DIR, entry)
    if full_entry != git_directory:
      logging.info('Cleaning up old git installation %r', entry)
      shutil.rmtree(full_entry, ignore_errors=True)


def bootstrap_cipd(cipd_directory, cipd_platform):
  """Bootstraps CIPD client into |cipd_directory|."""
  _check_call([
      sys.executable,
      os.path.join(ROOT_DIR, 'recipe_modules', 'cipd', 'resources',
                   'bootstrap.py'),
      '--platform', cipd_platform,
      '--dest-directory', cipd_directory
  ])


def cipd_install(args, dest_directory, package, version):
  """Installs CIPD |package| at |version| into |dest_directory|."""
  manifest_file = tempfile.mktemp()
  try:
    with open(manifest_file, 'w') as f:
      f.write('%s %s\n' % (package, version))

    cipd_args = [
      args.cipd_client,
      'ensure',
      '-list', manifest_file,
      '-root', dest_directory,
    ]
    if args.cipd_cache_directory:
      cipd_args.extend(['-cache-dir', args.cipd_cache_directory])
    if args.verbose:
      cipd_args.append('-verbose')
    _check_call(cipd_args)
  finally:
    os.remove(manifest_file)


def need_to_install_git(args, git_directory):
  """Returns True if git needs to be installed."""
  if args.force:
    return True
  git_exe_path = os.path.join(git_directory, 'bin', 'git.exe')
  if not os.path.exists(git_exe_path):
    return True
  if subprocess.call(
      [git_exe_path, '--version'],
      stdout=DEVNULL, stderr=DEVNULL) != 0:
    return True
  for script in ('git.bat', 'gitk.bat', 'ssh.bat', 'ssh-keygen.bat',
                 'git-bash'):
    full_path = os.path.join(ROOT_DIR, script)
    if not os.path.exists(full_path):
      return True
    with open(full_path) as f:
      if os.path.relpath(git_directory, ROOT_DIR) not in f.read():
        return True
  if not os.path.exists(os.path.join(
      git_directory, 'etc', 'profile.d', 'python.sh')):
    return True
  return False


def install_git(args, git_version, git_directory):
  """Installs |git_version| into |git_directory|."""
  cipd_platform = 'windows-%s' % ('amd64' if args.bits == 64 else '386')
  if not args.cipd_client:
    bootstrap_cipd(ROOT_DIR, cipd_platform)
    args.cipd_client = os.path.join(ROOT_DIR, 'cipd')
  temp_dir = tempfile.mkdtemp()
  try:
    cipd_install(args,
                 temp_dir,
                 'infra/depot_tools/git_installer/%s' % cipd_platform,
                 'v' + git_version.replace('.', '_'))

    if not os.path.exists(git_directory):
      os.makedirs(git_directory)

    # 7-zip has weird expectations for command-line syntax. Pass it as a string
    # to avoid subprocess module quoting breaking it. Also double-escape
    # backslashes in paths.
    _check_call(' '.join([
      os.path.join(temp_dir, 'git-installer.exe'),
      '-y',
      '-InstallPath="%s"' % git_directory.replace('\\', '\\\\'),
      '-Directory="%s"' % git_directory.replace('\\', '\\\\'),
    ]))
  finally:
    shutil.rmtree(temp_dir, ignore_errors=True)

  with open(os.path.join(THIS_DIR, 'git.template.bat')) as f:
    git_template = f.read()
  git_template = git_template.replace(
      'GIT_BIN_DIR', os.path.relpath(git_directory, ROOT_DIR))
  scripts = (
      ('git.bat', 'cmd\\git.exe'),
      ('gitk.bat', 'cmd\\gitk.exe'),
      ('ssh.bat', 'usr\\bin\\ssh.exe'),
      ('ssh-keygen.bat', 'usr\\bin\\ssh-keygen.exe'),
  )
  for script in scripts:
    with open(os.path.join(ROOT_DIR, script[0]), 'w') as f:
      f.write(git_template.replace('GIT_PROGRAM', script[1]))
  with open(os.path.join(THIS_DIR, 'git-bash.template.sh')) as f:
    git_bash_template = f.read()
  with open(os.path.join(ROOT_DIR, 'git-bash'), 'w') as f:
    f.write(git_bash_template.replace(
        'GIT_BIN_DIR', os.path.relpath(git_directory, ROOT_DIR)))
  shutil.copyfile(
      os.path.join(THIS_DIR, 'profile.d.python.sh'),
      os.path.join(git_directory, 'etc', 'profile.d', 'python.sh'))

  git_bat_path = os.path.join(ROOT_DIR, 'git.bat')
  _check_call([git_bat_path, 'config', '--system', 'core.autocrlf', 'false'])
  _check_call([git_bat_path, 'config', '--system', 'core.filemode', 'false'])
  _check_call([git_bat_path, 'config', '--system', 'core.preloadindex', 'true'])
  _check_call([git_bat_path, 'config', '--system', 'core.fscache', 'true'])


def sync_git_help_files(git_directory):
  """Updates depot_tools help files inside |git_directory|."""
  # TODO(phajdan.jr): consider replacing the call with python code.
  _check_call([
      'xcopy', '/i', '/q', '/d', '/y',
      os.path.join(ROOT_DIR, 'man', 'html', '*'),
      os.path.join(git_directory, 'mingw64', 'share', 'doc', 'git-doc')],
      stdout=DEVNULL)


def main(argv):
  parser = argparse.ArgumentParser()
  parser.add_argument('--bits', type=int, choices=(32,64), default=64,
                      help='Bitness of the client to install.')
  parser.add_argument('--cipd-client', help='Path to CIPD client binary.')
  parser.add_argument('--cipd-cache-directory',
                      help='Path to CIPD cache directory.')
  parser.add_argument('--force', action='store_true',
                      help='Always re-install git.')
  parser.add_argument('--verbose', action='store_true')
  args = parser.parse_args(argv)

  if os.environ.get('WIN_TOOLS_FORCE') == '1':
    args.force = True

  logging.basicConfig(level=logging.INFO if args.verbose else logging.WARN)

  git_version = get_target_git_version()
  git_directory = os.path.join(
      ROOT_DIR, 'git-%s-%s_bin' % (git_version, args.bits))

  clean_up_old_git_installations(git_directory)

  if need_to_install_git(args, git_directory):
    install_git(args, git_version, git_directory)

  sync_git_help_files(git_directory)

  return 0


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