1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
# git.py - git server bridge
#
# Copyright 2008 Scott Chacon <schacon at gmail dot com>
# also some code (and help) borrowed from durin42
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
# global modules
import os
from mercurial import (
bookmarks,
exthelper,
hg,
localrepo,
)
from mercurial.utils import urlutil
# local modules
from . import gitrepo
from . import util
eh = exthelper.exthelper()
def isgitdir(path):
"""True if the given file path is a git repo."""
if os.path.exists(os.path.join(path, b'.hg')):
return False
if os.path.exists(os.path.join(path, b'.git')):
# is full git repo
return True
if (
os.path.exists(os.path.join(path, b'HEAD'))
and os.path.exists(os.path.join(path, b'objects'))
and os.path.exists(os.path.join(path, b'refs'))
):
# is bare git repo
return True
return False
class RepoFactory:
"""thin wrapper to dispatch between git repos and mercurial ones"""
__slots__ = ('__orig',)
def __init__(self, orig):
self.__orig = orig
@property
def islocal(self):
'''indirection that allows us to only claim we're local if the wrappee is'''
if hasattr(self.__orig, 'islocal'):
return self.__islocal
else:
raise AttributeError('islocal')
def __islocal(self, path: bytes) -> bool:
if isgitdir(path):
return True
# detect git ssh urls (which mercurial thinks is a file-like path)
if util.isgitsshuri(path):
return False
return self.__orig.islocal(path)
def instance(self, ui, path, *args, **kwargs):
if isinstance(path, bytes):
url = urlutil.url(path)
else:
url = path.url
p = url.localpath()
# detect git ssh urls (which mercurial thinks is a file-like path)
if isgitdir(p) or util.isgitsshuri(p) or p.endswith(b'.git'):
fn = gitrepo.instance
else:
fn = self.__orig.instance
return fn(ui, path, *args, **kwargs)
def make_peer(self, ui, path, *args, **kwargs):
p = path.url.localpath()
# detect git ssh urls (which mercurial thinks is a file-like path)
if isgitdir(p) or util.isgitsshuri(p) or p.endswith(b'.git'):
fn = gitrepo.instance
elif hasattr(self.__orig, 'make_peer'):
fn = self.__orig.make_peer
return fn(ui, path, *args, **kwargs)
@eh.wrapfunction(hg, 'defaultdest')
def defaultdest(orig, source):
if source.endswith(b'.git'):
return orig(source[:-4])
return orig(source)
@eh.wrapfunction(hg, 'peer')
def peer(orig, uiorrepo, *args, **opts):
newpeer = orig(uiorrepo, *args, **opts)
if isinstance(newpeer, gitrepo.gitrepo):
if isinstance(uiorrepo, localrepo.localrepository):
newpeer.localrepo = uiorrepo
return newpeer
@eh.wrapfunction(hg, 'clone')
def clone(orig, *args, **opts):
srcpeer, destpeer = orig(*args, **opts)
# HACK: suppress bookmark activation with `--noupdate`
if isinstance(srcpeer, gitrepo.gitrepo) and not opts.get('update'):
bookmarks.deactivate(destpeer._repo)
return srcpeer, destpeer
@eh.wrapfunction(urlutil.path, '_isvalidlocalpath')
def isvalidlocalpath(orig, self, path):
return orig(self, path) or isgitdir(path)
@eh.wrapfunction(urlutil.url, 'islocal')
def isurllocal(orig, path):
# recognise git scp-style paths when cloning
return orig(path) and not util.isgitsshuri(path._origpath)
@eh.wrapfunction(hg, 'islocal')
def islocal(orig, path):
# recognise git scp-style paths when cloning
return orig(path) and not util.isgitsshuri(path)
@eh.wrapfunction(urlutil, 'hasscheme')
def hasscheme(orig, path):
# recognise git scp-style paths
return orig(path) or util.isgitsshuri(path)
@eh.extsetup
def extsetup(ui):
hg.peer_schemes[b'https'] = RepoFactory(hg.peer_schemes[b'https'])
hg.peer_schemes[b'http'] = RepoFactory(hg.peer_schemes[b'http'])
hg.repo_schemes[b'file'] = RepoFactory(hg.repo_schemes[b'file'])
# support for `hg clone git://github.com/defunkt/facebox.git`
# also hg clone git+ssh://git@github.com/schacon/simplegit.git
for _scheme in util.gitschemes:
hg.peer_schemes[_scheme] = gitrepo
|