#!/usr/bin/python
#
# Copyright 2010 Google Inc. All Rights Reserved.

__author__ = 'asharif@google.com (Ahmad Sharif)'

import datetime
import optparse
import os
import re
import socket
import sys
import tempfile

from automation.clients.helper import perforce
from utils import command_executer
from utils import logger
from utils import misc


def GetCanonicalMappings(mappings):
  canonical_mappings = []
  for mapping in mappings:
    remote_path, local_path = mapping.split()
    if local_path.endswith('/') and not remote_path.endswith('/'):
      local_path = os.path.join(local_path, os.path.basename(remote_path))
    remote_path = remote_path.lstrip('/').split('/', 1)[1]
    canonical_mappings.append(perforce.PathMapping(remote_path, local_path))
  return canonical_mappings


def SplitMapping(mapping):
  parts = mapping.split()
  assert len(parts) <= 2, 'Mapping %s invalid' % mapping
  remote_path = parts[0]
  if len(parts) == 2:
    local_path = parts[1]
  else:
    local_path = '.'
  return remote_path, local_path


class Repo(object):
  def __init__(self, no_create_tmp_dir=False):
    self.repo_type = None
    self.address = None
    self.mappings = None
    self.revision = None
    self.ignores = ['.gitignore', '.p4config', 'README.google']
    if no_create_tmp_dir:
      self._root_dir = None
    else:
      self._root_dir = tempfile.mkdtemp()
    self._ce = command_executer.GetCommandExecuter()
    self._logger = logger.GetLogger()

  def PullSources(self):
    """Pull all sources into an internal dir."""
    pass

  def SetupForPush(self):
    """Setup a repository for pushing later."""
    pass

  def PushSources(self, commit_message=None, dry_run=False, message_file=None):
    """Push to the external repo with the commit message."""
    pass

  def _RsyncExcludingRepoDirs(self, source_dir, dest_dir):
    for f in os.listdir(source_dir):
      if f in [".git", ".svn", ".p4config"]:
        continue
      dest_file = os.path.join(dest_dir, f)
      source_file = os.path.join(source_dir, f)
      if os.path.exists(dest_file):
        command = "rm -rf %s" % dest_file
        self._ce.RunCommand(command)
      command = "rsync -a %s %s" % (source_file, dest_dir)
      self._ce.RunCommand(command)
    return 0

  def MapSources(self, dest_dir):
    """Copy sources from the internal dir to root_dir."""
    return self._RsyncExcludingRepoDirs(self._root_dir, dest_dir)

  def GetRoot(self):
    return self._root_dir

  def CleanupRoot(self):
    command = 'rm -rf %s' % self._root_dir
    return self._ce.RunCommand(command)

  def __str__(self):
    return '\n'.join(str(s) for s in [self.repo_type,
                                      self.address,
                                      self.mappings])


# Note - this type of repo is used only for "readonly", in other words, this
# only serves as a incoming repo.
class FileRepo(Repo):
  def __init__(self, address, ignores=None):
    Repo.__init__(self, no_create_tmp_dir=True)
    self.repo_type = 'file'
    self.address = address
    self.mappings = None
    self.branch = None
    self.revision = '{0} (as of "{1}")'.format(address, datetime.datetime.now())
    self.gerrit = None
    self._root_dir = self.address

  def CleanupRoot(self):
    """Override to prevent deletion."""
    pass


class P4Repo(Repo):
  def __init__(self, address, mappings, revision=None):
    Repo.__init__(self)
    self.repo_type = 'p4'
    self.address = address
    self.mappings = mappings
    self.revision = revision

  def PullSources(self):
    client_name = socket.gethostname()
    client_name += tempfile.mkstemp()[1].replace('/', '-')
    mappings = self.mappings
    p4view = perforce.View('depot2',
                           GetCanonicalMappings(mappings))
    p4client = perforce.CommandsFactory(self._root_dir, p4view,
                                        name=client_name)
    command = p4client.SetupAndDo(p4client.Sync(self.revision))
    ret = self._ce.RunCommand(command)
    assert ret == 0, 'Could not setup client.'
    command = p4client.InCheckoutDir(p4client.SaveCurrentCLNumber())
    ret, o, _ = self._ce.RunCommand(command, return_output=True)
    assert ret == 0, 'Could not get version from client.'
    self.revision = re.search('^\d+$', o.strip(), re.MULTILINE).group(0)
    command = p4client.InCheckoutDir(p4client.Remove())
    ret = self._ce.RunCommand(command)
    assert ret == 0, 'Could not delete client.'
    return 0


