#!/usr/bin/python2
"""Syncs to a given Cobalt build id.

Syncs current gclient instance to a given build id, as
generated by "build_id.py" and stored on carbon-airlock-95823.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import json
import os
import subprocess
import sys
import requests

_BUILD_ID_QUERY_URL = (
    "https://carbon-airlock-95823.appspot.com/build_version/search")
_BUILD_ID_QUERY_PARAMETER_NAME = "build_number"


def _GetGClientRoot(repo_path):
  """Finds the root of this gclient repo, or returns repo_path if failed."""
  current_path = os.path.normpath(repo_path)
  while not os.access(os.path.join(current_path, ".gclient"), os.R_OK):
    next_path = os.path.dirname(current_path)
    if next_path == current_path:
      return repo_path
    current_path = next_path
  return current_path


class SubprocessFailedException(Exception):
  """Exception for non-zero subprocess exits."""

  def __init__(self, command):
    super(SubprocessFailedException, self).__init__()
    self.command = command

  def __str__(self):
    return "Subprocess failed '{0}'".format(self.command)


def _RunGitCommand(gitargs, **kwargs):
  """Runs a git command with "gitargs", returning the output splitlines().

  Args:
    gitargs: Commandline args that follow 'git'.
    **kwargs: Keyword args for Popen.

  Returns:
    All of stdout, as an array of lines.

  Raises:
    SubprocessFailedException: if the exit code is nonzero.

  """
  result_tuple = _RunGitCommandReturnExitCode(gitargs, **kwargs)
  if result_tuple[0] != 0:
    raise SubprocessFailedException(" ".join(["git"] + gitargs))
  return result_tuple[1]


def _RunGitCommandReturnExitCode(gitargs, **kwargs):
  """Runs a git command with "gitargs", returning the exit code and output.

  Args:
    gitargs: Commandline args that follow 'git'.
    **kwargs: Keyword args for Popen.

  Returns:
    Tuple of (exit code, all of stdout as an array of lines).

  """
  popen_args = ["git"] + gitargs
  p = subprocess.Popen(popen_args, stdout=subprocess.PIPE, **kwargs)
  output = p.stdout.read().splitlines()
  return p.wait(), output


def main():
  dev_null = open("/dev/null", "w")
  arg_parser = argparse.ArgumentParser(
      description="Syncs to a given Cobalt build id")
  arg_parser.add_argument("buildid", nargs=1)
  args = arg_parser.parse_args()
  r = requests.get(_BUILD_ID_QUERY_URL,
                   params={_BUILD_ID_QUERY_PARAMETER_NAME: args.buildid[0]})
  if not r.ok:
    print(
        "HTTP request failed\n{0} {1}\n{2}".format(r.status_code, r.reason,
                                                   r.text),
        file=sys.stderr)
    return 1
  # The response starts with a security-related close expression line
  outer_json = json.loads(r.text.splitlines()[1])
  hashes = json.loads(outer_json["deps"])
  gclient_root = _GetGClientRoot(os.getcwd())

  for relpath, rep_hash in hashes.iteritems():
    path = os.path.join(gclient_root, relpath)
    is_dirty = (bool(
        _RunGitCommandReturnExitCode(
            ["diff", "--no-ext-diff", "--quiet"], cwd=path, stderr=dev_null)[0])
                or bool(
                    _RunGitCommandReturnExitCode(
                        ["diff", "--no-ext-diff", "--quiet", "--cached"],
                        cwd=path,
                        stderr=dev_null)[0]))

    if is_dirty:
      print("{0} is dirty, please resolve".format(relpath))
      return 1

  for relpath, rep_hash in hashes.iteritems():
    path = os.path.join(gclient_root, relpath)
    # repo_hash has a repo path prefix like this:
    # 'https://chromium.googlesource.com/chromium/llvm-project/libcxx.git
    # @48198f9110397fff47fe7c37cbfa296be7d44d3d'
    requested_hash = rep_hash[rep_hash.rindex("@") + 1:]

    current_hash = _RunGitCommand(["rev-parse", "HEAD"], cwd=path)[0]

    if requested_hash == current_hash:
      continue
    symbolic_ref = None
    try:
      symbolic_ref = _RunGitCommand(
          ["symbolic-ref", "--short", "-q", "HEAD"], cwd=path,
          stderr=dev_null)[0]
    except SubprocessFailedException:
      pass

    user_visible_commit = symbolic_ref if symbolic_ref else current_hash[0:7]

    print("{0} was at {1} now {2}".format(path, user_visible_commit,
                                          requested_hash[0:7]))

    _RunGitCommand(["checkout", "-q", "--detach", requested_hash], cwd=path)

  return 0


if __name__ == "__main__":
  try:
    sys.exit(main())
  except SubprocessFailedException as ex:
    print(str(ex), file=sys.stderr)
    sys.exit(1)
