hgext3rd/pullbundle.py
changeset 4128 4e5ec9ae682e
child 4129 bc4e62a1cb82
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/pullbundle.py	Sun Sep 23 23:53:23 2018 +0200
@@ -0,0 +1,90 @@
+# Extension to provide automatic caching of bundle server for pull
+#
+# Copyright 2018 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from mercurial import (
+    changegroup,
+    exchange,
+    narrowspec,
+)
+
+from mercurial.i18n import _
+
+def uisetup(ui):
+    exchange.getbundle2partsmapping['changegroup'] = _getbundlechangegrouppart
+
+def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
+                              b2caps=None, heads=None, common=None, **kwargs):
+    """add a changegroup part to the requested bundle"""
+    if not kwargs.get(r'cg', True):
+        return
+
+    version = '01'
+    cgversions = b2caps.get('changegroup')
+    if cgversions:  # 3.1 and 3.2 ship with an empty value
+        cgversions = [v for v in cgversions
+                      if v in changegroup.supportedoutgoingversions(repo)]
+        if not cgversions:
+            raise ValueError(_('no common changegroup version'))
+        version = max(cgversions)
+
+    outgoing = exchange._computeoutgoing(repo, heads, common)
+    if not outgoing.missing:
+        return
+
+    if kwargs.get(r'narrow', False):
+        include = sorted(filter(bool, kwargs.get(r'includepats', [])))
+        exclude = sorted(filter(bool, kwargs.get(r'excludepats', [])))
+        filematcher = narrowspec.match(repo.root, include=include,
+                                       exclude=exclude)
+    else:
+        filematcher = None
+
+    # START OF ALTERED PART
+    makeallcgpart(bundler.newpart, repo, outgoing, version, source, bundlecaps,
+                  filematcher, cgversions)
+    # END OF ALTERED PART
+
+    if kwargs.get(r'narrow', False) and (include or exclude):
+        narrowspecpart = bundler.newpart('narrow:spec')
+        if include:
+            narrowspecpart.addparam(
+                'include', '\n'.join(include), mandatory=True)
+        if exclude:
+            narrowspecpart.addparam(
+                'exclude', '\n'.join(exclude), mandatory=True)
+
+def makeallcgpart(newpart, repo, outgoing, version, source,
+                  bundlecaps, filematcher, cgversions):
+    makeonecgpart(newpart, repo, outgoing, version, source, bundlecaps,
+                  filematcher, cgversions)
+
+def _changegroupinfo(repo, nodes, source):
+    if repo.ui.verbose or source == 'bundle':
+        repo.ui.status(_("%d changesets found\n") % len(nodes))
+
+def makeonecgpart(newpart, repo, outgoing, version, source,
+                  bundlecaps, filematcher, cgversions):
+    # same as upstream code
+
+    old = changegroup._changegroupinfo
+    try:
+        changegroup._changegroupinfo = _changegroupinfo
+        cgstream = changegroup.makestream(repo, outgoing, version, source,
+                                          bundlecaps=bundlecaps,
+                                          filematcher=filematcher)
+    finally:
+        changegroup._changegroupinfo = old
+
+    part = newpart('changegroup', data=cgstream)
+    if cgversions:
+        part.addparam('version', version)
+
+    part.addparam('nbchanges', '%d' % len(outgoing.missing),
+                  mandatory=False)
+
+    if 'treemanifest' in repo.requirements:
+        part.addparam('treemanifest', '1')