# HG changeset patch # User Gregory Szorc # Date 2017-08-10 06:52:25 # Node ID 707750e5310bfef867740befde355c79a959c912 # Parent a0aad86b3b6af9ca878857368f7ac55fdbe1e09c localrepo: use peer interfaces We now have a formal abstract base class for peers. Let's transition the peer classes in localrepo to it. As part of the transition, we reorder methods so they are grouped by interface and match the order they are defined in the interface. We also had to change self.ui from an instance attribute to a property to satisfy the @abstractproperty requirement. As part of this change, we uncover the first "bug" as part of enforcing interfaces: stream_out() wasn't implemented on localpeer! This isn't technically a bug since the repo isn't advertising the stream capability, so clients shouldn't be attempting to call it. But I don't think there's a good reason why this is the case. We implement a dummy method to satisfy the interface requriements. We can make localpeer instances streamable as a future enhancement. # no-check-commit Differential Revision: https://phab.mercurial-scm.org/D335 diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -49,6 +49,7 @@ from . import ( phases, pushkey, pycompat, + repository, repoview, revset, revsetlang, @@ -144,43 +145,52 @@ moderncaps = {'lookup', 'branchmap', 'pu 'unbundle'} legacycaps = moderncaps.union({'changegroupsubset'}) -class localpeer(peer.peerrepository): +class localpeer(repository.peer): '''peer for a local repo; reflects only the most recent API''' def __init__(self, repo, caps=None): + super(localpeer, self).__init__() + if caps is None: caps = moderncaps.copy() - peer.peerrepository.__init__(self) self._repo = repo.filtered('served') - self.ui = repo.ui + self._ui = repo.ui self._caps = repo._restrictcapabilities(caps) + # Begin of _basepeer interface. + + @util.propertycache + def ui(self): + return self._ui + + def url(self): + return self._repo.url() + + def local(self): + return self._repo + + def peer(self): + return self + + def canpush(self): + return True + def close(self): self._repo.close() - def _capabilities(self): - return self._caps - - def local(self): - return self._repo + # End of _basepeer interface. - def canpush(self): - return True - - def url(self): - return self._repo.url() - - def lookup(self, key): - return self._repo.lookup(key) + # Begin of _basewirecommands interface. def branchmap(self): return self._repo.branchmap() - def heads(self): - return self._repo.heads() + def capabilities(self): + return self._caps - def known(self, nodes): - return self._repo.known(nodes) + def debugwireargs(self, one, two, three=None, four=None, five=None): + """Used to test argument passing over the wire""" + return "%s %s %s %s %s" % (one, two, three, four, five) def getbundle(self, source, heads=None, common=None, bundlecaps=None, **kwargs): @@ -197,8 +207,24 @@ class localpeer(peer.peerrepository): else: return changegroup.getunbundler('01', cb, None) - # TODO We might want to move the next two calls into legacypeer and add - # unbundle instead. + def heads(self): + return self._repo.heads() + + def known(self, nodes): + return self._repo.known(nodes) + + def listkeys(self, namespace): + return self._repo.listkeys(namespace) + + def lookup(self, key): + return self._repo.lookup(key) + + def pushkey(self, namespace, key, old, new): + return self._repo.pushkey(namespace, key, old, new) + + def stream_out(self): + raise error.Abort(_('cannot perform stream clone against local ' + 'peer')) def unbundle(self, cg, heads, url): """apply a bundle on a repo @@ -235,35 +261,38 @@ class localpeer(peer.peerrepository): except error.PushRaced as exc: raise error.ResponseError(_('push failed:'), str(exc)) - def pushkey(self, namespace, key, old, new): - return self._repo.pushkey(namespace, key, old, new) + # End of _basewirecommands interface. - def listkeys(self, namespace): - return self._repo.listkeys(namespace) + # Begin of peer interface. - def debugwireargs(self, one, two, three=None, four=None, five=None): - '''used to test argument passing over the wire''' - return "%s %s %s %s %s" % (one, two, three, four, five) + def iterbatch(self): + return peer.localiterbatcher(self) -class locallegacypeer(localpeer): + # End of peer interface. + +class locallegacypeer(repository.legacypeer, localpeer): '''peer extension which implements legacy methods too; used for tests with restricted capabilities''' def __init__(self, repo): - localpeer.__init__(self, repo, caps=legacycaps) + super(locallegacypeer, self).__init__(repo, caps=legacycaps) + + # Begin of baselegacywirecommands interface. + + def between(self, pairs): + return self._repo.between(pairs) def branches(self, nodes): return self._repo.branches(nodes) - def between(self, pairs): - return self._repo.between(pairs) - def changegroup(self, basenodes, source): return changegroup.changegroup(self._repo, basenodes, source) def changegroupsubset(self, bases, heads, source): return changegroup.changegroupsubset(self._repo, bases, heads, source) + # End of baselegacywirecommands interface. + # Increment the sub-version when the revlog v2 format changes to lock out old # clients. REVLOGV2_REQUIREMENT = 'exp-revlogv2.0'