comparison mercurial/localrepo.py @ 33803:707750e5310b

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
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 09 Aug 2017 23:52:25 -0700
parents 02a745c20121
children f7d41b85bbf6
comparison
equal deleted inserted replaced
33802:a0aad86b3b6a 33803:707750e5310b
47 pathutil, 47 pathutil,
48 peer, 48 peer,
49 phases, 49 phases,
50 pushkey, 50 pushkey,
51 pycompat, 51 pycompat,
52 repository,
52 repoview, 53 repoview,
53 revset, 54 revset,
54 revsetlang, 55 revsetlang,
55 scmutil, 56 scmutil,
56 sparse, 57 sparse,
142 143
143 moderncaps = {'lookup', 'branchmap', 'pushkey', 'known', 'getbundle', 144 moderncaps = {'lookup', 'branchmap', 'pushkey', 'known', 'getbundle',
144 'unbundle'} 145 'unbundle'}
145 legacycaps = moderncaps.union({'changegroupsubset'}) 146 legacycaps = moderncaps.union({'changegroupsubset'})
146 147
147 class localpeer(peer.peerrepository): 148 class localpeer(repository.peer):
148 '''peer for a local repo; reflects only the most recent API''' 149 '''peer for a local repo; reflects only the most recent API'''
149 150
150 def __init__(self, repo, caps=None): 151 def __init__(self, repo, caps=None):
152 super(localpeer, self).__init__()
153
151 if caps is None: 154 if caps is None:
152 caps = moderncaps.copy() 155 caps = moderncaps.copy()
153 peer.peerrepository.__init__(self)
154 self._repo = repo.filtered('served') 156 self._repo = repo.filtered('served')
155 self.ui = repo.ui 157 self._ui = repo.ui
156 self._caps = repo._restrictcapabilities(caps) 158 self._caps = repo._restrictcapabilities(caps)
159
160 # Begin of _basepeer interface.
161
162 @util.propertycache
163 def ui(self):
164 return self._ui
165
166 def url(self):
167 return self._repo.url()
168
169 def local(self):
170 return self._repo
171
172 def peer(self):
173 return self
174
175 def canpush(self):
176 return True
157 177
158 def close(self): 178 def close(self):
159 self._repo.close() 179 self._repo.close()
160 180
161 def _capabilities(self): 181 # End of _basepeer interface.
162 return self._caps 182
163 183 # Begin of _basewirecommands interface.
164 def local(self):
165 return self._repo
166
167 def canpush(self):
168 return True
169
170 def url(self):
171 return self._repo.url()
172
173 def lookup(self, key):
174 return self._repo.lookup(key)
175 184
176 def branchmap(self): 185 def branchmap(self):
177 return self._repo.branchmap() 186 return self._repo.branchmap()
178 187
179 def heads(self): 188 def capabilities(self):
180 return self._repo.heads() 189 return self._caps
181 190
182 def known(self, nodes): 191 def debugwireargs(self, one, two, three=None, four=None, five=None):
183 return self._repo.known(nodes) 192 """Used to test argument passing over the wire"""
193 return "%s %s %s %s %s" % (one, two, three, four, five)
184 194
185 def getbundle(self, source, heads=None, common=None, bundlecaps=None, 195 def getbundle(self, source, heads=None, common=None, bundlecaps=None,
186 **kwargs): 196 **kwargs):
187 chunks = exchange.getbundlechunks(self._repo, source, heads=heads, 197 chunks = exchange.getbundlechunks(self._repo, source, heads=heads,
188 common=common, bundlecaps=bundlecaps, 198 common=common, bundlecaps=bundlecaps,
195 # from it in local peer. 205 # from it in local peer.
196 return bundle2.getunbundler(self.ui, cb) 206 return bundle2.getunbundler(self.ui, cb)
197 else: 207 else:
198 return changegroup.getunbundler('01', cb, None) 208 return changegroup.getunbundler('01', cb, None)
199 209
200 # TODO We might want to move the next two calls into legacypeer and add 210 def heads(self):
201 # unbundle instead. 211 return self._repo.heads()
212
213 def known(self, nodes):
214 return self._repo.known(nodes)
215
216 def listkeys(self, namespace):
217 return self._repo.listkeys(namespace)
218
219 def lookup(self, key):
220 return self._repo.lookup(key)
221
222 def pushkey(self, namespace, key, old, new):
223 return self._repo.pushkey(namespace, key, old, new)
224
225 def stream_out(self):
226 raise error.Abort(_('cannot perform stream clone against local '
227 'peer'))
202 228
203 def unbundle(self, cg, heads, url): 229 def unbundle(self, cg, heads, url):
204 """apply a bundle on a repo 230 """apply a bundle on a repo
205 231
206 This function handles the repo locking itself.""" 232 This function handles the repo locking itself."""
233 bundle2.processbundle(self._repo, b) 259 bundle2.processbundle(self._repo, b)
234 raise 260 raise
235 except error.PushRaced as exc: 261 except error.PushRaced as exc:
236 raise error.ResponseError(_('push failed:'), str(exc)) 262 raise error.ResponseError(_('push failed:'), str(exc))
237 263
238 def pushkey(self, namespace, key, old, new): 264 # End of _basewirecommands interface.
239 return self._repo.pushkey(namespace, key, old, new) 265
240 266 # Begin of peer interface.
241 def listkeys(self, namespace): 267
242 return self._repo.listkeys(namespace) 268 def iterbatch(self):
243 269 return peer.localiterbatcher(self)
244 def debugwireargs(self, one, two, three=None, four=None, five=None): 270
245 '''used to test argument passing over the wire''' 271 # End of peer interface.
246 return "%s %s %s %s %s" % (one, two, three, four, five) 272
247 273 class locallegacypeer(repository.legacypeer, localpeer):
248 class locallegacypeer(localpeer):
249 '''peer extension which implements legacy methods too; used for tests with 274 '''peer extension which implements legacy methods too; used for tests with
250 restricted capabilities''' 275 restricted capabilities'''
251 276
252 def __init__(self, repo): 277 def __init__(self, repo):
253 localpeer.__init__(self, repo, caps=legacycaps) 278 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
279
280 # Begin of baselegacywirecommands interface.
281
282 def between(self, pairs):
283 return self._repo.between(pairs)
254 284
255 def branches(self, nodes): 285 def branches(self, nodes):
256 return self._repo.branches(nodes) 286 return self._repo.branches(nodes)
257 287
258 def between(self, pairs):
259 return self._repo.between(pairs)
260
261 def changegroup(self, basenodes, source): 288 def changegroup(self, basenodes, source):
262 return changegroup.changegroup(self._repo, basenodes, source) 289 return changegroup.changegroup(self._repo, basenodes, source)
263 290
264 def changegroupsubset(self, bases, heads, source): 291 def changegroupsubset(self, bases, heads, source):
265 return changegroup.changegroupsubset(self._repo, bases, heads, source) 292 return changegroup.changegroupsubset(self._repo, bases, heads, source)
293
294 # End of baselegacywirecommands interface.
266 295
267 # Increment the sub-version when the revlog v2 format changes to lock out old 296 # Increment the sub-version when the revlog v2 format changes to lock out old
268 # clients. 297 # clients.
269 REVLOGV2_REQUIREMENT = 'exp-revlogv2.0' 298 REVLOGV2_REQUIREMENT = 'exp-revlogv2.0'
270 299