#!/usr/bin/python
# Copyright 2014 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.


"""Parse a DEPS file and git checkout all of the dependencies.

Args:
  An optional list of deps_os values.

Environment Variables:
  GIT_EXECUTABLE: path to "git" binary; if unset, will look for one of
  ['git', 'git.exe', 'git.bat'] in your default path.

  GIT_SYNC_DEPS_PATH: file to get the dependency list from; if unset,
  will use the file ../DEPS relative to this script's directory.

  GIT_SYNC_DEPS_QUIET: if set to non-empty string, suppress messages.

Git Config:
  To disable syncing of a single repository:
      cd path/to/repository
      git config sync-deps.disable true

  To re-enable sync:
      cd path/to/repository
      git config --unset sync-deps.disable
"""


import os
import subprocess
import sys
import threading

from git_utils import git_executable


DEFAULT_DEPS_PATH = os.path.normpath(
  os.path.join(os.path.dirname(__file__), os.pardir, 'DEPS'))


def usage(deps_file_path = None):
  sys.stderr.write(
    'Usage: run to grab dependencies, with optional platform support:\n')
  sys.stderr.write('  python %s' % __file__)
  if deps_file_path:
    for deps_os in parse_file_to_dict(deps_file_path)['deps_os']:
      sys.stderr.write(' [%s]' % deps_os)
  else:
    sys.stderr.write(' [DEPS_OS...]')
  sys.stderr.write('\n\n')
  sys.stderr.write(__doc__)


def git_repository_sync_is_disabled(git, directory):
  try:
    disable = subprocess.check_output(
      [git, 'config', 'sync-deps.disable'], cwd=directory)
    return disable.lower().strip() in ['true', '1', 'yes', 'on']
  except subprocess.CalledProcessError:
    return False


def is_git_toplevel(git, directory):
  """Return true iff the directory is the top level of a Git repository.

  Args:
    git (string) the git executable

    directory (string) the path into which the repository
              is expected to be checked out.
  """
  try:
    toplevel = subprocess.check_output(
      [git, 'rev-parse', '--show-toplevel'], cwd=directory).strip()
    return os.path.realpath(directory) == os.path.realpath(toplevel)
  except subprocess.CalledProcessError:
    return False


def git_checkout_to_directory(git, repo, checkoutable, directory, verbose):
  """Checkout (and clone if needed) a Git repository.

  Args:
    git (string) the git executable

    repo (string) the location of the repository, suitable
         for passing to `git clone`.

    checkoutable (string) a tag, branch, or commit, suitable for
                 passing to `git checkout`

    directory (string) the path into which the repository
              should be checked out.

    verbose (boolean)

  Raises an exception if any calls to git fail.
  """
  if not os.path.isdir(directory):
    subprocess.check_call(
      [git, 'clone', '--quiet', repo, directory])

  if not is_git_toplevel(git, directory):
    # if the directory exists, but isn't a git repo, you will modify
    # the parent repostory, which isn't what you want.
    sys.stdout.write('%s\n  IS NOT TOP-LEVEL GIT DIRECTORY.\n' % directory)
    return

  # Check to see if this repo is disabled.  Quick return.
  if git_repository_sync_is_disabled(git, directory):
    sys.stdout.write('%s\n  SYNC IS DISABLED.\n' % directory)
    return

  subprocess.check_call([git, 'fetch', '--quiet'], cwd=directory)

  subprocess.check_call(
    [git, 'checkout', '--quiet', checkoutable], cwd=directory)

  if verbose:
    sys.stdout.write('%s\n  @ %s\n' % (directory, checkoutable))  # Success.


def parse_file_to_dict(path):
  dictionary = {}
  execfile(path, dictionary)
  return dictionary


class DepsError(Exception):
  """Raised if deps_os is a bad key.
  """
  pass


def git_sync_deps(deps_file_path, deps_os_list, verbose):
  """Grab dependencies, with optional platform support.

  Args:
    deps_file_path (string) Path to the DEPS file.

    deps_os_list (list of strings) Can be empty list.  List of
                 strings that should each be a key in the deps_os
                 dictionary in the DEPS file.

  Raises DepsError exception and git Exceptions.
  """
  git = git_executable()
  assert git

  deps_file_directory = os.path.dirname(deps_file_path)
  deps = parse_file_to_dict(deps_file_path)
  dependencies = deps['deps'].copy()
  for deps_os in deps_os_list:
    # Add OS-specific dependencies
    if deps_os not in deps['deps_os']:
      raise DepsError(
        'Argument "%s" not found within deps_os keys %r' %
        (deps_os, deps['deps_os'].keys()))
    for dep in deps['deps_os'][deps_os]:
      dependencies[dep] = deps['deps_os'][deps_os][dep]
  list_of_arg_lists = []
  for directory in dependencies:
    if '@' in dependencies[directory]:
      repo, checkoutable = dependencies[directory].split('@', 1)
    else:
      repo, checkoutable = dependencies[directory], 'origin/master'

    relative_directory = os.path.join(deps_file_directory, directory)

    list_of_arg_lists.append(
      (git, repo, checkoutable, relative_directory, verbose))

  multithread(git_checkout_to_directory, list_of_arg_lists)


def multithread(function, list_of_arg_lists):
  # for args in list_of_arg_lists:
  #   function(*args)
  # return
  threads = []
  for args in list_of_arg_lists:
    thread = threading.Thread(None, function, None, args)
    thread.start()
    threads.append(thread)
  for thread in threads:
    thread.join()


def main(argv):
  deps_file_path = os.environ.get('GIT_SYNC_DEPS_PATH', DEFAULT_DEPS_PATH)
  verbose = not bool(os.environ.get('GIT_SYNC_DEPS_QUIET', False))
  try:
    git_sync_deps(deps_file_path, argv, verbose)
    return 0
  except DepsError:
    usage(deps_file_path)
    return 1


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