##// END OF EJS Templates
rawdata: update callers in bundlerepo...
marmoute -
r43015:e6d5ac17 default draft
parent child Browse files
Show More
@@ -1,668 +1,668 b''
1 1 # bundlerepo.py - repository class for viewing uncompressed bundles
2 2 #
3 3 # Copyright 2006, 2007 Benoit Boissinot <bboissin@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 """Repository class for viewing uncompressed bundles.
9 9
10 10 This provides a read-only repository interface to bundles as if they
11 11 were part of the actual repository.
12 12 """
13 13
14 14 from __future__ import absolute_import
15 15
16 16 import os
17 17 import shutil
18 18
19 19 from .i18n import _
20 20 from .node import nullid
21 21
22 22 from . import (
23 23 bundle2,
24 24 changegroup,
25 25 changelog,
26 26 cmdutil,
27 27 discovery,
28 28 encoding,
29 29 error,
30 30 exchange,
31 31 filelog,
32 32 localrepo,
33 33 manifest,
34 34 mdiff,
35 35 node as nodemod,
36 36 pathutil,
37 37 phases,
38 38 pycompat,
39 39 revlog,
40 40 util,
41 41 vfs as vfsmod,
42 42 )
43 43
44 44 class bundlerevlog(revlog.revlog):
45 45 def __init__(self, opener, indexfile, cgunpacker, linkmapper):
46 46 # How it works:
47 47 # To retrieve a revision, we need to know the offset of the revision in
48 48 # the bundle (an unbundle object). We store this offset in the index
49 49 # (start). The base of the delta is stored in the base field.
50 50 #
51 51 # To differentiate a rev in the bundle from a rev in the revlog, we
52 52 # check revision against repotiprev.
53 53 opener = vfsmod.readonlyvfs(opener)
54 54 revlog.revlog.__init__(self, opener, indexfile)
55 55 self.bundle = cgunpacker
56 56 n = len(self)
57 57 self.repotiprev = n - 1
58 58 self.bundlerevs = set() # used by 'bundle()' revset expression
59 59 for deltadata in cgunpacker.deltaiter():
60 60 node, p1, p2, cs, deltabase, delta, flags = deltadata
61 61
62 62 size = len(delta)
63 63 start = cgunpacker.tell() - size
64 64
65 65 link = linkmapper(cs)
66 66 if node in self.nodemap:
67 67 # this can happen if two branches make the same change
68 68 self.bundlerevs.add(self.nodemap[node])
69 69 continue
70 70
71 71 for p in (p1, p2):
72 72 if p not in self.nodemap:
73 73 raise error.LookupError(p, self.indexfile,
74 74 _("unknown parent"))
75 75
76 76 if deltabase not in self.nodemap:
77 77 raise LookupError(deltabase, self.indexfile,
78 78 _('unknown delta base'))
79 79
80 80 baserev = self.rev(deltabase)
81 81 # start, size, full unc. size, base (unused), link, p1, p2, node
82 82 e = (revlog.offset_type(start, flags), size, -1, baserev, link,
83 83 self.rev(p1), self.rev(p2), node)
84 84 self.index.append(e)
85 85 self.nodemap[node] = n
86 86 self.bundlerevs.add(n)
87 87 n += 1
88 88
89 89 def _chunk(self, rev, df=None):
90 90 # Warning: in case of bundle, the diff is against what we stored as
91 91 # delta base, not against rev - 1
92 92 # XXX: could use some caching
93 93 if rev <= self.repotiprev:
94 94 return revlog.revlog._chunk(self, rev)
95 95 self.bundle.seek(self.start(rev))
96 96 return self.bundle.read(self.length(rev))
97 97
98 98 def revdiff(self, rev1, rev2):
99 99 """return or calculate a delta between two revisions"""
100 100 if rev1 > self.repotiprev and rev2 > self.repotiprev:
101 101 # hot path for bundle
102 102 revb = self.index[rev2][3]
103 103 if revb == rev1:
104 104 return self._chunk(rev2)
105 105 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
106 106 return revlog.revlog.revdiff(self, rev1, rev2)
107 107
108 return mdiff.textdiff(self.revision(rev1, raw=True),
109 self.revision(rev2, raw=True))
108 return mdiff.textdiff(self.rawdata(rev1),
109 self.rawdata(rev2))
110 110
111 111 def revision(self, nodeorrev, _df=None, raw=False):
112 112 """return an uncompressed revision of a given node or revision
113 113 number.
114 114 """
115 115 if isinstance(nodeorrev, int):
116 116 rev = nodeorrev
117 117 node = self.node(rev)
118 118 else:
119 119 node = nodeorrev
120 120 rev = self.rev(node)
121 121
122 122 if node == nullid:
123 123 return ""
124 124
125 125 rawtext = None
126 126 chain = []
127 127 iterrev = rev
128 128 # reconstruct the revision if it is from a changegroup
129 129 while iterrev > self.repotiprev:
130 130 if self._revisioncache and self._revisioncache[1] == iterrev:
131 131 rawtext = self._revisioncache[2]
132 132 break
133 133 chain.append(iterrev)
134 134 iterrev = self.index[iterrev][3]
135 135 if rawtext is None:
136 136 rawtext = self.baserevision(iterrev)
137 137
138 138 while chain:
139 139 delta = self._chunk(chain.pop())
140 140 rawtext = mdiff.patches(rawtext, [delta])
141 141
142 142 text, validatehash = self._processflags(rawtext, self.flags(rev),
143 143 'read', raw=raw)
144 144 if validatehash:
145 145 self.checkhash(text, node, rev=rev)
146 146 self._revisioncache = (node, rev, rawtext)
147 147 return text
148 148
149 149 def rawdata(self, nodeorrev, _df=None):
150 150 return self.revision(nodeorrev, _df=_df, raw=True)
151 151
152 152 def baserevision(self, nodeorrev):
153 153 # Revlog subclasses may override 'revision' method to modify format of
154 154 # content retrieved from revlog. To use bundlerevlog with such class one
155 155 # needs to override 'baserevision' and make more specific call here.
156 return revlog.revlog.revision(self, nodeorrev, raw=True)
156 return revlog.revlog.rawdata(self, nodeorrev)
157 157
158 158 def addrevision(self, *args, **kwargs):
159 159 raise NotImplementedError
160 160
161 161 def addgroup(self, *args, **kwargs):
162 162 raise NotImplementedError
163 163
164 164 def strip(self, *args, **kwargs):
165 165 raise NotImplementedError
166 166
167 167 def checksize(self):
168 168 raise NotImplementedError
169 169
170 170 class bundlechangelog(bundlerevlog, changelog.changelog):
171 171 def __init__(self, opener, cgunpacker):
172 172 changelog.changelog.__init__(self, opener)
173 173 linkmapper = lambda x: x
174 174 bundlerevlog.__init__(self, opener, self.indexfile, cgunpacker,
175 175 linkmapper)
176 176
177 177 def baserevision(self, nodeorrev):
178 178 # Although changelog doesn't override 'revision' method, some extensions
179 179 # may replace this class with another that does. Same story with
180 180 # manifest and filelog classes.
181 181
182 182 # This bypasses filtering on changelog.node() and rev() because we need
183 183 # revision text of the bundle base even if it is hidden.
184 184 oldfilter = self.filteredrevs
185 185 try:
186 186 self.filteredrevs = ()
187 return changelog.changelog.revision(self, nodeorrev, raw=True)
187 return changelog.changelog.rawdata(self, nodeorrev)
188 188 finally:
189 189 self.filteredrevs = oldfilter
190 190
191 191 class bundlemanifest(bundlerevlog, manifest.manifestrevlog):
192 192 def __init__(self, opener, cgunpacker, linkmapper, dirlogstarts=None,
193 193 dir=''):
194 194 manifest.manifestrevlog.__init__(self, opener, tree=dir)
195 195 bundlerevlog.__init__(self, opener, self.indexfile, cgunpacker,
196 196 linkmapper)
197 197 if dirlogstarts is None:
198 198 dirlogstarts = {}
199 199 if self.bundle.version == "03":
200 200 dirlogstarts = _getfilestarts(self.bundle)
201 201 self._dirlogstarts = dirlogstarts
202 202 self._linkmapper = linkmapper
203 203
204 204 def baserevision(self, nodeorrev):
205 205 node = nodeorrev
206 206 if isinstance(node, int):
207 207 node = self.node(node)
208 208
209 209 if node in self.fulltextcache:
210 210 result = '%s' % self.fulltextcache[node]
211 211 else:
212 result = manifest.manifestrevlog.revision(self, nodeorrev, raw=True)
212 result = manifest.manifestrevlog.rawdata(self, nodeorrev)
213 213 return result
214 214
215 215 def dirlog(self, d):
216 216 if d in self._dirlogstarts:
217 217 self.bundle.seek(self._dirlogstarts[d])
218 218 return bundlemanifest(
219 219 self.opener, self.bundle, self._linkmapper,
220 220 self._dirlogstarts, dir=d)
221 221 return super(bundlemanifest, self).dirlog(d)
222 222
223 223 class bundlefilelog(filelog.filelog):
224 224 def __init__(self, opener, path, cgunpacker, linkmapper):
225 225 filelog.filelog.__init__(self, opener, path)
226 226 self._revlog = bundlerevlog(opener, self.indexfile,
227 227 cgunpacker, linkmapper)
228 228
229 229 def baserevision(self, nodeorrev):
230 return filelog.filelog.revision(self, nodeorrev, raw=True)
230 return filelog.filelog.rawdata(self, nodeorrev)
231 231
232 232 class bundlepeer(localrepo.localpeer):
233 233 def canpush(self):
234 234 return False
235 235
236 236 class bundlephasecache(phases.phasecache):
237 237 def __init__(self, *args, **kwargs):
238 238 super(bundlephasecache, self).__init__(*args, **kwargs)
239 239 if util.safehasattr(self, 'opener'):
240 240 self.opener = vfsmod.readonlyvfs(self.opener)
241 241
242 242 def write(self):
243 243 raise NotImplementedError
244 244
245 245 def _write(self, fp):
246 246 raise NotImplementedError
247 247
248 248 def _updateroots(self, phase, newroots, tr):
249 249 self.phaseroots[phase] = newroots
250 250 self.invalidate()
251 251 self.dirty = True
252 252
253 253 def _getfilestarts(cgunpacker):
254 254 filespos = {}
255 255 for chunkdata in iter(cgunpacker.filelogheader, {}):
256 256 fname = chunkdata['filename']
257 257 filespos[fname] = cgunpacker.tell()
258 258 for chunk in iter(lambda: cgunpacker.deltachunk(None), {}):
259 259 pass
260 260 return filespos
261 261
262 262 class bundlerepository(object):
263 263 """A repository instance that is a union of a local repo and a bundle.
264 264
265 265 Instances represent a read-only repository composed of a local repository
266 266 with the contents of a bundle file applied. The repository instance is
267 267 conceptually similar to the state of a repository after an
268 268 ``hg unbundle`` operation. However, the contents of the bundle are never
269 269 applied to the actual base repository.
270 270
271 271 Instances constructed directly are not usable as repository objects.
272 272 Use instance() or makebundlerepository() to create instances.
273 273 """
274 274 def __init__(self, bundlepath, url, tempparent):
275 275 self._tempparent = tempparent
276 276 self._url = url
277 277
278 278 self.ui.setconfig('phases', 'publish', False, 'bundlerepo')
279 279
280 280 self.tempfile = None
281 281 f = util.posixfile(bundlepath, "rb")
282 282 bundle = exchange.readbundle(self.ui, f, bundlepath)
283 283
284 284 if isinstance(bundle, bundle2.unbundle20):
285 285 self._bundlefile = bundle
286 286 self._cgunpacker = None
287 287
288 288 cgpart = None
289 289 for part in bundle.iterparts(seekable=True):
290 290 if part.type == 'changegroup':
291 291 if cgpart:
292 292 raise NotImplementedError("can't process "
293 293 "multiple changegroups")
294 294 cgpart = part
295 295
296 296 self._handlebundle2part(bundle, part)
297 297
298 298 if not cgpart:
299 299 raise error.Abort(_("No changegroups found"))
300 300
301 301 # This is required to placate a later consumer, which expects
302 302 # the payload offset to be at the beginning of the changegroup.
303 303 # We need to do this after the iterparts() generator advances
304 304 # because iterparts() will seek to end of payload after the
305 305 # generator returns control to iterparts().
306 306 cgpart.seek(0, os.SEEK_SET)
307 307
308 308 elif isinstance(bundle, changegroup.cg1unpacker):
309 309 if bundle.compressed():
310 310 f = self._writetempbundle(bundle.read, '.hg10un',
311 311 header='HG10UN')
312 312 bundle = exchange.readbundle(self.ui, f, bundlepath, self.vfs)
313 313
314 314 self._bundlefile = bundle
315 315 self._cgunpacker = bundle
316 316 else:
317 317 raise error.Abort(_('bundle type %s cannot be read') %
318 318 type(bundle))
319 319
320 320 # dict with the mapping 'filename' -> position in the changegroup.
321 321 self._cgfilespos = {}
322 322
323 323 self.firstnewrev = self.changelog.repotiprev + 1
324 324 phases.retractboundary(self, None, phases.draft,
325 325 [ctx.node() for ctx in self[self.firstnewrev:]])
326 326
327 327 def _handlebundle2part(self, bundle, part):
328 328 if part.type != 'changegroup':
329 329 return
330 330
331 331 cgstream = part
332 332 version = part.params.get('version', '01')
333 333 legalcgvers = changegroup.supportedincomingversions(self)
334 334 if version not in legalcgvers:
335 335 msg = _('Unsupported changegroup version: %s')
336 336 raise error.Abort(msg % version)
337 337 if bundle.compressed():
338 338 cgstream = self._writetempbundle(part.read, '.cg%sun' % version)
339 339
340 340 self._cgunpacker = changegroup.getunbundler(version, cgstream, 'UN')
341 341
342 342 def _writetempbundle(self, readfn, suffix, header=''):
343 343 """Write a temporary file to disk
344 344 """
345 345 fdtemp, temp = self.vfs.mkstemp(prefix="hg-bundle-",
346 346 suffix=suffix)
347 347 self.tempfile = temp
348 348
349 349 with os.fdopen(fdtemp, r'wb') as fptemp:
350 350 fptemp.write(header)
351 351 while True:
352 352 chunk = readfn(2**18)
353 353 if not chunk:
354 354 break
355 355 fptemp.write(chunk)
356 356
357 357 return self.vfs.open(self.tempfile, mode="rb")
358 358
359 359 @localrepo.unfilteredpropertycache
360 360 def _phasecache(self):
361 361 return bundlephasecache(self, self._phasedefaults)
362 362
363 363 @localrepo.unfilteredpropertycache
364 364 def changelog(self):
365 365 # consume the header if it exists
366 366 self._cgunpacker.changelogheader()
367 367 c = bundlechangelog(self.svfs, self._cgunpacker)
368 368 self.manstart = self._cgunpacker.tell()
369 369 return c
370 370
371 371 def _refreshchangelog(self):
372 372 # changelog for bundle repo are not filecache, this method is not
373 373 # applicable.
374 374 pass
375 375
376 376 @localrepo.unfilteredpropertycache
377 377 def manifestlog(self):
378 378 self._cgunpacker.seek(self.manstart)
379 379 # consume the header if it exists
380 380 self._cgunpacker.manifestheader()
381 381 linkmapper = self.unfiltered().changelog.rev
382 382 rootstore = bundlemanifest(self.svfs, self._cgunpacker, linkmapper)
383 383 self.filestart = self._cgunpacker.tell()
384 384
385 385 return manifest.manifestlog(self.svfs, self, rootstore,
386 386 self.narrowmatch())
387 387
388 388 def _consumemanifest(self):
389 389 """Consumes the manifest portion of the bundle, setting filestart so the
390 390 file portion can be read."""
391 391 self._cgunpacker.seek(self.manstart)
392 392 self._cgunpacker.manifestheader()
393 393 for delta in self._cgunpacker.deltaiter():
394 394 pass
395 395 self.filestart = self._cgunpacker.tell()
396 396
397 397 @localrepo.unfilteredpropertycache
398 398 def manstart(self):
399 399 self.changelog
400 400 return self.manstart
401 401
402 402 @localrepo.unfilteredpropertycache
403 403 def filestart(self):
404 404 self.manifestlog
405 405
406 406 # If filestart was not set by self.manifestlog, that means the
407 407 # manifestlog implementation did not consume the manifests from the
408 408 # changegroup (ex: it might be consuming trees from a separate bundle2
409 409 # part instead). So we need to manually consume it.
410 410 if r'filestart' not in self.__dict__:
411 411 self._consumemanifest()
412 412
413 413 return self.filestart
414 414
415 415 def url(self):
416 416 return self._url
417 417
418 418 def file(self, f):
419 419 if not self._cgfilespos:
420 420 self._cgunpacker.seek(self.filestart)
421 421 self._cgfilespos = _getfilestarts(self._cgunpacker)
422 422
423 423 if f in self._cgfilespos:
424 424 self._cgunpacker.seek(self._cgfilespos[f])
425 425 linkmapper = self.unfiltered().changelog.rev
426 426 return bundlefilelog(self.svfs, f, self._cgunpacker, linkmapper)
427 427 else:
428 428 return super(bundlerepository, self).file(f)
429 429
430 430 def close(self):
431 431 """Close assigned bundle file immediately."""
432 432 self._bundlefile.close()
433 433 if self.tempfile is not None:
434 434 self.vfs.unlink(self.tempfile)
435 435 if self._tempparent:
436 436 shutil.rmtree(self._tempparent, True)
437 437
438 438 def cancopy(self):
439 439 return False
440 440
441 441 def peer(self):
442 442 return bundlepeer(self)
443 443
444 444 def getcwd(self):
445 445 return encoding.getcwd() # always outside the repo
446 446
447 447 # Check if parents exist in localrepo before setting
448 448 def setparents(self, p1, p2=nullid):
449 449 p1rev = self.changelog.rev(p1)
450 450 p2rev = self.changelog.rev(p2)
451 451 msg = _("setting parent to node %s that only exists in the bundle\n")
452 452 if self.changelog.repotiprev < p1rev:
453 453 self.ui.warn(msg % nodemod.hex(p1))
454 454 if self.changelog.repotiprev < p2rev:
455 455 self.ui.warn(msg % nodemod.hex(p2))
456 456 return super(bundlerepository, self).setparents(p1, p2)
457 457
458 458 def instance(ui, path, create, intents=None, createopts=None):
459 459 if create:
460 460 raise error.Abort(_('cannot create new bundle repository'))
461 461 # internal config: bundle.mainreporoot
462 462 parentpath = ui.config("bundle", "mainreporoot")
463 463 if not parentpath:
464 464 # try to find the correct path to the working directory repo
465 465 parentpath = cmdutil.findrepo(encoding.getcwd())
466 466 if parentpath is None:
467 467 parentpath = ''
468 468 if parentpath:
469 469 # Try to make the full path relative so we get a nice, short URL.
470 470 # In particular, we don't want temp dir names in test outputs.
471 471 cwd = encoding.getcwd()
472 472 if parentpath == cwd:
473 473 parentpath = ''
474 474 else:
475 475 cwd = pathutil.normasprefix(cwd)
476 476 if parentpath.startswith(cwd):
477 477 parentpath = parentpath[len(cwd):]
478 478 u = util.url(path)
479 479 path = u.localpath()
480 480 if u.scheme == 'bundle':
481 481 s = path.split("+", 1)
482 482 if len(s) == 1:
483 483 repopath, bundlename = parentpath, s[0]
484 484 else:
485 485 repopath, bundlename = s
486 486 else:
487 487 repopath, bundlename = parentpath, path
488 488
489 489 return makebundlerepository(ui, repopath, bundlename)
490 490
491 491 def makebundlerepository(ui, repopath, bundlepath):
492 492 """Make a bundle repository object based on repo and bundle paths."""
493 493 if repopath:
494 494 url = 'bundle:%s+%s' % (util.expandpath(repopath), bundlepath)
495 495 else:
496 496 url = 'bundle:%s' % bundlepath
497 497
498 498 # Because we can't make any guarantees about the type of the base
499 499 # repository, we can't have a static class representing the bundle
500 500 # repository. We also can't make any guarantees about how to even
501 501 # call the base repository's constructor!
502 502 #
503 503 # So, our strategy is to go through ``localrepo.instance()`` to construct
504 504 # a repo instance. Then, we dynamically create a new type derived from
505 505 # both it and our ``bundlerepository`` class which overrides some
506 506 # functionality. We then change the type of the constructed repository
507 507 # to this new type and initialize the bundle-specific bits of it.
508 508
509 509 try:
510 510 repo = localrepo.instance(ui, repopath, create=False)
511 511 tempparent = None
512 512 except error.RepoError:
513 513 tempparent = pycompat.mkdtemp()
514 514 try:
515 515 repo = localrepo.instance(ui, tempparent, create=True)
516 516 except Exception:
517 517 shutil.rmtree(tempparent)
518 518 raise
519 519
520 520 class derivedbundlerepository(bundlerepository, repo.__class__):
521 521 pass
522 522
523 523 repo.__class__ = derivedbundlerepository
524 524 bundlerepository.__init__(repo, bundlepath, url, tempparent)
525 525
526 526 return repo
527 527
528 528 class bundletransactionmanager(object):
529 529 def transaction(self):
530 530 return None
531 531
532 532 def close(self):
533 533 raise NotImplementedError
534 534
535 535 def release(self):
536 536 raise NotImplementedError
537 537
538 538 def getremotechanges(ui, repo, peer, onlyheads=None, bundlename=None,
539 539 force=False):
540 540 '''obtains a bundle of changes incoming from peer
541 541
542 542 "onlyheads" restricts the returned changes to those reachable from the
543 543 specified heads.
544 544 "bundlename", if given, stores the bundle to this file path permanently;
545 545 otherwise it's stored to a temp file and gets deleted again when you call
546 546 the returned "cleanupfn".
547 547 "force" indicates whether to proceed on unrelated repos.
548 548
549 549 Returns a tuple (local, csets, cleanupfn):
550 550
551 551 "local" is a local repo from which to obtain the actual incoming
552 552 changesets; it is a bundlerepo for the obtained bundle when the
553 553 original "peer" is remote.
554 554 "csets" lists the incoming changeset node ids.
555 555 "cleanupfn" must be called without arguments when you're done processing
556 556 the changes; it closes both the original "peer" and the one returned
557 557 here.
558 558 '''
559 559 tmp = discovery.findcommonincoming(repo, peer, heads=onlyheads,
560 560 force=force)
561 561 common, incoming, rheads = tmp
562 562 if not incoming:
563 563 try:
564 564 if bundlename:
565 565 os.unlink(bundlename)
566 566 except OSError:
567 567 pass
568 568 return repo, [], peer.close
569 569
570 570 commonset = set(common)
571 571 rheads = [x for x in rheads if x not in commonset]
572 572
573 573 bundle = None
574 574 bundlerepo = None
575 575 localrepo = peer.local()
576 576 if bundlename or not localrepo:
577 577 # create a bundle (uncompressed if peer repo is not local)
578 578
579 579 # developer config: devel.legacy.exchange
580 580 legexc = ui.configlist('devel', 'legacy.exchange')
581 581 forcebundle1 = 'bundle2' not in legexc and 'bundle1' in legexc
582 582 canbundle2 = (not forcebundle1
583 583 and peer.capable('getbundle')
584 584 and peer.capable('bundle2'))
585 585 if canbundle2:
586 586 with peer.commandexecutor() as e:
587 587 b2 = e.callcommand('getbundle', {
588 588 'source': 'incoming',
589 589 'common': common,
590 590 'heads': rheads,
591 591 'bundlecaps': exchange.caps20to10(repo, role='client'),
592 592 'cg': True,
593 593 }).result()
594 594
595 595 fname = bundle = changegroup.writechunks(ui,
596 596 b2._forwardchunks(),
597 597 bundlename)
598 598 else:
599 599 if peer.capable('getbundle'):
600 600 with peer.commandexecutor() as e:
601 601 cg = e.callcommand('getbundle', {
602 602 'source': 'incoming',
603 603 'common': common,
604 604 'heads': rheads,
605 605 }).result()
606 606 elif onlyheads is None and not peer.capable('changegroupsubset'):
607 607 # compat with older servers when pulling all remote heads
608 608
609 609 with peer.commandexecutor() as e:
610 610 cg = e.callcommand('changegroup', {
611 611 'nodes': incoming,
612 612 'source': 'incoming',
613 613 }).result()
614 614
615 615 rheads = None
616 616 else:
617 617 with peer.commandexecutor() as e:
618 618 cg = e.callcommand('changegroupsubset', {
619 619 'bases': incoming,
620 620 'heads': rheads,
621 621 'source': 'incoming',
622 622 }).result()
623 623
624 624 if localrepo:
625 625 bundletype = "HG10BZ"
626 626 else:
627 627 bundletype = "HG10UN"
628 628 fname = bundle = bundle2.writebundle(ui, cg, bundlename,
629 629 bundletype)
630 630 # keep written bundle?
631 631 if bundlename:
632 632 bundle = None
633 633 if not localrepo:
634 634 # use the created uncompressed bundlerepo
635 635 localrepo = bundlerepo = makebundlerepository(repo. baseui,
636 636 repo.root,
637 637 fname)
638 638
639 639 # this repo contains local and peer now, so filter out local again
640 640 common = repo.heads()
641 641 if localrepo:
642 642 # Part of common may be remotely filtered
643 643 # So use an unfiltered version
644 644 # The discovery process probably need cleanup to avoid that
645 645 localrepo = localrepo.unfiltered()
646 646
647 647 csets = localrepo.changelog.findmissing(common, rheads)
648 648
649 649 if bundlerepo:
650 650 reponodes = [ctx.node() for ctx in bundlerepo[bundlerepo.firstnewrev:]]
651 651
652 652 with peer.commandexecutor() as e:
653 653 remotephases = e.callcommand('listkeys', {
654 654 'namespace': 'phases',
655 655 }).result()
656 656
657 657 pullop = exchange.pulloperation(bundlerepo, peer, heads=reponodes)
658 658 pullop.trmanager = bundletransactionmanager()
659 659 exchange._pullapplyphases(pullop, remotephases)
660 660
661 661 def cleanup():
662 662 if bundlerepo:
663 663 bundlerepo.close()
664 664 if bundle:
665 665 os.unlink(bundle)
666 666 peer.close()
667 667
668 668 return (localrepo, csets, cleanup)
General Comments 0
You need to be logged in to leave comments. Login now