##// END OF EJS Templates
undo-files: move the undo cleanup code in the transaction module...
undo-files: move the undo cleanup code in the transaction module Now that undo creation is gathered in the transaction module, let us move the code cleaning them up there too. This will be useful to better clean previous undo files up before creating new ones.

File last commit:

r51194:3d0b5760 stable
r51194:3d0b5760 stable
Show More
narrowbundle2.py
345 lines | 11.0 KiB | text/x-python | PythonLexer
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 # narrowbundle2.py - bundle2 extensions for narrow repository support
#
# Copyright 2017 Google, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
import struct
from mercurial.i18n import _
from mercurial import (
bundle2,
changegroup,
error,
exchange,
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 localrepo,
Gregory Szorc
narrowspec: move module into core...
r36178 narrowspec,
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 repair,
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirements,
Pulkit Goyal
scmutil: add writereporequirements() and route requires writing through it...
r45666 scmutil,
undo-files: move the undo cleanup code in the transaction module...
r51194 transaction,
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 util,
Gregory Szorc
wireproto: move gboptsmap to wireprototypes and rename (API)...
r37631 wireprototypes,
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _NARROWACL_SECTION = b'narrowacl'
_CHANGESPECPART = b'narrow:changespec'
_RESSPECS = b'narrow:responsespec'
_SPECPART = b'narrow:spec'
_SPECPART_INCLUDE = b'include'
_SPECPART_EXCLUDE = b'exclude'
_KILLNODESIGNAL = b'KILL'
_DONESIGNAL = b'DONE'
_ELIDEDCSHEADER = b'>20s20s20sl' # cset id, p1, p2, len(text)
_ELIDEDMFHEADER = b'>20s20s20s20sl' # manifest id, p1, p2, link id, len(text)
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 _CSHEADERSIZE = struct.calcsize(_ELIDEDCSHEADER)
_MFHEADERSIZE = struct.calcsize(_ELIDEDMFHEADER)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Serve a changegroup for a client with a narrow clone.
Augie Fackler
formatting: blacken the codebase...
r43346 def getbundlechangegrouppart_narrow(
bundler,
repo,
source,
bundlecaps=None,
b2caps=None,
heads=None,
common=None,
**kwargs
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert repo.ui.configbool(b'experimental', b'narrowservebrokenellipses')
Gregory Szorc
exchange: move simple narrow changegroup generation from extension...
r38844
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cgversions = b2caps.get(b'changegroup')
Augie Fackler
formatting: blacken the codebase...
r43346 cgversions = [
v
for v in cgversions
if v in changegroup.supportedoutgoingversions(repo)
]
Pulkit Goyal
narrow: remove unrequired compat code for old versions of hg...
r42557 if not cgversions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(_(b'no common changegroup version'))
Pulkit Goyal
narrow: remove unrequired compat code for old versions of hg...
r42557 version = max(cgversions)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 include = sorted(filter(bool, kwargs.get('includepats', [])))
exclude = sorted(filter(bool, kwargs.get('excludepats', [])))
Augie Fackler
formatting: blacken the codebase...
r43346 generateellipsesbundle2(
bundler,
repo,
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 include,
exclude,
Augie Fackler
formatting: blacken the codebase...
r43346 version,
common,
heads,
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 kwargs.get('depth', None),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: blacken the codebase...
r43346 def generateellipsesbundle2(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 bundler,
repo,
include,
exclude,
version,
common,
heads,
depth,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 match = narrowspec.match(repo.root, include=include, exclude=exclude)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 if depth is not None:
depth = int(depth)
if depth < 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'depth must be positive, got %d') % depth)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
heads = set(heads or repo.heads())
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 common = set(common or [repo.nullid])
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Gregory Szorc
exchange: move _computeellipsis() from narrow...
r38827 visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis(
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 repo, common, heads, set(), match, depth=depth
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b'Found %d relevant revs\n' % len(relevant_nodes))
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 if visitnodes:
Augie Fackler
formatting: blacken the codebase...
r43346 packer = changegroup.getbundler(
version,
repo,
Martin von Zweigbergk
narrow: drop server support for widening using the getbundle command (BC)...
r43537 matcher=match,
Augie Fackler
formatting: blacken the codebase...
r43346 ellipses=True,
shallow=depth is not None,
ellipsisroots=ellipsisroots,
fullnodes=relevant_nodes,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cgdata = packer.generate(common, visitnodes, False, b'narrow_widen')
Gregory Szorc
changegroup: inline _packellipsischangegroup...
r38946
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part = bundler.newpart(b'changegroup', data=cgdata)
part.addparam(b'version', version)
Pulkit Goyal
scmutil: introduce function to check whether repo uses treemanifest or not...
r46129 if scmutil.istreemanifest(repo):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 part.addparam(b'treemanifest', b'1')
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536 def generate_ellipses_bundle2_for_widening(
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 bundler,
repo,
oldmatch,
newmatch,
version,
common,
known,
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536 ):
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 common = set(common or [repo.nullid])
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 # Steps:
# 1. Send kill for "$known & ::common"
#
# 2. Send changegroup for ::common
#
# 3. Proceed.
#
# In the future, we can send kills for only the specific
# nodes we know should go away or change shape, and then
# send a data stream that tells the client something like this:
#
# a) apply this changegroup
# b) apply nodes XXX, YYY, ZZZ that you already have
# c) goto a
#
# until they've built up the full new state.
Martin von Zweigbergk
widening: trust user to give full "known" set...
r43542 knownrevs = {repo.changelog.rev(n) for n in known}
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 # TODO: we could send only roots() of this set, and the
# list of nodes in common, and the client could work out
# what to strip, instead of us explicitly sending every
# single node.
Martin von Zweigbergk
widening: trust user to give full "known" set...
r43542 deadrevs = knownrevs
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 def genkills():
for r in deadrevs:
yield _KILLNODESIGNAL
yield repo.changelog.node(r)
yield _DONESIGNAL
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 bundler.newpart(_CHANGESPECPART, data=genkills())
newvisit, newfull, newellipsis = exchange._computeellipsis(
Martin von Zweigbergk
widening: trust user to give full "known" set...
r43542 repo, set(), common, knownrevs, newmatch
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 )
if newvisit:
packer = changegroup.getbundler(
version,
repo,
matcher=newmatch,
ellipses=True,
Martin von Zweigbergk
widening: remove "depth" argument since it's always None...
r43541 shallow=False,
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 ellipsisroots=newellipsis,
fullnodes=newfull,
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536 )
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 cgdata = packer.generate(common, newvisit, False, b'narrow_widen')
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 part = bundler.newpart(b'changegroup', data=cgdata)
part.addparam(b'version', version)
Pulkit Goyal
scmutil: introduce function to check whether repo uses treemanifest or not...
r46129 if scmutil.istreemanifest(repo):
Martin von Zweigbergk
widening: remove always-true condition in widening code...
r43538 part.addparam(b'treemanifest', b'1')
Martin von Zweigbergk
widening: duplicate generateellipsesbundle2() for widening...
r43536
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 @bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE))
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def _handlechangespec_2(op, inpart):
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 # XXX: This bundle2 handling is buggy and should be removed after hg5.2 is
# released. New servers will send a mandatory bundle2 part named
# 'Narrowspec' and will send specs as data instead of params.
# Refer to issue5952 and 6019
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 includepats = set(inpart.params.get(_SPECPART_INCLUDE, b'').splitlines())
excludepats = set(inpart.params.get(_SPECPART_EXCLUDE, b'').splitlines())
Gregory Szorc
narrow: validate patterns on incoming bundle2 part...
r39576 narrowspec.validatepatterns(includepats)
narrowspec.validatepatterns(excludepats)
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if not requirements.NARROW_REQUIREMENT in op.repo.requirements:
op.repo.requirements.add(requirements.NARROW_REQUIREMENT)
Pulkit Goyal
scmutil: add writereporequirements() and route requires writing through it...
r45666 scmutil.writereporequirements(op.repo)
Martin von Zweigbergk
narrow: reduce depedence on narrowspec.save()...
r36487 op.repo.setnarrowpats(includepats, excludepats)
Martin von Zweigbergk
narrow: move copytonarrowspec() out of setnarrowpats()...
r41272 narrowspec.copytoworkingcopy(op.repo)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 @bundle2.parthandler(_RESSPECS)
def _handlenarrowspecs(op, inpart):
data = inpart.read()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 inc, exc = data.split(b'\0')
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 includepats = set(inc.splitlines())
excludepats = set(exc.splitlines())
narrowspec.validatepatterns(includepats)
narrowspec.validatepatterns(excludepats)
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if requirements.NARROW_REQUIREMENT not in op.repo.requirements:
op.repo.requirements.add(requirements.NARROW_REQUIREMENT)
Pulkit Goyal
scmutil: add writereporequirements() and route requires writing through it...
r45666 scmutil.writereporequirements(op.repo)
Pulkit Goyal
narrow: send specs as bundle2 data instead of param (issue5952) (issue6019)...
r42393 op.repo.setnarrowpats(includepats, excludepats)
narrowspec.copytoworkingcopy(op.repo)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 @bundle2.parthandler(_CHANGESPECPART)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def _handlechangespec(op, inpart):
repo = op.repo
cl = repo.changelog
# changesets which need to be stripped entirely. either they're no longer
# needed in the new narrow spec, or the server is sending a replacement
# in the changegroup part.
clkills = set()
# A changespec part contains all the updates to ellipsis nodes
# that will happen as a result of widening or narrowing a
# repo. All the changes that this block encounters are ellipsis
# nodes or flags to kill an existing ellipsis.
chunksignal = changegroup.readexactly(inpart, 4)
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 while chunksignal != _DONESIGNAL:
if chunksignal == _KILLNODESIGNAL:
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 # a node used to be an ellipsis but isn't anymore
ck = changegroup.readexactly(inpart, 20)
if cl.hasnode(ck):
clkills.add(ck)
else:
raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'unexpected changespec node chunk type: %s') % chunksignal
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 chunksignal = changegroup.readexactly(inpart, 4)
if clkills:
# preserve bookmarks that repair.strip() would otherwise strip
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 op._bookmarksbackup = repo._bookmarks
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 class dummybmstore(dict):
def applychanges(self, repo, tr, changes):
pass
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 localrepo.localrepository._bookmarks.set(repo, dummybmstore())
Augie Fackler
formatting: blacken the codebase...
r43346 chgrpfile = repair.strip(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 op.ui, repo, list(clkills), backup=True, topic=b'widen'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 if chgrpfile:
Kyle Lippincott
procutil: correct spelling of uninterruptable -> uninterruptible...
r41106 op._widen_uninterr = repo.ui.uninterruptible()
Augie Fackler
narrowbundle2: when we handle a widen, mark the operation as unsafe...
r38548 op._widen_uninterr.__enter__()
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 # presence of _widen_bundle attribute activates widen handler later
op._widen_bundle = chgrpfile
# Set the new narrowspec if we're widening. The setnewnarrowpats() method
# will currently always be there when using the core+narrowhg server, but
# other servers may include a changespec part even when not widening (e.g.
# because we're deepening a shallow repo).
Martin von Zweigbergk
py3: delete b'' prefix from safehasattr arguments...
r43385 if util.safehasattr(repo, 'setnewnarrowpats'):
narrow: open the transaction sooner when unbundling...
r51085 op.gettransaction()
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 repo.setnewnarrowpats()
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def handlechangegroup_widen(op, inpart):
"""Changegroup exchange handler which restores temporarily-stripped nodes"""
# We saved a bundle with stripped node data we must now restore.
# This approach is based on mercurial/repair.py@6ee26a53c111.
repo = op.repo
ui = op.ui
chgrpfile = op._widen_bundle
del op._widen_bundle
vfs = repo.vfs
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b"adding branch\n"))
f = vfs.open(chgrpfile, b"rb")
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 try:
gen = exchange.readbundle(ui, f, chgrpfile, vfs)
narrow: rely on setting `quiet` mode instead of `pushbuffer`...
r43165 # silence internal shuffling chatter
Martin von Zweigbergk
narrowbundle: use new context manager for silencing the ui...
r48232 maybe_silent = (
ui.silent() if not ui.verbose else util.nullcontextmanager()
)
with maybe_silent:
narrow: rely on setting `quiet` mode instead of `pushbuffer`...
r43165 if isinstance(gen, bundle2.unbundle20):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with repo.transaction(b'strip') as tr:
narrow: rely on setting `quiet` mode instead of `pushbuffer`...
r43165 bundle2.processbundle(repo, gen, lambda: tr)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 gen.apply(
repo, b'strip', b'bundle:' + vfs.join(chgrpfile), True
)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 finally:
f.close()
undo-files: move the undo cleanup code in the transaction module...
r51194 transaction.cleanup_undo_files(repo)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Remove partial backup only if there were no exceptions
Augie Fackler
narrowbundle2: when we handle a widen, mark the operation as unsafe...
r38548 op._widen_uninterr.__exit__(None, None, None)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 vfs.unlink(chgrpfile)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def setup():
"""Enable narrow repo support in bundle2-related extension points."""
Gregory Szorc
wireproto: move gboptsmap to wireprototypes and rename (API)...
r37631 getbundleargs = wireprototypes.GETBUNDLE_ARGUMENTS
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 getbundleargs[b'narrow'] = b'boolean'
getbundleargs[b'depth'] = b'plain'
getbundleargs[b'oldincludepats'] = b'csv'
getbundleargs[b'oldexcludepats'] = b'csv'
getbundleargs[b'known'] = b'csv'
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Extend changegroup serving to handle requests from narrow clients.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 origcgfn = exchange.getbundle2partsmapping[b'changegroup']
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def wrappedcgfn(*args, **kwargs):
repo = args[1]
Augie Fackler
narrowbundle2: mark most constants as module-private...
r36104 if repo.ui.has_section(_NARROWACL_SECTION):
Gregory Szorc
exchange: make narrow ACL presence imply narrow=True...
r38843 kwargs = exchange.applynarrowacl(repo, kwargs)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if kwargs.get('narrow', False) and repo.ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'experimental', b'narrowservebrokenellipses'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 getbundlechangegrouppart_narrow(*args, **kwargs)
else:
origcgfn(*args, **kwargs)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 exchange.getbundle2partsmapping[b'changegroup'] = wrappedcgfn
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
# Extend changegroup receiver so client can fixup after widen requests.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 origcghandler = bundle2.parthandlermapping[b'changegroup']
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def wrappedcghandler(op, inpart):
origcghandler(op, inpart)
Martin von Zweigbergk
py3: delete b'' prefix from safehasattr arguments...
r43385 if util.safehasattr(op, '_widen_bundle'):
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 handlechangegroup_widen(op, inpart)
Martin von Zweigbergk
py3: delete b'' prefix from safehasattr arguments...
r43385 if util.safehasattr(op, '_bookmarksbackup'):
Augie Fackler
formatting: blacken the codebase...
r43346 localrepo.localrepository._bookmarks.set(
op.repo, op._bookmarksbackup
)
Martin von Zweigbergk
narrow: keep bookmarks temporarily stripped for as long as commits are...
r40903 del op._bookmarksbackup
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 wrappedcghandler.params = origcghandler.params
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundle2.parthandlermapping[b'changegroup'] = wrappedcghandler