#!/usr/bin/env python
# Copyright 2013 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.
#
# Usage:
#    gclient-new-workdir.py <repository> <new_workdir> [<branch>]
#

import os
import shutil
import subprocess
import sys
import textwrap


def print_err(msg):
  print >> sys.stderr, msg


def usage(msg=None):

  if msg is not None:
    print_err('\n' + textwrap.dedent(msg) + '\n')
    usage_msg = 'Run without arguments to get usage help.'
  else:
    usage_msg = '''\
    usage: %s <repository> <new_workdir>

    Clone an existing gclient directory, taking care of all sub-repositories
    Works similarly to 'git new-workdir'.

    <repository> should contain a .gclient file
    <new_workdir> must not exist
    ''' % os.path.basename(sys.argv[0])

  print_err(textwrap.dedent(usage_msg))
  sys.exit(1)


def parse_options():
  if sys.platform == 'win32':
    usage('This script cannot run on Windows because it uses symlinks.')

  if len(sys.argv) != 3:
    usage()

  repository = os.path.abspath(sys.argv[1])
  new_workdir = sys.argv[2]

  if not os.path.exists(repository):
    usage('Repository does not exist: ' + repository)

  if os.path.exists(new_workdir):
    usage('New workdir already exists: ' + new_workdir)

  return repository, new_workdir


def main():
  repository, new_workdir = parse_options()

  gclient = os.path.join(repository, '.gclient')
  if not os.path.exists(gclient):
    print_err('No .gclient file: ' + gclient)

  os.makedirs(new_workdir)
  os.symlink(gclient, os.path.join(new_workdir, '.gclient'))

  for root, dirs, _ in os.walk(repository):
    if '.git' in dirs:
      workdir = root.replace(repository, new_workdir, 1)
      make_workdir(os.path.join(root, '.git'),
                   os.path.join(workdir, '.git'))


def make_workdir(repository, new_workdir):
  print('Creating: ' + new_workdir)
  os.makedirs(new_workdir)

  GIT_DIRECTORY_WHITELIST = [
    'config',
    'info',
    'hooks',
    'logs/refs',
    'objects',
    'packed-refs',
    'refs',
    'remotes',
    'rr-cache',
    'svn'
  ]

  for entry in GIT_DIRECTORY_WHITELIST:
    make_symlink(repository, new_workdir, entry)

  shutil.copy2(os.path.join(repository, 'HEAD'),
               os.path.join(new_workdir, 'HEAD'))
  subprocess.check_call(['git', 'checkout', '-f'],
                        cwd=new_workdir.rstrip('.git'))


def make_symlink(repository, new_workdir, link):
  if not os.path.exists(os.path.join(repository, link)):
    return
  link_dir = os.path.dirname(os.path.join(new_workdir, link))
  if not os.path.exists(link_dir):
    os.makedirs(link_dir)
  os.symlink(os.path.join(repository, link), os.path.join(new_workdir, link))


if __name__ == '__main__':
  sys.exit(main())