changegroup: add bundlecaps back

Commit 9233182ea547d0aa removed the unused bundlecaps argument from the
changegroup code. While it is unused in core Mercurial, it was an important
feature for the remotefilelog extension because it allowed the exchange layer to
communicate to the changegroup packer that this was a shallow repo and that
filelogs should not be included. Without bundlecaps, there is currently no other
way to pass that information along without a more extensive refactor of
exchange, bundle, and changegroup code.

This patch backs out the original removal, and merges it with some recent
changes to changegroup apis.
This commit is contained in:
Durham Goode 2017-05-15 09:35:27 -07:00
parent 4656f56bb3
commit a73dbb6c8d
4 changed files with 32 additions and 15 deletions

View File

@ -494,9 +494,18 @@ class headerlessfixup(object):
class cg1packer(object):
deltaheader = _CHANGEGROUPV1_DELTA_HEADER
version = '01'
def __init__(self, repo):
def __init__(self, repo, bundlecaps=None):
"""Given a source repo, construct a bundler.
bundlecaps is optional and can be used to specify the set of
capabilities which can be used to build the bundle. While bundlecaps is
unused in core Mercurial, extensions rely on this feature to communicate
capabilities to customize the changegroup packer.
"""
# Set of capabilities we can use to build the bundle.
if bundlecaps is None:
bundlecaps = set()
self._bundlecaps = bundlecaps
# experimental config: bundle.reorder
reorder = repo.ui.config('bundle', 'reorder', 'auto')
if reorder == 'auto':
@ -800,8 +809,8 @@ class cg2packer(cg1packer):
version = '02'
deltaheader = _CHANGEGROUPV2_DELTA_HEADER
def __init__(self, repo):
super(cg2packer, self).__init__(repo)
def __init__(self, repo, bundlecaps=None):
super(cg2packer, self).__init__(repo, bundlecaps)
if self._reorder is None:
# Since generaldelta is directly supported by cg2, reordering
# generally doesn't help, so we disable it by default (treating
@ -895,9 +904,9 @@ def safeversion(repo):
assert versions
return min(versions)
def getbundler(version, repo):
def getbundler(version, repo, bundlecaps=None):
assert version in supportedoutgoingversions(repo)
return _packermap[version][0](repo)
return _packermap[version][0](repo, bundlecaps)
def getunbundler(version, fh, alg, extras=None):
return _packermap[version][1](fh, alg, extras=extras)
@ -948,24 +957,26 @@ def changegroupsubset(repo, roots, heads, source, version='01'):
bundler = getbundler(version, repo)
return getsubset(repo, outgoing, bundler, source)
def getlocalchangegroupraw(repo, source, outgoing, version='01'):
def getlocalchangegroupraw(repo, source, outgoing, bundlecaps=None,
version='01'):
"""Like getbundle, but taking a discovery.outgoing as an argument.
This is only implemented for local repos and reuses potentially
precomputed sets in outgoing. Returns a raw changegroup generator."""
if not outgoing.missing:
return None
bundler = getbundler(version, repo)
bundler = getbundler(version, repo, bundlecaps)
return getsubsetraw(repo, outgoing, bundler, source)
def getchangegroup(repo, source, outgoing, version='01'):
def getchangegroup(repo, source, outgoing, bundlecaps=None,
version='01'):
"""Like getbundle, but taking a discovery.outgoing as an argument.
This is only implemented for local repos and reuses potentially
precomputed sets in outgoing."""
if not outgoing.missing:
return None
bundler = getbundler(version, repo)
bundler = getbundler(version, repo, bundlecaps)
return getsubset(repo, outgoing, bundler, source)
def getlocalchangegroup(repo, *args, **kwargs):

View File

@ -936,19 +936,22 @@ def _pushchangeset(pushop):
pushop.repo.prepushoutgoinghooks(pushop)
outgoing = pushop.outgoing
unbundle = pushop.remote.capable('unbundle')
# TODO: get bundlecaps from remote
bundlecaps = None
# create a changegroup from local
if pushop.revs is None and not (outgoing.excluded
or pushop.repo.changelog.filteredrevs):
# push everything,
# use the fast path, no race possible on push
bundler = changegroup.cg1packer(pushop.repo)
bundler = changegroup.cg1packer(pushop.repo, bundlecaps)
cg = changegroup.getsubset(pushop.repo,
outgoing,
bundler,
'push',
fastpath=True)
else:
cg = changegroup.getchangegroup(pushop.repo, 'push', outgoing)
cg = changegroup.getchangegroup(pushop.repo, 'push', outgoing,
bundlecaps=bundlecaps)
# apply changegroup to remote
if unbundle:
@ -1575,7 +1578,7 @@ def getbundlechunks(repo, source, heads=None, common=None, bundlecaps=None,
raise ValueError(_('unsupported getbundle arguments: %s')
% ', '.join(sorted(kwargs.keys())))
outgoing = _computeoutgoing(repo, heads, common)
bundler = changegroup.getbundler('01', repo)
bundler = changegroup.getbundler('01', repo, bundlecaps)
return changegroup.getsubsetraw(repo, outgoing, bundler, source)
# bundle20 case
@ -1613,6 +1616,7 @@ def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
version = max(cgversions)
outgoing = _computeoutgoing(repo, heads, common)
cg = changegroup.getlocalchangegroupraw(repo, source, outgoing,
bundlecaps=bundlecaps,
version=version)
if cg:

View File

@ -113,7 +113,7 @@ Create an extension to test bundle2 API
> headmissing = [c.node() for c in repo.set('heads(%ld)', revs)]
> headcommon = [c.node() for c in repo.set('parents(%ld) - %ld', revs, revs)]
> outgoing = discovery.outgoing(repo, headcommon, headmissing)
> cg = changegroup.getchangegroup(repo, 'test:bundle2', outgoing)
> cg = changegroup.getchangegroup(repo, 'test:bundle2', outgoing, None)
> bundler.newpart('changegroup', data=cg.getchunks(),
> mandatory=False)
>

View File

@ -13,11 +13,13 @@ Create an extension to test bundle2 with multiple changegroups
> # in 'heads' as intermediate heads for the first changegroup.
> intermediates = [repo[r].p1().node() for r in heads]
> outgoing = discovery.outgoing(repo, common, intermediates)
> cg = changegroup.getchangegroup(repo, source, outgoing)
> cg = changegroup.getchangegroup(repo, source, outgoing,
> bundlecaps=bundlecaps)
> bundler.newpart('output', data='changegroup1')
> bundler.newpart('changegroup', data=cg.getchunks())
> outgoing = discovery.outgoing(repo, common + intermediates, heads)
> cg = changegroup.getchangegroup(repo, source, outgoing)
> cg = changegroup.getchangegroup(repo, source, outgoing,
> bundlecaps=bundlecaps)
> bundler.newpart('output', data='changegroup2')
> bundler.newpart('changegroup', data=cg.getchunks())
>