cg3 inserts a custom marker in the stream once all manifests
have been transferred. This is currently abstracted out by
overriding a method.
Let's pass the end of manifests marker in as an argument to avoid
the extra method.
hg-reviewers |
cg3 inserts a custom marker in the stream once all manifests
have been transferred. This is currently abstracted out by
overriding a method.
Let's pass the end of manifests marker in as an argument to avoid
the extra method.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/changegroup.py (19 lines) |
Status | Author | Revision | |
---|---|---|---|
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg |
linknode = attr.ib() | linknode = attr.ib() | ||||
# 2 bytes of flags to apply to revision data. | # 2 bytes of flags to apply to revision data. | ||||
flags = attr.ib() | flags = attr.ib() | ||||
# Iterable of chunks holding raw delta data. | # Iterable of chunks holding raw delta data. | ||||
deltachunks = attr.ib() | deltachunks = attr.ib() | ||||
class cg1packer(object): | class cg1packer(object): | ||||
def __init__(self, repo, filematcher, version, builddeltaheader, | def __init__(self, repo, filematcher, version, builddeltaheader, | ||||
manifestsend, | |||||
bundlecaps=None): | bundlecaps=None): | ||||
"""Given a source repo, construct a bundler. | """Given a source repo, construct a bundler. | ||||
filematcher is a matcher that matches on files to include in the | filematcher is a matcher that matches on files to include in the | ||||
changegroup. Used to facilitate sparse changegroups. | changegroup. Used to facilitate sparse changegroups. | ||||
builddeltaheader is a callable that constructs the header for a group | builddeltaheader is a callable that constructs the header for a group | ||||
delta. | delta. | ||||
manifestsend is a chunk to send after manifests have been fully emitted. | |||||
bundlecaps is optional and can be used to specify the set of | bundlecaps is optional and can be used to specify the set of | ||||
capabilities which can be used to build the bundle. While bundlecaps is | capabilities which can be used to build the bundle. While bundlecaps is | ||||
unused in core Mercurial, extensions rely on this feature to communicate | unused in core Mercurial, extensions rely on this feature to communicate | ||||
capabilities to customize the changegroup packer. | capabilities to customize the changegroup packer. | ||||
""" | """ | ||||
assert filematcher | assert filematcher | ||||
self._filematcher = filematcher | self._filematcher = filematcher | ||||
self.version = version | self.version = version | ||||
self._builddeltaheader = builddeltaheader | self._builddeltaheader = builddeltaheader | ||||
self._manifestsend = manifestsend | |||||
# Set of capabilities we can use to build the bundle. | # Set of capabilities we can use to build the bundle. | ||||
if bundlecaps is None: | if bundlecaps is None: | ||||
bundlecaps = set() | bundlecaps = set() | ||||
self._bundlecaps = bundlecaps | self._bundlecaps = bundlecaps | ||||
# experimental config: bundle.reorder | # experimental config: bundle.reorder | ||||
reorder = repo.ui.config('bundle', 'reorder') | reorder = repo.ui.config('bundle', 'reorder') | ||||
if reorder == 'auto': | if reorder == 'auto': | ||||
def _packmanifests(self, dir, mfnodes, lookuplinknode): | def _packmanifests(self, dir, mfnodes, lookuplinknode): | ||||
"""Pack flat manifests into a changegroup stream.""" | """Pack flat manifests into a changegroup stream.""" | ||||
assert not dir | assert not dir | ||||
for chunk in self.group(mfnodes, self._repo.manifestlog._revlog, | for chunk in self.group(mfnodes, self._repo.manifestlog._revlog, | ||||
lookuplinknode, units=_('manifests')): | lookuplinknode, units=_('manifests')): | ||||
yield chunk | yield chunk | ||||
def _manifestsdone(self): | |||||
return '' | |||||
def generate(self, commonrevs, clnodes, fastpathlinkrev, source): | def generate(self, commonrevs, clnodes, fastpathlinkrev, source): | ||||
'''yield a sequence of changegroup chunks (strings)''' | '''yield a sequence of changegroup chunks (strings)''' | ||||
repo = self._repo | repo = self._repo | ||||
cl = repo.changelog | cl = repo.changelog | ||||
clrevorder = {} | clrevorder = {} | ||||
mfs = {} # needed manifests | mfs = {} # needed manifests | ||||
fnodes = {} # needed file nodes | fnodes = {} # needed file nodes | ||||
dir, nodes = tmfnodes.popitem() | dir, nodes = tmfnodes.popitem() | ||||
prunednodes = self.prune(dirlog(dir), nodes, commonrevs) | prunednodes = self.prune(dirlog(dir), nodes, commonrevs) | ||||
if not dir or prunednodes: | if not dir or prunednodes: | ||||
for x in self._packmanifests(dir, prunednodes, | for x in self._packmanifests(dir, prunednodes, | ||||
makelookupmflinknode(dir, nodes)): | makelookupmflinknode(dir, nodes)): | ||||
size += len(x) | size += len(x) | ||||
yield x | yield x | ||||
self._verbosenote(_('%8.i (manifests)\n') % size) | self._verbosenote(_('%8.i (manifests)\n') % size) | ||||
yield self._manifestsdone() | yield self._manifestsend | ||||
# The 'source' parameter is useful for extensions | # The 'source' parameter is useful for extensions | ||||
def generatefiles(self, changedfiles, linknodes, commonrevs, source): | def generatefiles(self, changedfiles, linknodes, commonrevs, source): | ||||
changedfiles = list(filter(self._filematcher, changedfiles)) | changedfiles = list(filter(self._filematcher, changedfiles)) | ||||
if getattr(self, 'is_shallow', False): | if getattr(self, 'is_shallow', False): | ||||
# See comment in generate() for why this sadness is a thing. | # See comment in generate() for why this sadness is a thing. | ||||
mfdicts = self._mfdicts | mfdicts = self._mfdicts | ||||
basenode=nullid, | basenode=nullid, | ||||
linknode=linknode, | linknode=linknode, | ||||
flags=flags, | flags=flags, | ||||
deltachunks=(diffheader, data), | deltachunks=(diffheader, data), | ||||
) | ) | ||||
class cg2packer(cg1packer): | class cg2packer(cg1packer): | ||||
def __init__(self, repo, filematcher, version, builddeltaheader, | def __init__(self, repo, filematcher, version, builddeltaheader, | ||||
bundlecaps=None): | manifestsend, bundlecaps=None): | ||||
super(cg2packer, self).__init__(repo, filematcher, version, | super(cg2packer, self).__init__(repo, filematcher, version, | ||||
builddeltaheader, | builddeltaheader, manifestsend, | ||||
bundlecaps=bundlecaps) | bundlecaps=bundlecaps) | ||||
if self._reorder is None: | if self._reorder is None: | ||||
# Since generaldelta is directly supported by cg2, reordering | # Since generaldelta is directly supported by cg2, reordering | ||||
# generally doesn't help, so we disable it by default (treating | # generally doesn't help, so we disable it by default (treating | ||||
# bundle.reorder=auto just like bundle.reorder=False). | # bundle.reorder=auto just like bundle.reorder=False). | ||||
self._reorder = False | self._reorder = False | ||||
if dir: | if dir: | ||||
yield self.fileheader(dir) | yield self.fileheader(dir) | ||||
dirlog = self._repo.manifestlog._revlog.dirlog(dir) | dirlog = self._repo.manifestlog._revlog.dirlog(dir) | ||||
for chunk in self.group(mfnodes, dirlog, lookuplinknode, | for chunk in self.group(mfnodes, dirlog, lookuplinknode, | ||||
units=_('manifests')): | units=_('manifests')): | ||||
yield chunk | yield chunk | ||||
def _manifestsdone(self): | |||||
return self.close() | |||||
def _makecg1packer(repo, filematcher, bundlecaps): | def _makecg1packer(repo, filematcher, bundlecaps): | ||||
builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( | builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( | ||||
d.node, d.p1node, d.p2node, d.linknode) | d.node, d.p1node, d.p2node, d.linknode) | ||||
return cg1packer(repo, filematcher, b'01', builddeltaheader, | return cg1packer(repo, filematcher, b'01', builddeltaheader, | ||||
manifestsend=b'', | |||||
bundlecaps=bundlecaps) | bundlecaps=bundlecaps) | ||||
def _makecg2packer(repo, filematcher, bundlecaps): | def _makecg2packer(repo, filematcher, bundlecaps): | ||||
builddeltaheader = lambda d: _CHANGEGROUPV2_DELTA_HEADER.pack( | builddeltaheader = lambda d: _CHANGEGROUPV2_DELTA_HEADER.pack( | ||||
d.node, d.p1node, d.p2node, d.basenode, d.linknode) | d.node, d.p1node, d.p2node, d.basenode, d.linknode) | ||||
return cg2packer(repo, filematcher, b'02', builddeltaheader, | return cg2packer(repo, filematcher, b'02', builddeltaheader, | ||||
manifestsend=b'', | |||||
bundlecaps=bundlecaps) | bundlecaps=bundlecaps) | ||||
def _makecg3packer(repo, filematcher, bundlecaps): | def _makecg3packer(repo, filematcher, bundlecaps): | ||||
builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( | builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( | ||||
d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) | d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) | ||||
return cg3packer(repo, filematcher, b'03', builddeltaheader, | return cg3packer(repo, filematcher, b'03', builddeltaheader, | ||||
manifestsend=closechunk(), | |||||
bundlecaps=bundlecaps) | bundlecaps=bundlecaps) | ||||
_packermap = {'01': (_makecg1packer, cg1unpacker), | _packermap = {'01': (_makecg1packer, cg1unpacker), | ||||
# cg2 adds support for exchanging generaldelta | # cg2 adds support for exchanging generaldelta | ||||
'02': (_makecg2packer, cg2unpacker), | '02': (_makecg2packer, cg2unpacker), | ||||
# cg3 adds support for exchanging revlog flags and treemanifests | # cg3 adds support for exchanging revlog flags and treemanifests | ||||
'03': (_makecg3packer, cg3unpacker), | '03': (_makecg3packer, cg3unpacker), | ||||
} | } |