#
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
import os
import shutil

from error import GitError
from error import ManifestParseError
from git_command import GitCommand
from git_config import GitConfig
from git_config import IsId
from manifest import Manifest
from progress import Progress
from project import RemoteSpec
from project import Project
from project import MetaProject
from project import R_HEADS
from project import HEAD
from project import _lwrite

import manifest_xml

GITLINK = '160000'

def _rmdir(dir, top):
  while dir != top:
    try:
      os.rmdir(dir)
    except OSError:
      break
    dir = os.path.dirname(dir)

def _rmref(gitdir, ref):
  os.remove(os.path.join(gitdir, ref))
  log = os.path.join(gitdir, 'logs', ref)
  if os.path.exists(log):
    os.remove(log)
    _rmdir(os.path.dirname(log), gitdir)

def _has_gitmodules(d):
  return os.path.exists(os.path.join(d, '.gitmodules'))

class SubmoduleManifest(Manifest):
  """manifest from .gitmodules file"""

  @classmethod
  def Is(cls, repodir):
    return _has_gitmodules(os.path.dirname(repodir)) \
        or _has_gitmodules(os.path.join(repodir, 'manifest')) \
        or _has_gitmodules(os.path.join(repodir, 'manifests'))

  @classmethod
  def IsBare(cls, p):
    try:
      p.bare_git.cat_file('-e', '%s:.gitmodules' % p.GetRevisionId())
    except GitError:
      return False
    return True

  def __init__(self, repodir):
    Manifest.__init__(self, repodir)

    gitdir = os.path.join(repodir, 'manifest.git')
    config = GitConfig.ForRepository(gitdir = gitdir)

    if config.GetBoolean('repo.mirror'):
      worktree = os.path.join(repodir, 'manifest')
      relpath = None
    else:
      worktree = self.topdir
      relpath  = '.'

    self.manifestProject = MetaProject(self, '__manifest__',
      gitdir   = gitdir,
      worktree = worktree,
      relpath  = relpath)
    self._modules = GitConfig(os.path.join(worktree, '.gitmodules'),
                              pickleFile = os.path.join(
                                repodir, '.repopickle_gitmodules'
                              ))
    self._review = GitConfig(os.path.join(worktree, '.review'),
                             pickleFile = os.path.join(
                               repodir, '.repopickle_review'
                             ))
    self._Unload()

  @property
  def projects(self):
    self._Load()
    return self._projects

  def InitBranch(self):
    m = self.manifestProject
    if m.CurrentBranch is None:
      b = m.revisionExpr
      if b.startswith(R_HEADS):
        b = b[len(R_HEADS):]
      return m.StartBranch(b)
    return True

  def SetMRefs(self, project):
    if project.revisionId is None:
      # Special project, e.g. the manifest or repo executable.
      #
      return

    ref = 'refs/remotes/m'
    cur = project.bare_ref.get(ref)
    exp = project.revisionId
    if cur != exp:
      msg = 'manifest set to %s' % exp
      project.bare_git.UpdateRef(ref, exp, message = msg, detach = True)

    ref = 'refs/remotes/m-revision'
    cur = project.bare_ref.symref(ref)
    exp = project.revisionExpr
    if exp is None:
      if cur:
        _rmref(project.gitdir, ref)
    elif cur != exp:
      remote = project.GetRemote(project.remote.name)
      dst = remote.ToLocal(exp)
      msg = 'manifest set to %s (%s)' % (exp, dst)
      project.bare_git.symbolic_ref('-m', msg, ref, dst)

  def Upgrade_Local(self, old):
    if isinstance(old, manifest_xml.XmlManifest):
      self.FromXml_Local_1(old, checkout=True)
      self.FromXml_Local_2(old)
    else:
      raise ManifestParseError, 'cannot upgrade manifest'

  def FromXml_Local_1(self, old, checkout):
    os.rename(old.manifestProject.gitdir,
              os.path.join(old.repodir, 'manifest.git'))

    oldmp = old.manifestProject
    oldBranch = oldmp.CurrentBranch
    b = oldmp.GetBranch(oldBranch).merge
    if not b:
      raise ManifestParseError, 'cannot upgrade manifest'
    if b.startswith(R_HEADS):
      b = b[len(R_HEADS):]

    newmp = self.manifestProject
    self._CleanOldMRefs(newmp)
    if oldBranch != b:
      newmp.bare_git.branch('-m', oldBranch, b)
      newmp.config.ClearCache()

    old_remote = newmp.GetBranch(b).remote.name
    act_remote = self._GuessRemoteName(old)
    if old_remote != act_remote:
      newmp.bare_git.remote('rename', old_remote, act_remote)
      newmp.config.ClearCache()
    newmp.remote.name = act_remote
    print >>sys.stderr, "Assuming remote named '%s'" % act_remote

    if checkout:
      for p in old.projects.values():
        for c in p.copyfiles:
          if os.path.exists(c.abs_dest):
            os.remove(c.abs_dest)
      newmp._InitWorkTree()
    else:
      newmp._LinkWorkTree()

    _lwrite(os.path.join(newmp.worktree,'.git',HEAD),
            'ref: refs/heads/%s\n' % b)

  def _GuessRemoteName(self, old):
    used = {}
    for p in old.projects.values():
      n = p.remote.name
      used[n] = used.get(n, 0) + 1

    remote_name = 'origin'
    remote_used = 0
    for n in used.keys():
      if remote_used < used[n]:
        remote_used = used[n]
        remote_name = n
    return remote_name

  def FromXml_Local_2(self, old):
    shutil.rmtree(old.manifestProject.worktree)
    os.remove(old._manifestFile)

    my_remote = self._Remote().name
    new_base = os.path.join(self.repodir, 'projects')
    old_base = os.path.join(self.repodir, 'projects.old')
    os.rename(new_base, old_base)
    os.makedirs(new_base)

    info = []
    pm = Progress('Converting projects', len(self.projects))
    for p in self.projects.values():
      pm.update()

      old_p = old.projects.get(p.name)
      old_gitdir = os.path.join(old_base, '%s.git' % p.relpath)
      if not os.path.isdir(old_gitdir):
        continue

      parent = os.path.dirname(p.gitdir)
      if not os.path.isdir(parent):
        os.makedirs(parent)
      os.rename(old_gitdir, p.gitdir)
      _rmdir(os.path.dirname(old_gitdir), self.repodir)

      if not os.path.isdir(p.worktree):
        os.makedirs(p.worktree)

      if os.path.isdir(os.path.join(p.worktree, '.git')):
        p._LinkWorkTree(relink=True)

      self._CleanOldMRefs(p)
      if old_p and old_p.remote.name != my_remote:
        info.append("%s/: renamed remote '%s' to '%s'" \
                    % (p.relpath, old_p.remote.name, my_remote))
        p.bare_git.remote('rename', old_p.remote.name, my_remote)
        p.config.ClearCache()

      self.SetMRefs(p)
    pm.end()
    for i in info:
      print >>sys.stderr, i

  def _CleanOldMRefs(self, p):
    all_refs = p._allrefs
    for ref in all_refs.keys():
      if ref.startswith(manifest_xml.R_M):
        if p.bare_ref.symref(ref) != '':
          _rmref(p.gitdir, ref)
        else:
          p.bare_git.DeleteRef(ref, all_refs[ref])

  def FromXml_Definition(self, old):
    """Convert another manifest representation to this one.
    """
    mp = self.manifestProject
    gm = self._modules
    gr = self._review

    fd = open(os.path.join(mp.worktree, '.gitignore'), 'ab')
    fd.write('/.repo\n')
    fd.close()

    sort_projects = list(old.projects.keys())
    sort_projects.sort()

    b = mp.GetBranch(mp.CurrentBranch).merge
    if b.startswith(R_HEADS):
      b = b[len(R_HEADS):]

    info = []
    pm = Progress('Converting manifest', len(sort_projects))
    for p in sort_projects:
      pm.update()
      p = old.projects[p]

      gm.SetString('submodule.%s.path' % p.name, p.relpath)
      gm.SetString('submodule.%s.url' % p.name, p.remote.url)

      if gr.GetString('review.url') is None:
        gr.SetString('review.url', p.remote.review)
      elif gr.GetString('review.url') != p.remote.review:
        gr.SetString('review.%s.url' % p.name, p.remote.review)

      r = p.revisionExpr
      if r and not IsId(r):
        if r.startswith(R_HEADS):
          r = r[len(R_HEADS):]
        if r == b:
          r = '.'
        gm.SetString('submodule.%s.revision' % p.name, r)

      for c in p.copyfiles:
        info.append('Moved %s out of %s' % (c.src, p.relpath))
        c._Copy()
        p.work_git.rm(c.src)
        mp.work_git.add(c.dest)

      self.SetRevisionId(p.relpath, p.GetRevisionId())
    mp.work_git.add('.gitignore', '.gitmodules', '.review')
    pm.end()
    for i in info:
      print >>sys.stderr, i

  def _Unload(self):
    self._loaded = False
    self._projects = {}
    self._revisionIds = None
    self.branch = None

  def _Load(self):
    if not self._loaded:
      f = os.path.join(self.repodir, manifest_xml.LOCAL_MANIFEST_NAME)
      if os.path.exists(f):
        print >>sys.stderr, 'warning: ignoring %s' % f

      m = self.manifestProject
      b = m.CurrentBranch
      if not b:
        raise ManifestParseError, 'manifest cannot be on detached HEAD'
      b = m.GetBranch(b).merge
      if b.startswith(R_HEADS):
        b = b[len(R_HEADS):]
      self.branch = b
      m.remote.name = self._Remote().name

      self._ParseModules()

      if self.IsMirror:
        self._AddMetaProjectMirror(self.repoProject)
        self._AddMetaProjectMirror(self.manifestProject)

      self._loaded = True

  def _ParseModules(self):
    byPath = dict()
    for name in self._modules.GetSubSections('submodule'):
      p = self._ParseProject(name)
      if self._projects.get(p.name):
        raise ManifestParseError, 'duplicate project "%s"' % p.name
      if byPath.get(p.relpath):
        raise ManifestParseError, 'duplicate path "%s"' % p.relpath
      self._projects[p.name] = p
      byPath[p.relpath] = p

    for relpath in self._allRevisionIds.keys():
      if relpath not in byPath:
        raise ManifestParseError, \
          'project "%s" not in .gitmodules' \
          % relpath

  def _Remote(self):
    m = self.manifestProject
    b = m.GetBranch(m.CurrentBranch)
    return b.remote

  def _ResolveUrl(self, url):
    if url.startswith('./') or url.startswith('../'):
      base = self._Remote().url
      try:
        base = base[:base.rindex('/')+1]
      except ValueError:
        base = base[:base.rindex(':')+1]
      if url.startswith('./'):
        url = url[2:]
      while '/' in base and url.startswith('../'):
        base = base[:base.rindex('/')+1]
        url = url[3:]
      return base + url
    return url

  def _GetRevisionId(self, path):
    return self._allRevisionIds.get(path)

  @property
  def _allRevisionIds(self):
    if self._revisionIds is None:
      a = dict()
      p = GitCommand(self.manifestProject,
                     ['ls-files','-z','--stage'],
                     capture_stdout = True)
      for line in p.process.stdout.read().split('\0')[:-1]:
        l_info, l_path = line.split('\t', 2)
        l_mode, l_id, l_stage = l_info.split(' ', 2)
        if l_mode == GITLINK and l_stage == '0':
          a[l_path] = l_id
      p.Wait()
      self._revisionIds = a
    return self._revisionIds

  def SetRevisionId(self, path, id):
    self.manifestProject.work_git.update_index(
      '--add','--cacheinfo', GITLINK, id, path)

  def _ParseProject(self, name):
    gm = self._modules
    gr = self._review

    path = gm.GetString('submodule.%s.path' % name)
    if not path:
      path = name

    revId = self._GetRevisionId(path)
    if not revId:
      raise ManifestParseError(
        'submodule "%s" has no revision at "%s"' \
        % (name, path))

    url = gm.GetString('submodule.%s.url' % name)
    if not url:
      url = name
    url = self._ResolveUrl(url)

    review = gr.GetString('review.%s.url' % name)
    if not review:
      review = gr.GetString('review.url')
    if not review:
      review = self._Remote().review

    remote = RemoteSpec(self._Remote().name, url, review)
    revExpr = gm.GetString('submodule.%s.revision' % name)
    if revExpr == '.':
      revExpr = self.branch

    if self.IsMirror:
      relpath = None
      worktree = None
      gitdir = os.path.join(self.topdir, '%s.git' % name)
    else:
      worktree = os.path.join(self.topdir, path)
      gitdir = os.path.join(self.repodir, 'projects/%s.git' % name)

    return Project(manifest = self,
                   name = name,
                   remote = remote,
                   gitdir = gitdir,
                   worktree = worktree,
                   relpath = path,
                   revisionExpr = revExpr,
                   revisionId = revId)

  def _AddMetaProjectMirror(self, m):
    m_url = m.GetRemote(m.remote.name).url
    if m_url.endswith('/.git'):
      raise ManifestParseError, 'refusing to mirror %s' % m_url

    name = self._GuessMetaName(m_url)
    if name.endswith('.git'):
      name = name[:-4]

    if name not in self._projects:
      m.PreSync()
      gitdir = os.path.join(self.topdir, '%s.git' % name)
      project = Project(manifest = self,
                        name = name,
                        remote = RemoteSpec(self._Remote().name, m_url),
                        gitdir = gitdir,
                        worktree = None,
                        relpath = None,
                        revisionExpr = m.revisionExpr,
                        revisionId = None)
      self._projects[project.name] = project

  def _GuessMetaName(self, m_url):
    parts = m_url.split('/')
    name = parts[-1]
    parts = parts[0:-1]
    s = len(parts) - 1
    while s > 0:
      l = '/'.join(parts[0:s]) + '/'
      r = '/'.join(parts[s:]) + '/'
      for p in self._projects.values():
        if p.name.startswith(r) and p.remote.url.startswith(l):
          return r + name
      s -= 1
    return m_url[m_url.rindex('/') + 1:]
