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