class SvnRepo(Repo):
  def __init__(self, address, mappings):
    Repo.__init__(self)
    self.repo_type = 'svn'
    self.address = address
    self.mappings = mappings

  def PullSources(self):
    with misc.WorkingDirectory(self._root_dir):
      for mapping in self.mappings:
        remote_path, local_path = SplitMapping(mapping)
        command = 'svn co %s/%s %s' % (self.address, remote_path, local_path)
      ret = self._ce.RunCommand(command)
      if ret: return ret

      self.revision = ''
      for mapping in self.mappings:
        remote_path, local_path = SplitMapping(mapping)
        command = 'cd %s && svnversion -c .' % (local_path)
        ret, o, _ = self._ce.RunCommand(command, return_output=True)
        self.revision += o.strip().split(":")[-1]
        if ret: return ret
    return 0


class GitRepo(Repo):
  def __init__(self, address, branch, mappings=None, ignores=None, gerrit=None):
    Repo.__init__(self)
    self.repo_type = 'git'
    self.address = address
    self.branch = branch or 'master'
    if ignores:
      self.ignores += ignores
    self.mappings = mappings
    self.gerrit = gerrit

  def _CloneSources(self):
    with misc.WorkingDirectory(self._root_dir):
      command = 'git clone %s .' % (self.address)
      return self._ce.RunCommand(command)

  def PullSources(self):
    with misc.WorkingDirectory(self._root_dir):
      ret = self._CloneSources()
      if ret: return ret

      command = 'git checkout %s' % self.branch
      ret = self._ce.RunCommand(command)
      if ret: return ret

      command = 'git describe --always'
      ret, o, _ = self._ce.RunCommand(command, return_output=True)
      self.revision = o.strip()
      return ret

  def SetupForPush(self):
    with misc.WorkingDirectory(self._root_dir):
      ret = self._CloneSources()
      logger.GetLogger().LogFatalIf(ret, 'Could not clone git repo %s.' %
                                    self.address)

      command = 'git branch -a | grep -wq %s' % self.branch
      ret = self._ce.RunCommand(command)

      if ret == 0:
        if self.branch != 'master':
          command = ('git branch --track %s remotes/origin/%s' %
                     (self.branch, self.branch))
        else:
          command = 'pwd'
        command += '&& git checkout %s' % self.branch
      else:
        command = 'git symbolic-ref HEAD refs/heads/%s' % self.branch
      command += '&& rm -rf *'
      ret = self._ce.RunCommand(command)
      return ret

  def CommitLocally(self, commit_message=None, message_file=None):
    with misc.WorkingDirectory(self._root_dir):
      command = 'pwd'
      for ignore in self.ignores:
        command += '&& echo \'%s\' >> .git/info/exclude' % ignore
      command += '&& git add -Av .'
      if message_file:
        message_arg = '-F %s' % message_file
      elif commit_message:
        message_arg = '-m \'%s\'' % commit_message
      else:
        raise Exception("No commit message given!")
      command += '&& git commit -v %s' % message_arg
      return self._ce.RunCommand(command)

  def PushSources(self, commit_message=None, dry_run=False, message_file=None):
    ret = self.CommitLocally(commit_message, message_file)
    if ret: return ret
    push_args = ''
    if dry_run:
      push_args += ' -n '
    with misc.WorkingDirectory(self._root_dir):
      if self.gerrit:
        label = 'somelabel'
        command = 'git remote add %s %s' % (label, self.address)
        command += ('&& git push %s %s HEAD:refs/for/master' %
                    (push_args,label))
      else:
        command = 'git push -v %s origin %s:%s' % (push_args, self.branch,
                                                   self.branch)
      ret = self._ce.RunCommand(command)
    return ret

  def MapSources(self, root_dir):
    if not self.mappings:
      self._RsyncExcludingRepoDirs(self._root_dir, root_dir)
      return
    with misc.WorkingDirectory(self._root_dir):
      for mapping in self.mappings:
        remote_path, local_path = SplitMapping(mapping)
        remote_path.rstrip('...')
        local_path.rstrip('...')
        full_local_path = os.path.join(root_dir, local_path)
        ret = self._RsyncExcludingRepoDirs(remote_path, full_local_path)
        if ret: return ret
    return 0


