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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
|
from dulwich.refs import LOCAL_BRANCH_PREFIX
from mercurial import (
bundlerepo,
discovery,
error,
exchange,
exthelper,
hg,
pycompat,
wireprotov1peer,
)
from mercurial.interfaces import repository
from mercurial.utils import urlutil
from . import util
eh = exthelper.exthelper()
class gitrepo(repository.peer):
def __init__(self, ui, path=None, create=False, intents=None, **kwargs):
if create: # pragma: no cover
raise error.Abort(b'Cannot create a git repository.')
self._ui = ui
self.path = path
self.localrepo = None
_peercapabilities = [b'lookup']
def _capabilities(self):
return self._peercapabilities
def capabilities(self):
return self._peercapabilities
@property
def ui(self):
return self._ui
def url(self):
return self.path
@util.makebatchable
def lookup(self, key):
assert isinstance(key, bytes)
# FIXME: this method is supposed to return a 20-byte node hash
return key
def local(self):
if not self.path:
raise error.RepoError
def filtered(self, name: bytes):
assert name == b'visible'
return self
@util.makebatchable
def heads(self):
return []
@util.makebatchable
def listkeys(self, namespace):
if namespace == b'namespaces':
return {b'bookmarks': b''}
elif namespace == b'bookmarks':
if self.localrepo is not None:
handler = self.localrepo.githandler
result = handler.fetch_pack(self.path, heads=[])
# map any git shas that exist in hg to hg shas
stripped_refs = {
ref[len(LOCAL_BRANCH_PREFIX) :]: handler.map_hg_get(val)
or val
for ref, val in result.refs.items()
if ref.startswith(LOCAL_BRANCH_PREFIX)
}
return stripped_refs
return {}
@util.makebatchable
def pushkey(self, namespace, key, old, new):
return False
def branchmap(self):
raise NotImplementedError
def canpush(self):
return True
def close(self):
pass
def debugwireargs(self):
raise NotImplementedError
def getbundle(self):
raise NotImplementedError
def iterbatch(self):
raise NotImplementedError
def known(self):
raise NotImplementedError
def peer(self, path=None, remotehidden=False):
return self
def stream_out(self):
raise NotImplementedError
def unbundle(self):
raise NotImplementedError
def commandexecutor(self):
return wireprotov1peer.peerexecutor(self)
def _submitbatch(self, req):
for op, argsdict in req:
yield None
def _submitone(self, op, args):
return None
instance = gitrepo
def islocal(path):
if util.isgitsshuri(path):
return True
u = urlutil.url(path)
return not u.scheme or u.scheme == b'file'
# defend against tracebacks if we specify -r in 'hg pull'
@eh.wrapfunction(hg, 'addbranchrevs')
def safebranchrevs(orig, lrepo, otherrepo, branches, revs, **kwargs):
revs, co = orig(lrepo, otherrepo, branches, revs, **kwargs)
if isinstance(otherrepo, gitrepo):
# FIXME: Unless it's None, the 'co' result is passed to the lookup()
# remote command. Since our implementation of the lookup() remote
# command is incorrect, we set it to None to avoid a crash later when
# the incorect result of the lookup() remote command would otherwise be
# used. This can, in undocumented corner-cases, result in that a
# different revision is updated to when passing both -u and -r to
# 'hg pull'. An example of such case is in tests/test-addbranchrevs.t
# (for the non-hg-git case).
co = None
return revs, co
@eh.wrapfunction(discovery, 'findcommonoutgoing')
def findcommonoutgoing(orig, repo, other, *args, **kwargs):
if isinstance(other, gitrepo):
heads = repo.githandler.get_refs(other.path)[0]
kw = {}
kw.update(kwargs)
for val, k in zip(
args, ('onlyheads', 'force', 'commoninc', 'portable')
):
kw[k] = val
force = kw.get('force', False)
commoninc = kw.get('commoninc', None)
if commoninc is None:
commoninc = discovery.findcommonincoming(
repo, other, heads=heads, force=force
)
kw['commoninc'] = commoninc
return orig(repo, other, **kw)
return orig(repo, other, *args, **kwargs)
@eh.wrapfunction(bundlerepo, 'getremotechanges')
def getremotechanges(orig, ui, repo, other, onlyheads, *args, **opts):
if isinstance(other, gitrepo):
return repo.githandler.getremotechanges(other, onlyheads)
return orig(ui, repo, other, onlyheads, *args, **opts)
@eh.wrapfunction(exchange, 'pull')
@util.transform_notgit
def exchangepull(
orig, repo, remote, heads=None, force=False, bookmarks=(), **kwargs
):
if isinstance(remote, gitrepo):
pullop = exchange.pulloperation(
repo, remote, heads, force, bookmarks=bookmarks
)
pullop.trmanager = exchange.transactionmanager(
repo, b'pull', remote.url()
)
with repo.wlock(), repo.lock(), pullop.trmanager:
pullop.cgresult = repo.githandler.fetch(remote, heads)
return pullop
else:
return orig(
repo,
remote,
heads=heads,
force=force,
bookmarks=bookmarks,
**kwargs,
)
# TODO figure out something useful to do with the newbranch param
@eh.wrapfunction(exchange, 'push')
@util.transform_notgit
def exchangepush(
orig,
repo,
remote,
force=False,
revs=None,
newbranch=False,
bookmarks=(),
opargs=None,
**kwargs
):
if isinstance(remote, gitrepo):
pushop = exchange.pushoperation(
repo,
remote,
force,
revs,
newbranch,
bookmarks,
**pycompat.strkwargs(opargs or {}),
)
pushop.cgresult = repo.githandler.push(
remote.path, revs, bookmarks, force
)
return pushop
else:
return orig(
repo,
remote,
force,
revs,
newbranch,
bookmarks=bookmarks,
opargs=opargs,
**kwargs,
)
def make_peer(
ui, path, create, intents=None, createopts=None, remotehidden=False
):
return gitrepo(ui, path, create)
|