Patchwork [3,of,4] revbranchcache: add the necessary bit to send 'rbc' data over bundle2

login
register
mail settings
Submitter Boris Feld
Date Jan. 18, 2018, 3:38 p.m.
Message ID <544af0806c0556e6281b.1516289926@FB>
Download mbox | patch
Permalink /patch/26906/
State Accepted
Headers show

Comments

Boris Feld - Jan. 18, 2018, 3:38 p.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1516283882 -3600
#      Thu Jan 18 14:58:02 2018 +0100
# Node ID 544af0806c0556e6281b38214466d5acd623b5f3
# Parent  9c1ad82226a2e1fc7ca69550a46a7f7329c6b579
# EXP-Topic wire-rbc
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 544af0806c05
revbranchcache: add the necessary bit to send 'rbc' data over bundle2

Getbundle is now capable of sending rev-branch-cache information for the
changesets it bundle. The data sent are mostly nodes so it is quite compact.
The goal of the rev-branch-cache is to speed up branch map computation,
especially when the branchmap gets invalidated so we send data for all
exchanged changesets. In addition, computing the relevant heads to send in
case of partial pulling would be challenging.

The feature is still inactive since the capability is not advertised yet.

Patch

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -1879,6 +1879,44 @@  def _getbundletagsfnodes(bundler, repo, 
     outgoing = _computeoutgoing(repo, heads, common)
     bundle2.addparttagsfnodescache(repo, bundler, outgoing)
 
+@getbundle2partsgenerator('cache:rev-branch-cache')
+def _getbundlerevbranchcache(bundler, repo, source, bundlecaps=None,
+                             b2caps=None, heads=None, common=None,
+                             **kwargs):
+    """Transfer the rev-branch-cache mapping
+
+    The payload is a series of data related to each branch
+
+    1) branch name length
+    2) number of open heads
+    3) number of closed heads
+    4) open heads nodes
+    5) closed heads nodes
+    """
+    # Don't send unless:
+    # - changeset are being exchanged,
+    # - the client supports it.
+    if not (kwargs.get(r'cg', True)) or 'rev-branch-cache' not in b2caps:
+        return
+    cache = repo.revbranchcache()
+    cl = repo.unfiltered().changelog
+    outgoing = _computeoutgoing(repo, heads, common)
+    branchesdata = collections.defaultdict(lambda: (set(), set()))
+    for node in outgoing.missing:
+        branch, close = cache.branchinfo(cl.rev(node))
+        branchesdata[branch][close].add(node)
+
+    def generate():
+        for branch, (nodes, closed) in sorted(branchesdata.items()):
+            yield bundle2.rbcstruct.pack(len(branch), len(nodes), len(closed))
+            yield branch
+            for n in sorted(nodes):
+                yield n
+            for n in sorted(closed):
+                yield n
+
+    bundler.newpart('cache:rev-branch-cache', data=generate())
+
 def check_heads(repo, their_heads, context):
     """check if the heads of a repo have been modified