diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py --- a/mercurial/changegroup.py +++ b/mercurial/changegroup.py @@ -225,8 +225,11 @@ def readbundle(fh, fname): class bundle10(object): deltaheader = _BUNDLE10_DELTA_HEADER - def __init__(self): - pass + def __init__(self, bundlecaps=None): + # Set of capabilities we can use to build the bundle. + if bundlecaps is None: + bundlecaps = set() + self._bundlecaps = bundlecaps def start(self, lookup): self._lookup = lookup def close(self): diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1096,13 +1096,16 @@ def bundle(ui, repo, fname, dest=None, * base = ['null'] else: base = scmutil.revrange(repo, opts.get('base')) + # TODO: get desired bundlecaps from command line. + bundlecaps = None if base: if dest: raise util.Abort(_("--base is incompatible with specifying " "a destination")) common = [repo.lookup(rev) for rev in base] heads = revs and map(repo.lookup, revs) or revs - cg = repo.getbundle('bundle', heads=heads, common=common) + cg = repo.getbundle('bundle', heads=heads, common=common, + bundlecaps=bundlecaps) outgoing = None else: dest = ui.expandpath(dest or 'default-push', dest or 'default') @@ -1114,7 +1117,7 @@ def bundle(ui, repo, fname, dest=None, * onlyheads=heads, force=opts.get('force'), portable=True) - cg = repo.getlocalbundle('bundle', outgoing) + cg = repo.getlocalbundle('bundle', outgoing, bundlecaps) if not cg: scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded) return 1 @@ -1913,6 +1916,8 @@ def debuggetbundle(ui, repopath, bundlep args['common'] = [bin(s) for s in common] if head: args['heads'] = [bin(s) for s in head] + # TODO: get desired bundlecaps from command line. + args['bundlecaps'] = None bundle = repo.getbundle('debug', **args) bundletype = opts.get('type', 'bzip2').lower() diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -99,8 +99,9 @@ class localpeer(peer.peerrepository): def known(self, nodes): return self._repo.known(nodes) - def getbundle(self, source, heads=None, common=None): - return self._repo.getbundle(source, heads=heads, common=common) + def getbundle(self, source, heads=None, common=None, bundlecaps=None): + return self._repo.getbundle(source, heads=heads, common=common, + bundlecaps=None) # TODO We might want to move the next two calls into legacypeer and add # unbundle instead. @@ -1674,6 +1675,7 @@ class localrepository(object): heads = rheads if remote.capable('getbundle'): + # TODO: get bundlecaps from remote cg = remote.getbundle('pull', common=common, heads=heads or rheads) elif heads is None: @@ -1836,15 +1838,17 @@ class localrepository(object): remoteheads, newbranch, bool(inc)) + # TODO: get bundlecaps from remote + bundlecaps = None # create a changegroup from local if revs is None and not outgoing.excluded: # push everything, # use the fast path, no race possible on push - bundler = changegroup.bundle10() + bundler = changegroup.bundle10(bundlecaps) cg = self._changegroup(outgoing.missing, bundler, 'push') else: - cg = self.getlocalbundle('push', outgoing) + cg = self.getlocalbundle('push', outgoing, bundlecaps) # apply changegroup to remote if unbundle: @@ -1991,21 +1995,21 @@ class localrepository(object): bundler = changegroup.bundle10() return self._changegroupsubset(common, csets, heads, bundler, source) - def getlocalbundle(self, source, outgoing): + def getlocalbundle(self, source, outgoing, bundlecaps=None): """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 = changegroup.bundle10() + bundler = changegroup.bundle10(bundlecaps) return self._changegroupsubset(outgoing.common, outgoing.missing, outgoing.missingheads, bundler, source) - def getbundle(self, source, heads=None, common=None): + def getbundle(self, source, heads=None, common=None, bundlecaps=None): """Like changegroupsubset, but returns the set difference between the ancestors of heads and the ancestors common. @@ -2023,7 +2027,8 @@ class localrepository(object): if not heads: heads = cl.heads() return self.getlocalbundle(source, - discovery.outgoing(cl, common, heads)) + discovery.outgoing(cl, common, heads), + bundlecaps=bundlecaps) @unfilteredmethod def _changegroupsubset(self, commonrevs, csets, heads, bundler, source): diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -281,13 +281,15 @@ class wirepeer(peer.peerrepository): bases=bases, heads=heads) return changegroupmod.unbundle10(self._decompress(f), 'UN') - def getbundle(self, source, heads=None, common=None): + def getbundle(self, source, heads=None, common=None, bundlecaps=None): self.requirecap('getbundle', _('look up remote changes')) opts = {} if heads is not None: opts['heads'] = encodelist(heads) if common is not None: opts['common'] = encodelist(common) + if bundlecaps is not None: + opts['bundlecaps'] = ','.join(bundlecaps) f = self._callstream("getbundle", **opts) return changegroupmod.unbundle10(self._decompress(f), 'UN') @@ -449,9 +451,12 @@ def debugwireargs(repo, proto, one, two, return repo.debugwireargs(one, two, **opts) def getbundle(repo, proto, others): - opts = options('getbundle', ['heads', 'common'], others) + opts = options('getbundle', ['heads', 'common', 'bundlecaps'], others) for k, v in opts.iteritems(): - opts[k] = decodelist(v) + if k in ('heads', 'common'): + opts[k] = decodelist(v) + elif k == 'bundlecaps': + opts[k] = set(v.split(',')) cg = repo.getbundle('serve', **opts) return streamres(proto.groupchunks(cg))