comparison mercurial/exchange.py @ 37498:aacfca6f9767

wireproto: support for pullbundles Pullbundles are similar to clonebundles, but served as normal inline bundle streams. They are almost transparent to the client -- the only visible effect is that the client might get less changes than what it asked for, i.e. not all requested head revisions are provided. The client announces support for the necessary retries with the partial-pull capability. After receiving a partial bundle, it updates the set of revisions shared with the server and drops all now-known heads from the request list. It will then rerun getbundle until no changes are received or all remote heads are present. Extend badserverext to support per-socket limit, i.e. don't assume that the same limits should be applied to all sockets. Differential Revision: https://phab.mercurial-scm.org/D1856
author Joerg Sonnenberger <joerg@bec.de>
date Thu, 18 Jan 2018 12:54:01 +0100
parents f7d3915d5b3a
children cc8c06835097
comparison
equal deleted inserted replaced
37497:1541e1a8e87d 37498:aacfca6f9767
1373 def release(self): 1373 def release(self):
1374 """release transaction if created""" 1374 """release transaction if created"""
1375 if self._tr is not None: 1375 if self._tr is not None:
1376 self._tr.release() 1376 self._tr.release()
1377 1377
1378 def _fullpullbundle2(repo, pullop):
1379 # The server may send a partial reply, i.e. when inlining
1380 # pre-computed bundles. In that case, update the common
1381 # set based on the results and pull another bundle.
1382 #
1383 # There are two indicators that the process is finished:
1384 # - no changeset has been added, or
1385 # - all remote heads are known locally.
1386 # The head check must use the unfiltered view as obsoletion
1387 # markers can hide heads.
1388 unfi = repo.unfiltered()
1389 unficl = unfi.changelog
1390 def headsofdiff(h1, h2):
1391 """Returns heads(h1 % h2)"""
1392 res = unfi.set('heads(%ln %% %ln)', h1, h2)
1393 return set(ctx.node() for ctx in res)
1394 def headsofunion(h1, h2):
1395 """Returns heads((h1 + h2) - null)"""
1396 res = unfi.set('heads((%ln + %ln - null))', h1, h2)
1397 return set(ctx.node() for ctx in res)
1398 while True:
1399 old_heads = unficl.heads()
1400 clstart = len(unficl)
1401 _pullbundle2(pullop)
1402 if changegroup.NARROW_REQUIREMENT in repo.requirements:
1403 # XXX narrow clones filter the heads on the server side during
1404 # XXX getbundle and result in partial replies as well.
1405 # XXX Disable pull bundles in this case as band aid to avoid
1406 # XXX extra round trips.
1407 break
1408 if clstart == len(unficl):
1409 break
1410 if all(unficl.hasnode(n) for n in pullop.rheads):
1411 break
1412 new_heads = headsofdiff(unficl.heads(), old_heads)
1413 pullop.common = headsofunion(new_heads, pullop.common)
1414 pullop.rheads = set(pullop.rheads) - pullop.common
1415
1378 def pull(repo, remote, heads=None, force=False, bookmarks=(), opargs=None, 1416 def pull(repo, remote, heads=None, force=False, bookmarks=(), opargs=None,
1379 streamclonerequested=None): 1417 streamclonerequested=None):
1380 """Fetch repository data from a remote. 1418 """Fetch repository data from a remote.
1381 1419
1382 This is the main function used to retrieve data from a remote repository. 1420 This is the main function used to retrieve data from a remote repository.
1418 # before discovery to avoid extra work. 1456 # before discovery to avoid extra work.
1419 _maybeapplyclonebundle(pullop) 1457 _maybeapplyclonebundle(pullop)
1420 streamclone.maybeperformlegacystreamclone(pullop) 1458 streamclone.maybeperformlegacystreamclone(pullop)
1421 _pulldiscovery(pullop) 1459 _pulldiscovery(pullop)
1422 if pullop.canusebundle2: 1460 if pullop.canusebundle2:
1423 _pullbundle2(pullop) 1461 _fullpullbundle2(repo, pullop)
1424 _pullchangeset(pullop) 1462 _pullchangeset(pullop)
1425 _pullphase(pullop) 1463 _pullphase(pullop)
1426 _pullbookmarks(pullop) 1464 _pullbookmarks(pullop)
1427 _pullobsolete(pullop) 1465 _pullobsolete(pullop)
1428 1466