Mercurial > hg
comparison mercurial/changegroup.py @ 29593:953839de96ab
bundle2: store changeset count when creating file bundles
The bundle2 changegroup part has an advisory param saying how many
changesets are in the part. Before this patch, we were setting
this part when generating bundle2 parts via the wire protocol but
not when generating local bundle2 files.
A side effect of not setting the changeset count part is that progress
bars don't work when applying changesets. As the tests show, this
impacted clone bundles, shelve, backup bundles, `hg unbundle`, and
anything touching bundle2 files.
This patch adds a backdoor to allow us to pass state from
changegroup generation into the unbundler. We store the number
of changesets in the changegroup in this state and use it to
populate the aforementioned advisory part parameter when generating
the bundle2 bundle.
I concede that I'm not thrilled by how state is being passed in
changegroup.py (it feels a bit hacky). I would love to overhaul the
rather confusing set of functions in changegroup.py with something that
passes rich objects around instead of e.g. low-level generators.
However, given the code freeze for 3.9 is imminent, I'd rather not
undertake this endeavor right now. This feels like the easiest way
to get the parameter added to the changegroup part.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 17 Jul 2016 15:13:51 -0700 |
parents | 1b699c7eb2b7 |
children | 5684bc429e6a |
comparison
equal
deleted
inserted
replaced
29592:37cccad55410 | 29593:953839de96ab |
---|---|
133 deltaheader = _CHANGEGROUPV1_DELTA_HEADER | 133 deltaheader = _CHANGEGROUPV1_DELTA_HEADER |
134 deltaheadersize = struct.calcsize(deltaheader) | 134 deltaheadersize = struct.calcsize(deltaheader) |
135 version = '01' | 135 version = '01' |
136 _grouplistcount = 1 # One list of files after the manifests | 136 _grouplistcount = 1 # One list of files after the manifests |
137 | 137 |
138 def __init__(self, fh, alg): | 138 def __init__(self, fh, alg, extras=None): |
139 if alg == 'UN': | 139 if alg == 'UN': |
140 alg = None # get more modern without breaking too much | 140 alg = None # get more modern without breaking too much |
141 if not alg in util.decompressors: | 141 if not alg in util.decompressors: |
142 raise error.Abort(_('unknown stream compression type: %s') | 142 raise error.Abort(_('unknown stream compression type: %s') |
143 % alg) | 143 % alg) |
144 if alg == 'BZ': | 144 if alg == 'BZ': |
145 alg = '_truncatedBZ' | 145 alg = '_truncatedBZ' |
146 self._stream = util.decompressors[alg](fh) | 146 self._stream = util.decompressors[alg](fh) |
147 self._type = alg | 147 self._type = alg |
148 self.extras = extras or {} | |
148 self.callback = None | 149 self.callback = None |
149 | 150 |
150 # These methods (compressed, read, seek, tell) all appear to only | 151 # These methods (compressed, read, seek, tell) all appear to only |
151 # be used by bundlerepo, but it's a little hard to tell. | 152 # be used by bundlerepo, but it's a little hard to tell. |
152 def compressed(self): | 153 def compressed(self): |
898 | 899 |
899 def getbundler(version, repo, bundlecaps=None): | 900 def getbundler(version, repo, bundlecaps=None): |
900 assert version in supportedoutgoingversions(repo) | 901 assert version in supportedoutgoingversions(repo) |
901 return _packermap[version][0](repo, bundlecaps) | 902 return _packermap[version][0](repo, bundlecaps) |
902 | 903 |
903 def getunbundler(version, fh, alg): | 904 def getunbundler(version, fh, alg, extras=None): |
904 return _packermap[version][1](fh, alg) | 905 return _packermap[version][1](fh, alg, extras=extras) |
905 | 906 |
906 def _changegroupinfo(repo, nodes, source): | 907 def _changegroupinfo(repo, nodes, source): |
907 if repo.ui.verbose or source == 'bundle': | 908 if repo.ui.verbose or source == 'bundle': |
908 repo.ui.status(_("%d changesets found\n") % len(nodes)) | 909 repo.ui.status(_("%d changesets found\n") % len(nodes)) |
909 if repo.ui.debugflag: | 910 if repo.ui.debugflag: |
927 _changegroupinfo(repo, csets, source) | 928 _changegroupinfo(repo, csets, source) |
928 return bundler.generate(commonrevs, csets, fastpathlinkrev, source) | 929 return bundler.generate(commonrevs, csets, fastpathlinkrev, source) |
929 | 930 |
930 def getsubset(repo, outgoing, bundler, source, fastpath=False): | 931 def getsubset(repo, outgoing, bundler, source, fastpath=False): |
931 gengroup = getsubsetraw(repo, outgoing, bundler, source, fastpath) | 932 gengroup = getsubsetraw(repo, outgoing, bundler, source, fastpath) |
932 return getunbundler(bundler.version, util.chunkbuffer(gengroup), None) | 933 return getunbundler(bundler.version, util.chunkbuffer(gengroup), None, |
934 {'clcount': len(outgoing.missing)}) | |
933 | 935 |
934 def changegroupsubset(repo, roots, heads, source, version='01'): | 936 def changegroupsubset(repo, roots, heads, source, version='01'): |
935 """Compute a changegroup consisting of all the nodes that are | 937 """Compute a changegroup consisting of all the nodes that are |
936 descendants of any of the roots and ancestors of any of the heads. | 938 descendants of any of the roots and ancestors of any of the heads. |
937 Return a chunkbuffer object whose read() method will return | 939 Return a chunkbuffer object whose read() method will return |