class RepoReader(object):
  def __init__(self, filename):
    self.filename = filename
    self.main_dict = {}
    self.input_repos = []
    self.output_repos = []

  def ParseFile(self):
    with open(self.filename) as f:
      self.main_dict = eval(f.read())
      self.CreateReposFromDict(self.main_dict)
    return [self.input_repos, self.output_repos]

  def CreateReposFromDict(self, main_dict):
    for key, repo_list in main_dict.items():
      for repo_dict in repo_list:
        repo = self.CreateRepoFromDict(repo_dict)
        if key == 'input':
          self.input_repos.append(repo)
        elif key == 'output':
          self.output_repos.append(repo)
        else:
          logger.GetLogger().LogFatal('Unknown key: %s found' % key)

  def CreateRepoFromDict(self, repo_dict):
    repo_type = repo_dict.get('type', None)
    repo_address = repo_dict.get('address', None)
    repo_mappings = repo_dict.get('mappings', None)
    repo_ignores = repo_dict.get('ignores', None)
    repo_branch = repo_dict.get('branch', None)
    gerrit = repo_dict.get('gerrit', None)
    revision = repo_dict.get('revision', None)

    if repo_type == 'p4':
      repo = P4Repo(repo_address,
                    repo_mappings,
                    revision=revision)
    elif repo_type == 'svn':
      repo = SvnRepo(repo_address,
                     repo_mappings)
    elif repo_type == 'git':
      repo = GitRepo(repo_address,
                     repo_branch,
                     mappings=repo_mappings,
                     ignores=repo_ignores,
                     gerrit=gerrit)
    elif repo_type == 'file':
      repo = FileRepo(repo_address)
    else:
      logger.GetLogger().LogFatal('Unknown repo type: %s' % repo_type)
    return repo


@logger.HandleUncaughtExceptions
def Main(argv):
  parser = optparse.OptionParser()
  parser.add_option('-i',
                    '--input_file',
                    dest='input_file',
                    help='The input file that contains repo descriptions.')

  parser.add_option('-n',
                    '--dry_run',
                    dest='dry_run',
                    action='store_true',
                    default=False,
                    help='Do a dry run of the push.')

  parser.add_option('-F',
                    '--message_file',
                    dest='message_file',
                    default=None,
                    help='Use contents of the log file as the commit message.')

  options = parser.parse_args(argv)[0]
  if not options.input_file:
    parser.print_help()
    return 1
  rr = RepoReader(options.input_file)
  [input_repos, output_repos] = rr.ParseFile()

  # Make sure FileRepo is not used as output destination.
  for output_repo in output_repos:
    if output_repo.repo_type == 'file':
      logger.GetLogger().LogFatal(
        'FileRepo is only supported as an input repo.')

  for output_repo in output_repos:
    ret = output_repo.SetupForPush()
    if ret: return ret

  input_revisions = []
  for input_repo in input_repos:
    ret = input_repo.PullSources()
    if ret: return ret
    input_revisions.append(input_repo.revision)

  for input_repo in input_repos:
    for output_repo in output_repos:
      ret = input_repo.MapSources(output_repo.GetRoot())
      if ret: return ret

  commit_message = 'Synced repos to: %s' % ','.join(input_revisions)
  for output_repo in output_repos:
    ret = output_repo.PushSources(commit_message=commit_message,
                                  dry_run=options.dry_run,
                                  message_file=options.message_file)
    if ret: return ret

  if not options.dry_run:
    for output_repo in output_repos:
      output_repo.CleanupRoot()
    for input_repo in input_repos:
      input_repo.CleanupRoot()

  return ret


if __name__ == '__main__':
  retval = Main(sys.argv)
  sys.exit(retval)
