# 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 json
import logging
import os
import re
import subprocess
import sys
import tempfile
import traceback


# Install Infra build environment.
BUILD_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(
                             os.path.abspath(__file__))))
sys.path.insert(0, os.path.join(BUILD_ROOT, 'scripts'))

from common import annotator
from common import env


LOGGER = logging.getLogger('update_scripts')


IS_WINDOWS = sys.platform.startswith('win')


def _run_command(cmd, **kwargs):
  LOGGER.debug('Executing command: %s', cmd)
  kwargs.setdefault('stderr', subprocess.STDOUT)

  proc = subprocess.Popen(cmd, **kwargs)
  stdout, _ = proc.communicate()

  LOGGER.debug('Process [%s] returned [%d] with output:\n%s',
               cmd, proc.returncode, stdout)
  return proc.returncode, stdout


def ensure_managed(dot_gclient_filename):
  """Rewrites a .gclient file to set "managed": True.

  Returns:
    True if the .gclient file was modified.
  """

  with open(dot_gclient_filename) as fh:
    contents = fh.read()

  new_contents = re.sub(r'("managed"\s*:\s*)False', r'\1True', contents)

  if contents != new_contents:
    with open(dot_gclient_filename, 'w') as fh:
      fh.write(new_contents)
    return True
  return False

IMPORTANT_REPOS = ['build', 'depot_tools']

REPO_TO_GITILES_PATH = {
    'build': 'chromium/tools/build',
    'depot_tools': 'chromium/tools/depot_tools',
}

GITILES_COMMIT_TEMPLATE = 'https://chromium.googlesource.com/%s/+/%s'
GITILES_LOG_TEMPLATE = 'https://chromium.googlesource.com/%s/+log/%s..%s'

def get_repo_head(path):
  # On Windows, we need to run this in a shell so "cmd.exe" can resolve "git"
  # into something on PATH (likely "git.bat").
  cmd = ['git', 'rev-parse', 'HEAD']
  return _run_command(cmd, cwd=path, stdout=subprocess.PIPE, shell=IS_WINDOWS)


def add_revision_links(s, repos_to_old_hashes):
  """Adds infra repo revision information to the update_scripts step.

  Args:
    s: The step to add the links and step text to.
    repos_to_old_hashes: A dictionary mapping repo name to revision hash
      before update scripts was executed.
  """
  for repo, old_hash in sorted(
      repos_to_old_hashes.items(), key=lambda it: it[0]):
    path = os.path.join(env.Build, os.pardir, repo)
    rv, out = get_repo_head(path)
    if rv:
      sys.stderr.write(
          'error while getting revision info for project %r (return'
          ' code was %s):\n%s' % (repo, rv, out))
      continue

    new_hash = out.strip()
    if new_hash == old_hash:
      s.step_link(
          '%s: %s' % (repo, new_hash), GITILES_COMMIT_TEMPLATE % (
              REPO_TO_GITILES_PATH[repo], new_hash))
    else:
      gitiles_link = GITILES_LOG_TEMPLATE % (
          REPO_TO_GITILES_PATH[repo], old_hash, new_hash)
      s.step_link(
          '%s: %s..%s' % (repo, old_hash, new_hash), gitiles_link)


def update_scripts():
  if os.environ.get('RUN_SLAVE_UPDATED_SCRIPTS'):
    os.environ.pop('RUN_SLAVE_UPDATED_SCRIPTS')
    return False

  # For testing, we don't actually want to run "gclient sync" against its native
  # root. However, we don't want to mock/disable it either, since we want to
  # exercise this code path.
  build_dir = os.environ.get(
      'RUN_SLAVE_UPDATED_SCRIPTS_TEST_BUILD_DIR', env.Build)

  stream = annotator.StructuredAnnotationStream()

  with stream.step('update_scripts') as s:
    if ensure_managed(os.path.join(build_dir, os.pardir, '.gclient')):
      s.step_text('Top-level gclient solution was unmanaged, '
                  'changed to managed')

    # Get our "gclient" file. We will use the "gclient" relative to this
    # script's checkout, regardless of "build_dir".
    gclient_name = 'gclient'
    if sys.platform.startswith('win'):
      gclient_name += '.bat'
    gclient_path = os.path.join(env.Build, os.pardir, 'depot_tools',
                                gclient_name)
    gclient_cmd = [gclient_path, 'sync',
                   # these two need to both be here to actually get
                   # `git checkout --force` to happen.
                   '--force', '--delete_unversioned_trees',
                   '--break_repo_locks', '--verbose', '--jobs=2',
                   # TODO(phajdan.jr): enable syntax validation (crbug/570091).
                   '--disable-syntax-validation']
    try:
      fd, output_json = tempfile.mkstemp()
      os.close(fd)
      gclient_cmd += ['--output-json', output_json]
    except Exception:
      # Super paranoia try block.
      output_json = None

    repos_to_old_hashes = {}
    try:
      for repo in sorted(IMPORTANT_REPOS):
        path = os.path.join(env.Build, os.pardir, repo)
        rv, out = get_repo_head(path)
        if rv:
          break

        proj_sha = out.strip()
        repos_to_old_hashes[repo] = proj_sha
    except Exception:
      traceback.print_exc()

    cmd_dict = {
        'name': 'update_scripts',
        'cmd': gclient_cmd,
        'cwd': build_dir,
    }
    annotator.print_step(cmd_dict, os.environ, stream)
    rv, _ = _run_command(gclient_cmd, cwd=build_dir)
    if rv != 0:
      s.step_text('gclient sync failed!')
      s.step_exception()
    elif output_json:
      try:
        with open(output_json, 'r') as f:
          gclient_json = json.load(f)
        for line in json.dumps(
            gclient_json, sort_keys=True,
            indent=4, separators=(',', ': ')).splitlines():
          s.step_log_line('gclient_json', line)
        s.step_log_end('gclient_json')

        if repos_to_old_hashes:
          add_revision_links(s, repos_to_old_hashes)
        else:
          build_checkout = gclient_json['solutions'].get('build/')
          if build_checkout:
            s.step_text('%(scm)s - %(revision)s' % build_checkout)
            s.set_build_property('build_scm', json.dumps(build_checkout['scm']))
            s.set_build_property('build_revision',
                                 json.dumps(build_checkout['revision']))
      except Exception as e:
        s.step_text('Unable to process gclient JSON %s' % repr(e))
        s.step_exception()
      finally:
        try:
          os.remove(output_json)
        except Exception as e:
          LOGGER.warning("LEAKED: %s", output_json, exc_info=True)
    else:
      s.step_text('Unable to get SCM data')
      s.step_exception()

    os.environ['RUN_SLAVE_UPDATED_SCRIPTS'] = '1'

    # After running update scripts, set PYTHONIOENCODING=UTF-8 for the real
    # annotated_run.
    os.environ['PYTHONIOENCODING'] = 'UTF-8'

    return True
