# -*-python-*-
#
# Copyright (C) 1999-2023 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
# distribution or at http://viewvc.org/license-1.html.
#
# For more information, visit http://viewvc.org/
#
# -----------------------------------------------------------------------

"Version Control lib driver for Subversion repositories"

import os
import os.path
import re
import urllib

_re_url = re.compile('^(http|https|file|svn|svn\+[^:]+)://')

def _canonicalize_path(path):
  import svn.core
  try:
    return svn.core.svn_path_canonicalize(path)
  except AttributeError: # svn_path_canonicalize() appeared in 1.4.0 bindings
    # There's so much more that we *could* do here, but if we're
    # here at all its because there's a really old Subversion in
    # place, and those older Subversion versions cared quite a bit
    # less about the specifics of path canonicalization.
    if re.search(_re_url, path):
      return path.rstrip('/')
    else:
      return os.path.normpath(path)


def canonicalize_rootpath(rootpath):
  # Try to canonicalize the rootpath using Subversion semantics.
  rootpath = _canonicalize_path(rootpath)
  
  # ViewVC's support for local repositories is more complete and more
  # performant than its support for remote ones, so if we're on a
  # Unix-y system and we have a file:/// URL, convert it to a local
  # path instead.
  if os.name == 'posix':
    rootpath_lower = rootpath.lower()
    if rootpath_lower in ['file://localhost',
                          'file://localhost/',
                          'file://',
                          'file:///'
                          ]:
      return '/'
    if rootpath_lower.startswith('file://localhost/'):
      rootpath = os.path.normpath(urllib.unquote(rootpath[16:]))
    elif rootpath_lower.startswith('file:///'):
      rootpath = os.path.normpath(urllib.unquote(rootpath[7:]))

  # Ensure that we have an absolute path (or URL), and return.
  if not re.search(_re_url, rootpath):
    assert os.path.isabs(rootpath)
  return rootpath


def expand_root_parent(parent_path):
  roots = {}
  if re.search(_re_url, parent_path):
    pass
  else:
    # Any subdirectories of PARENT_PATH which themselves have a child
    # "format" are returned as roots.
    assert os.path.isabs(parent_path)
    subpaths = os.listdir(parent_path)
    for rootname in subpaths:
      rootpath = os.path.join(parent_path, rootname)
      if os.path.exists(os.path.join(rootpath, "format")):
        roots[rootname] = canonicalize_rootpath(rootpath)
  return roots


def find_root_in_parent(parent_path, rootname):
  """Search PARENT_PATH for a root named ROOTNAME, returning the
  canonicalized ROOTPATH of the root if found; return None if no such
  root is found."""
  
  if not re.search(_re_url, parent_path):
    assert os.path.isabs(parent_path)
    rootpath = os.path.join(parent_path, rootname)
    format_path = os.path.join(rootpath, "format")
    if os.path.exists(format_path):
      return canonicalize_rootpath(rootpath)
  return None


def SubversionRepository(name, rootpath, authorizer, utilities, config_dir):
  rootpath = canonicalize_rootpath(rootpath)
  if re.search(_re_url, rootpath):
    import svn_ra
    return svn_ra.RemoteSubversionRepository(name, rootpath, authorizer,
                                             utilities, config_dir)
  else:
    import svn_repos
    return svn_repos.LocalSubversionRepository(name, rootpath, authorizer,
                                               utilities, config_dir)
