##// END OF EJS Templates
narrow: move heads close to common as they are closely related...
Pulkit Goyal -
r42561:343b3ed3 default
parent child Browse files
Show More
@@ -1,301 +1,301 b''
1 # narrowbundle2.py - bundle2 extensions for narrow repository support
1 # narrowbundle2.py - bundle2 extensions for narrow repository support
2 #
2 #
3 # Copyright 2017 Google, Inc.
3 # Copyright 2017 Google, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import struct
11 import struct
12
12
13 from mercurial.i18n import _
13 from mercurial.i18n import _
14 from mercurial.node import (
14 from mercurial.node import (
15 bin,
15 bin,
16 nullid,
16 nullid,
17 )
17 )
18 from mercurial import (
18 from mercurial import (
19 bundle2,
19 bundle2,
20 changegroup,
20 changegroup,
21 error,
21 error,
22 exchange,
22 exchange,
23 localrepo,
23 localrepo,
24 narrowspec,
24 narrowspec,
25 repair,
25 repair,
26 repository,
26 repository,
27 util,
27 util,
28 wireprototypes,
28 wireprototypes,
29 )
29 )
30 from mercurial.utils import (
30 from mercurial.utils import (
31 stringutil,
31 stringutil,
32 )
32 )
33
33
34 _NARROWACL_SECTION = 'narrowacl'
34 _NARROWACL_SECTION = 'narrowacl'
35 _CHANGESPECPART = 'narrow:changespec'
35 _CHANGESPECPART = 'narrow:changespec'
36 _RESSPECS = 'narrow:responsespec'
36 _RESSPECS = 'narrow:responsespec'
37 _SPECPART = 'narrow:spec'
37 _SPECPART = 'narrow:spec'
38 _SPECPART_INCLUDE = 'include'
38 _SPECPART_INCLUDE = 'include'
39 _SPECPART_EXCLUDE = 'exclude'
39 _SPECPART_EXCLUDE = 'exclude'
40 _KILLNODESIGNAL = 'KILL'
40 _KILLNODESIGNAL = 'KILL'
41 _DONESIGNAL = 'DONE'
41 _DONESIGNAL = 'DONE'
42 _ELIDEDCSHEADER = '>20s20s20sl' # cset id, p1, p2, len(text)
42 _ELIDEDCSHEADER = '>20s20s20sl' # cset id, p1, p2, len(text)
43 _ELIDEDMFHEADER = '>20s20s20s20sl' # manifest id, p1, p2, link id, len(text)
43 _ELIDEDMFHEADER = '>20s20s20s20sl' # manifest id, p1, p2, link id, len(text)
44 _CSHEADERSIZE = struct.calcsize(_ELIDEDCSHEADER)
44 _CSHEADERSIZE = struct.calcsize(_ELIDEDCSHEADER)
45 _MFHEADERSIZE = struct.calcsize(_ELIDEDMFHEADER)
45 _MFHEADERSIZE = struct.calcsize(_ELIDEDMFHEADER)
46
46
47 # Serve a changegroup for a client with a narrow clone.
47 # Serve a changegroup for a client with a narrow clone.
48 def getbundlechangegrouppart_narrow(bundler, repo, source,
48 def getbundlechangegrouppart_narrow(bundler, repo, source,
49 bundlecaps=None, b2caps=None, heads=None,
49 bundlecaps=None, b2caps=None, heads=None,
50 common=None, **kwargs):
50 common=None, **kwargs):
51 assert repo.ui.configbool('experimental', 'narrowservebrokenellipses')
51 assert repo.ui.configbool('experimental', 'narrowservebrokenellipses')
52
52
53 cgversions = b2caps.get('changegroup')
53 cgversions = b2caps.get('changegroup')
54 cgversions = [v for v in cgversions
54 cgversions = [v for v in cgversions
55 if v in changegroup.supportedoutgoingversions(repo)]
55 if v in changegroup.supportedoutgoingversions(repo)]
56 if not cgversions:
56 if not cgversions:
57 raise ValueError(_('no common changegroup version'))
57 raise ValueError(_('no common changegroup version'))
58 version = max(cgversions)
58 version = max(cgversions)
59
59
60 oldinclude = sorted(filter(bool, kwargs.get(r'oldincludepats', [])))
60 oldinclude = sorted(filter(bool, kwargs.get(r'oldincludepats', [])))
61 oldexclude = sorted(filter(bool, kwargs.get(r'oldexcludepats', [])))
61 oldexclude = sorted(filter(bool, kwargs.get(r'oldexcludepats', [])))
62 newinclude = sorted(filter(bool, kwargs.get(r'includepats', [])))
62 newinclude = sorted(filter(bool, kwargs.get(r'includepats', [])))
63 newexclude = sorted(filter(bool, kwargs.get(r'excludepats', [])))
63 newexclude = sorted(filter(bool, kwargs.get(r'excludepats', [])))
64 known = {bin(n) for n in kwargs.get('known', [])}
64 known = {bin(n) for n in kwargs.get('known', [])}
65 generateellipsesbundle2(bundler, repo, oldinclude, oldexclude, newinclude,
65 generateellipsesbundle2(bundler, repo, oldinclude, oldexclude, newinclude,
66 newexclude, version, common, known,
66 newexclude, version, common, heads, known,
67 kwargs.get(r'depth', None), heads)
67 kwargs.get(r'depth', None))
68
68
69 def generateellipsesbundle2(bundler, repo, oldinclude, oldexclude, newinclude,
69 def generateellipsesbundle2(bundler, repo, oldinclude, oldexclude, newinclude,
70 newexclude, version, common, known, depth, heads):
70 newexclude, version, common, heads, known, depth):
71 newmatch = narrowspec.match(repo.root, include=newinclude,
71 newmatch = narrowspec.match(repo.root, include=newinclude,
72 exclude=newexclude)
72 exclude=newexclude)
73 if depth is not None:
73 if depth is not None:
74 depth = int(depth)
74 depth = int(depth)
75 if depth < 1:
75 if depth < 1:
76 raise error.Abort(_('depth must be positive, got %d') % depth)
76 raise error.Abort(_('depth must be positive, got %d') % depth)
77
77
78 heads = set(heads or repo.heads())
78 heads = set(heads or repo.heads())
79 common = set(common or [nullid])
79 common = set(common or [nullid])
80 if known and (oldinclude != newinclude or oldexclude != newexclude):
80 if known and (oldinclude != newinclude or oldexclude != newexclude):
81 # Steps:
81 # Steps:
82 # 1. Send kill for "$known & ::common"
82 # 1. Send kill for "$known & ::common"
83 #
83 #
84 # 2. Send changegroup for ::common
84 # 2. Send changegroup for ::common
85 #
85 #
86 # 3. Proceed.
86 # 3. Proceed.
87 #
87 #
88 # In the future, we can send kills for only the specific
88 # In the future, we can send kills for only the specific
89 # nodes we know should go away or change shape, and then
89 # nodes we know should go away or change shape, and then
90 # send a data stream that tells the client something like this:
90 # send a data stream that tells the client something like this:
91 #
91 #
92 # a) apply this changegroup
92 # a) apply this changegroup
93 # b) apply nodes XXX, YYY, ZZZ that you already have
93 # b) apply nodes XXX, YYY, ZZZ that you already have
94 # c) goto a
94 # c) goto a
95 #
95 #
96 # until they've built up the full new state.
96 # until they've built up the full new state.
97 # Convert to revnums and intersect with "common". The client should
97 # Convert to revnums and intersect with "common". The client should
98 # have made it a subset of "common" already, but let's be safe.
98 # have made it a subset of "common" already, but let's be safe.
99 known = set(repo.revs("%ln & ::%ln", known, common))
99 known = set(repo.revs("%ln & ::%ln", known, common))
100 # TODO: we could send only roots() of this set, and the
100 # TODO: we could send only roots() of this set, and the
101 # list of nodes in common, and the client could work out
101 # list of nodes in common, and the client could work out
102 # what to strip, instead of us explicitly sending every
102 # what to strip, instead of us explicitly sending every
103 # single node.
103 # single node.
104 deadrevs = known
104 deadrevs = known
105 def genkills():
105 def genkills():
106 for r in deadrevs:
106 for r in deadrevs:
107 yield _KILLNODESIGNAL
107 yield _KILLNODESIGNAL
108 yield repo.changelog.node(r)
108 yield repo.changelog.node(r)
109 yield _DONESIGNAL
109 yield _DONESIGNAL
110 bundler.newpart(_CHANGESPECPART, data=genkills())
110 bundler.newpart(_CHANGESPECPART, data=genkills())
111 newvisit, newfull, newellipsis = exchange._computeellipsis(
111 newvisit, newfull, newellipsis = exchange._computeellipsis(
112 repo, set(), common, known, newmatch)
112 repo, set(), common, known, newmatch)
113 if newvisit:
113 if newvisit:
114 packer = changegroup.getbundler(version, repo,
114 packer = changegroup.getbundler(version, repo,
115 matcher=newmatch,
115 matcher=newmatch,
116 ellipses=True,
116 ellipses=True,
117 shallow=depth is not None,
117 shallow=depth is not None,
118 ellipsisroots=newellipsis,
118 ellipsisroots=newellipsis,
119 fullnodes=newfull)
119 fullnodes=newfull)
120 cgdata = packer.generate(common, newvisit, False, 'narrow_widen')
120 cgdata = packer.generate(common, newvisit, False, 'narrow_widen')
121
121
122 part = bundler.newpart('changegroup', data=cgdata)
122 part = bundler.newpart('changegroup', data=cgdata)
123 part.addparam('version', version)
123 part.addparam('version', version)
124 if 'treemanifest' in repo.requirements:
124 if 'treemanifest' in repo.requirements:
125 part.addparam('treemanifest', '1')
125 part.addparam('treemanifest', '1')
126
126
127 visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis(
127 visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis(
128 repo, common, heads, set(), newmatch, depth=depth)
128 repo, common, heads, set(), newmatch, depth=depth)
129
129
130 repo.ui.debug('Found %d relevant revs\n' % len(relevant_nodes))
130 repo.ui.debug('Found %d relevant revs\n' % len(relevant_nodes))
131 if visitnodes:
131 if visitnodes:
132 packer = changegroup.getbundler(version, repo,
132 packer = changegroup.getbundler(version, repo,
133 matcher=newmatch,
133 matcher=newmatch,
134 ellipses=True,
134 ellipses=True,
135 shallow=depth is not None,
135 shallow=depth is not None,
136 ellipsisroots=ellipsisroots,
136 ellipsisroots=ellipsisroots,
137 fullnodes=relevant_nodes)
137 fullnodes=relevant_nodes)
138 cgdata = packer.generate(common, visitnodes, False, 'narrow_widen')
138 cgdata = packer.generate(common, visitnodes, False, 'narrow_widen')
139
139
140 part = bundler.newpart('changegroup', data=cgdata)
140 part = bundler.newpart('changegroup', data=cgdata)
141 part.addparam('version', version)
141 part.addparam('version', version)
142 if 'treemanifest' in repo.requirements:
142 if 'treemanifest' in repo.requirements:
143 part.addparam('treemanifest', '1')
143 part.addparam('treemanifest', '1')
144
144
145 @bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE))
145 @bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE))
146 def _handlechangespec_2(op, inpart):
146 def _handlechangespec_2(op, inpart):
147 # XXX: This bundle2 handling is buggy and should be removed after hg5.2 is
147 # XXX: This bundle2 handling is buggy and should be removed after hg5.2 is
148 # released. New servers will send a mandatory bundle2 part named
148 # released. New servers will send a mandatory bundle2 part named
149 # 'Narrowspec' and will send specs as data instead of params.
149 # 'Narrowspec' and will send specs as data instead of params.
150 # Refer to issue5952 and 6019
150 # Refer to issue5952 and 6019
151 includepats = set(inpart.params.get(_SPECPART_INCLUDE, '').splitlines())
151 includepats = set(inpart.params.get(_SPECPART_INCLUDE, '').splitlines())
152 excludepats = set(inpart.params.get(_SPECPART_EXCLUDE, '').splitlines())
152 excludepats = set(inpart.params.get(_SPECPART_EXCLUDE, '').splitlines())
153 narrowspec.validatepatterns(includepats)
153 narrowspec.validatepatterns(includepats)
154 narrowspec.validatepatterns(excludepats)
154 narrowspec.validatepatterns(excludepats)
155
155
156 if not repository.NARROW_REQUIREMENT in op.repo.requirements:
156 if not repository.NARROW_REQUIREMENT in op.repo.requirements:
157 op.repo.requirements.add(repository.NARROW_REQUIREMENT)
157 op.repo.requirements.add(repository.NARROW_REQUIREMENT)
158 op.repo._writerequirements()
158 op.repo._writerequirements()
159 op.repo.setnarrowpats(includepats, excludepats)
159 op.repo.setnarrowpats(includepats, excludepats)
160 narrowspec.copytoworkingcopy(op.repo)
160 narrowspec.copytoworkingcopy(op.repo)
161
161
162 @bundle2.parthandler(_RESSPECS)
162 @bundle2.parthandler(_RESSPECS)
163 def _handlenarrowspecs(op, inpart):
163 def _handlenarrowspecs(op, inpart):
164 data = inpart.read()
164 data = inpart.read()
165 inc, exc = data.split('\0')
165 inc, exc = data.split('\0')
166 includepats = set(inc.splitlines())
166 includepats = set(inc.splitlines())
167 excludepats = set(exc.splitlines())
167 excludepats = set(exc.splitlines())
168 narrowspec.validatepatterns(includepats)
168 narrowspec.validatepatterns(includepats)
169 narrowspec.validatepatterns(excludepats)
169 narrowspec.validatepatterns(excludepats)
170
170
171 if repository.NARROW_REQUIREMENT not in op.repo.requirements:
171 if repository.NARROW_REQUIREMENT not in op.repo.requirements:
172 op.repo.requirements.add(repository.NARROW_REQUIREMENT)
172 op.repo.requirements.add(repository.NARROW_REQUIREMENT)
173 op.repo._writerequirements()
173 op.repo._writerequirements()
174 op.repo.setnarrowpats(includepats, excludepats)
174 op.repo.setnarrowpats(includepats, excludepats)
175 narrowspec.copytoworkingcopy(op.repo)
175 narrowspec.copytoworkingcopy(op.repo)
176
176
177 @bundle2.parthandler(_CHANGESPECPART)
177 @bundle2.parthandler(_CHANGESPECPART)
178 def _handlechangespec(op, inpart):
178 def _handlechangespec(op, inpart):
179 repo = op.repo
179 repo = op.repo
180 cl = repo.changelog
180 cl = repo.changelog
181
181
182 # changesets which need to be stripped entirely. either they're no longer
182 # changesets which need to be stripped entirely. either they're no longer
183 # needed in the new narrow spec, or the server is sending a replacement
183 # needed in the new narrow spec, or the server is sending a replacement
184 # in the changegroup part.
184 # in the changegroup part.
185 clkills = set()
185 clkills = set()
186
186
187 # A changespec part contains all the updates to ellipsis nodes
187 # A changespec part contains all the updates to ellipsis nodes
188 # that will happen as a result of widening or narrowing a
188 # that will happen as a result of widening or narrowing a
189 # repo. All the changes that this block encounters are ellipsis
189 # repo. All the changes that this block encounters are ellipsis
190 # nodes or flags to kill an existing ellipsis.
190 # nodes or flags to kill an existing ellipsis.
191 chunksignal = changegroup.readexactly(inpart, 4)
191 chunksignal = changegroup.readexactly(inpart, 4)
192 while chunksignal != _DONESIGNAL:
192 while chunksignal != _DONESIGNAL:
193 if chunksignal == _KILLNODESIGNAL:
193 if chunksignal == _KILLNODESIGNAL:
194 # a node used to be an ellipsis but isn't anymore
194 # a node used to be an ellipsis but isn't anymore
195 ck = changegroup.readexactly(inpart, 20)
195 ck = changegroup.readexactly(inpart, 20)
196 if cl.hasnode(ck):
196 if cl.hasnode(ck):
197 clkills.add(ck)
197 clkills.add(ck)
198 else:
198 else:
199 raise error.Abort(
199 raise error.Abort(
200 _('unexpected changespec node chunk type: %s') % chunksignal)
200 _('unexpected changespec node chunk type: %s') % chunksignal)
201 chunksignal = changegroup.readexactly(inpart, 4)
201 chunksignal = changegroup.readexactly(inpart, 4)
202
202
203 if clkills:
203 if clkills:
204 # preserve bookmarks that repair.strip() would otherwise strip
204 # preserve bookmarks that repair.strip() would otherwise strip
205 op._bookmarksbackup = repo._bookmarks
205 op._bookmarksbackup = repo._bookmarks
206 class dummybmstore(dict):
206 class dummybmstore(dict):
207 def applychanges(self, repo, tr, changes):
207 def applychanges(self, repo, tr, changes):
208 pass
208 pass
209 localrepo.localrepository._bookmarks.set(repo, dummybmstore())
209 localrepo.localrepository._bookmarks.set(repo, dummybmstore())
210 chgrpfile = repair.strip(op.ui, repo, list(clkills), backup=True,
210 chgrpfile = repair.strip(op.ui, repo, list(clkills), backup=True,
211 topic='widen')
211 topic='widen')
212 if chgrpfile:
212 if chgrpfile:
213 op._widen_uninterr = repo.ui.uninterruptible()
213 op._widen_uninterr = repo.ui.uninterruptible()
214 op._widen_uninterr.__enter__()
214 op._widen_uninterr.__enter__()
215 # presence of _widen_bundle attribute activates widen handler later
215 # presence of _widen_bundle attribute activates widen handler later
216 op._widen_bundle = chgrpfile
216 op._widen_bundle = chgrpfile
217 # Set the new narrowspec if we're widening. The setnewnarrowpats() method
217 # Set the new narrowspec if we're widening. The setnewnarrowpats() method
218 # will currently always be there when using the core+narrowhg server, but
218 # will currently always be there when using the core+narrowhg server, but
219 # other servers may include a changespec part even when not widening (e.g.
219 # other servers may include a changespec part even when not widening (e.g.
220 # because we're deepening a shallow repo).
220 # because we're deepening a shallow repo).
221 if util.safehasattr(repo, 'setnewnarrowpats'):
221 if util.safehasattr(repo, 'setnewnarrowpats'):
222 repo.setnewnarrowpats()
222 repo.setnewnarrowpats()
223
223
224 def handlechangegroup_widen(op, inpart):
224 def handlechangegroup_widen(op, inpart):
225 """Changegroup exchange handler which restores temporarily-stripped nodes"""
225 """Changegroup exchange handler which restores temporarily-stripped nodes"""
226 # We saved a bundle with stripped node data we must now restore.
226 # We saved a bundle with stripped node data we must now restore.
227 # This approach is based on mercurial/repair.py@6ee26a53c111.
227 # This approach is based on mercurial/repair.py@6ee26a53c111.
228 repo = op.repo
228 repo = op.repo
229 ui = op.ui
229 ui = op.ui
230
230
231 chgrpfile = op._widen_bundle
231 chgrpfile = op._widen_bundle
232 del op._widen_bundle
232 del op._widen_bundle
233 vfs = repo.vfs
233 vfs = repo.vfs
234
234
235 ui.note(_("adding branch\n"))
235 ui.note(_("adding branch\n"))
236 f = vfs.open(chgrpfile, "rb")
236 f = vfs.open(chgrpfile, "rb")
237 try:
237 try:
238 gen = exchange.readbundle(ui, f, chgrpfile, vfs)
238 gen = exchange.readbundle(ui, f, chgrpfile, vfs)
239 if not ui.verbose:
239 if not ui.verbose:
240 # silence internal shuffling chatter
240 # silence internal shuffling chatter
241 ui.pushbuffer()
241 ui.pushbuffer()
242 if isinstance(gen, bundle2.unbundle20):
242 if isinstance(gen, bundle2.unbundle20):
243 with repo.transaction('strip') as tr:
243 with repo.transaction('strip') as tr:
244 bundle2.processbundle(repo, gen, lambda: tr)
244 bundle2.processbundle(repo, gen, lambda: tr)
245 else:
245 else:
246 gen.apply(repo, 'strip', 'bundle:' + vfs.join(chgrpfile), True)
246 gen.apply(repo, 'strip', 'bundle:' + vfs.join(chgrpfile), True)
247 if not ui.verbose:
247 if not ui.verbose:
248 ui.popbuffer()
248 ui.popbuffer()
249 finally:
249 finally:
250 f.close()
250 f.close()
251
251
252 # remove undo files
252 # remove undo files
253 for undovfs, undofile in repo.undofiles():
253 for undovfs, undofile in repo.undofiles():
254 try:
254 try:
255 undovfs.unlink(undofile)
255 undovfs.unlink(undofile)
256 except OSError as e:
256 except OSError as e:
257 if e.errno != errno.ENOENT:
257 if e.errno != errno.ENOENT:
258 ui.warn(_('error removing %s: %s\n') %
258 ui.warn(_('error removing %s: %s\n') %
259 (undovfs.join(undofile), stringutil.forcebytestr(e)))
259 (undovfs.join(undofile), stringutil.forcebytestr(e)))
260
260
261 # Remove partial backup only if there were no exceptions
261 # Remove partial backup only if there were no exceptions
262 op._widen_uninterr.__exit__(None, None, None)
262 op._widen_uninterr.__exit__(None, None, None)
263 vfs.unlink(chgrpfile)
263 vfs.unlink(chgrpfile)
264
264
265 def setup():
265 def setup():
266 """Enable narrow repo support in bundle2-related extension points."""
266 """Enable narrow repo support in bundle2-related extension points."""
267 getbundleargs = wireprototypes.GETBUNDLE_ARGUMENTS
267 getbundleargs = wireprototypes.GETBUNDLE_ARGUMENTS
268
268
269 getbundleargs['narrow'] = 'boolean'
269 getbundleargs['narrow'] = 'boolean'
270 getbundleargs['depth'] = 'plain'
270 getbundleargs['depth'] = 'plain'
271 getbundleargs['oldincludepats'] = 'csv'
271 getbundleargs['oldincludepats'] = 'csv'
272 getbundleargs['oldexcludepats'] = 'csv'
272 getbundleargs['oldexcludepats'] = 'csv'
273 getbundleargs['known'] = 'csv'
273 getbundleargs['known'] = 'csv'
274
274
275 # Extend changegroup serving to handle requests from narrow clients.
275 # Extend changegroup serving to handle requests from narrow clients.
276 origcgfn = exchange.getbundle2partsmapping['changegroup']
276 origcgfn = exchange.getbundle2partsmapping['changegroup']
277 def wrappedcgfn(*args, **kwargs):
277 def wrappedcgfn(*args, **kwargs):
278 repo = args[1]
278 repo = args[1]
279 if repo.ui.has_section(_NARROWACL_SECTION):
279 if repo.ui.has_section(_NARROWACL_SECTION):
280 kwargs = exchange.applynarrowacl(repo, kwargs)
280 kwargs = exchange.applynarrowacl(repo, kwargs)
281
281
282 if (kwargs.get(r'narrow', False) and
282 if (kwargs.get(r'narrow', False) and
283 repo.ui.configbool('experimental', 'narrowservebrokenellipses')):
283 repo.ui.configbool('experimental', 'narrowservebrokenellipses')):
284 getbundlechangegrouppart_narrow(*args, **kwargs)
284 getbundlechangegrouppart_narrow(*args, **kwargs)
285 else:
285 else:
286 origcgfn(*args, **kwargs)
286 origcgfn(*args, **kwargs)
287 exchange.getbundle2partsmapping['changegroup'] = wrappedcgfn
287 exchange.getbundle2partsmapping['changegroup'] = wrappedcgfn
288
288
289 # Extend changegroup receiver so client can fixup after widen requests.
289 # Extend changegroup receiver so client can fixup after widen requests.
290 origcghandler = bundle2.parthandlermapping['changegroup']
290 origcghandler = bundle2.parthandlermapping['changegroup']
291 def wrappedcghandler(op, inpart):
291 def wrappedcghandler(op, inpart):
292 origcghandler(op, inpart)
292 origcghandler(op, inpart)
293 if util.safehasattr(op, '_widen_bundle'):
293 if util.safehasattr(op, '_widen_bundle'):
294 handlechangegroup_widen(op, inpart)
294 handlechangegroup_widen(op, inpart)
295 if util.safehasattr(op, '_bookmarksbackup'):
295 if util.safehasattr(op, '_bookmarksbackup'):
296 localrepo.localrepository._bookmarks.set(op.repo,
296 localrepo.localrepository._bookmarks.set(op.repo,
297 op._bookmarksbackup)
297 op._bookmarksbackup)
298 del op._bookmarksbackup
298 del op._bookmarksbackup
299
299
300 wrappedcghandler.params = origcghandler.params
300 wrappedcghandler.params = origcghandler.params
301 bundle2.parthandlermapping['changegroup'] = wrappedcghandler
301 bundle2.parthandlermapping['changegroup'] = wrappedcghandler
General Comments 0
You need to be logged in to leave comments. Login now