1# -*-python-*- 2# 3# Copyright (C) 1999-2020 The ViewCVS Group. All Rights Reserved. 4# 5# By using this file, you agree to the terms and conditions set forth in 6# the LICENSE.html file which can be found at the top level of the ViewVC 7# distribution or at http://viewvc.org/license-1.html. 8# 9# For more information, visit http://viewvc.org/ 10# 11# ----------------------------------------------------------------------- 12 13"Version Control lib driver for Subversion repositories" 14 15import os 16import os.path 17import re 18import urllib.parse 19 20_re_url = re.compile('^(http|https|file|svn|svn\+[^:]+)://') 21 22def _canonicalize_path(path): 23 import svn.core 24 return svn.core.svn_path_canonicalize(path).decode('utf-8', 'surrogateescpe') 25 26def canonicalize_rootpath(rootpath): 27 # Try to canonicalize the rootpath using Subversion semantics. 28 rootpath = _canonicalize_path(rootpath) 29 30 # ViewVC's support for local repositories is more complete and more 31 # performant than its support for remote ones, so if we're on a 32 # Unix-y system and we have a file:/// URL, convert it to a local 33 # path instead. 34 if os.name == 'posix': 35 rootpath_lower = rootpath.lower() 36 if rootpath_lower in ['file://localhost', 37 'file://localhost/', 38 'file://', 39 'file:///' 40 ]: 41 return '/' 42 if rootpath_lower.startswith('file://localhost/'): 43 rootpath = os.path.normpath(urllib.parse.unquote(rootpath[16:])) 44 elif rootpath_lower.startswith('file:///'): 45 rootpath = os.path.normpath(urllib.parse.unquote(rootpath[7:])) 46 47 # Ensure that we have an absolute path (or URL), and return. 48 if not re.search(_re_url, rootpath): 49 assert os.path.isabs(rootpath) 50 return rootpath 51 52 53def expand_root_parent(parent_path): 54 roots = {} 55 if re.search(_re_url, parent_path): 56 pass 57 else: 58 # Any subdirectories of PARENT_PATH which themselves have a child 59 # "format" are returned as roots. 60 assert os.path.isabs(parent_path) 61 subpaths = os.listdir(parent_path) 62 for rootname in subpaths: 63 rootpath = os.path.join(parent_path, rootname) 64 if os.path.exists(os.path.join(rootpath, "format")): 65 roots[rootname] = canonicalize_rootpath(rootpath) 66 return roots 67 68 69def find_root_in_parent(parent_path, rootname): 70 """Search PARENT_PATH for a root named ROOTNAME, returning the 71 canonicalized ROOTPATH of the root if found; return None if no such 72 root is found.""" 73 74 if not re.search(_re_url, parent_path): 75 assert os.path.isabs(parent_path) 76 rootpath = os.path.join(parent_path, rootname) 77 format_path = os.path.join(rootpath, "format") 78 if os.path.exists(format_path): 79 return canonicalize_rootpath(rootpath) 80 return None 81 82 83def SubversionRepository(name, rootpath, authorizer, utilities, config_dir, 84 encoding='utf-8'): 85 rootpath = canonicalize_rootpath(rootpath) 86 if re.search(_re_url, rootpath): 87 from . import svn_ra 88 return svn_ra.RemoteSubversionRepository(name, rootpath, authorizer, 89 utilities, config_dir, encoding) 90 else: 91 from . import svn_repos 92 return svn_repos.LocalSubversionRepository(name, rootpath, authorizer, 93 utilities, config_dir, encoding) 94