diff -r 2372284d9457 -r 687b865b95ad mercurial/wireprotov1server.py --- a/mercurial/wireprotov1server.py Sun Oct 06 09:45:02 2019 -0400 +++ b/mercurial/wireprotov1server.py Sun Oct 06 09:48:39 2019 -0400 @@ -38,11 +38,11 @@ urlerr = util.urlerr urlreq = util.urlreq -bundle2requiredmain = _('incompatible Mercurial client; bundle2 required') +bundle2requiredmain = _(b'incompatible Mercurial client; bundle2 required') bundle2requiredhint = _( - 'see https://www.mercurial-scm.org/wiki/' 'IncompatibleClient' + b'see https://www.mercurial-scm.org/wiki/' b'IncompatibleClient' ) -bundle2required = '%s\n(%s)\n' % (bundle2requiredmain, bundle2requiredhint) +bundle2required = b'%s\n(%s)\n' % (bundle2requiredmain, bundle2requiredhint) def clientcompressionsupport(proto): @@ -53,9 +53,9 @@ been announced, fallback to the default of zlib and uncompressed. """ for cap in proto.getprotocaps(): - if cap.startswith('comp='): - return cap[5:].split(',') - return ['zlib', 'none'] + if cap.startswith(b'comp='): + return cap[5:].split(b',') + return [b'zlib', b'none'] # wire protocol command can either return a string or one of these classes. @@ -68,7 +68,7 @@ extensions that need commands to operate on different repo views under specialized circumstances. """ - viewconfig = repo.ui.config('server', 'view') + viewconfig = repo.ui.config(b'server', b'view') return repo.filtered(viewconfig) @@ -89,8 +89,8 @@ del others[k] if others: procutil.stderr.write( - "warning: %s ignored unexpected arguments %s\n" - % (cmd, ",".join(others)) + b"warning: %s ignored unexpected arguments %s\n" + % (cmd, b",".join(others)) ) return opts @@ -106,29 +106,29 @@ 4. server.bundle1 """ ui = repo.ui - gd = 'generaldelta' in repo.requirements + gd = b'generaldelta' in repo.requirements if gd: - v = ui.configbool('server', 'bundle1gd.%s' % action) + v = ui.configbool(b'server', b'bundle1gd.%s' % action) if v is not None: return v - v = ui.configbool('server', 'bundle1.%s' % action) + v = ui.configbool(b'server', b'bundle1.%s' % action) if v is not None: return v if gd: - v = ui.configbool('server', 'bundle1gd') + v = ui.configbool(b'server', b'bundle1gd') if v is not None: return v - return ui.configbool('server', 'bundle1') + return ui.configbool(b'server', b'bundle1') commands = wireprototypes.commanddict() -def wireprotocommand(name, args=None, permission='push'): +def wireprotocommand(name, args=None, permission=b'push'): """Decorator to declare a wire protocol command. ``name`` is the name of the wire protocol command being provided. @@ -144,7 +144,7 @@ a repository that is supposed to be read-only. """ transports = { - k for k, v in wireprototypes.TRANSPORTS.items() if v['version'] == 1 + k for k, v in wireprototypes.TRANSPORTS.items() if v[b'version'] == 1 } # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to @@ -153,24 +153,24 @@ if name == b'batch': transports.add(wireprototypes.SSHV2) - if permission not in ('push', 'pull'): + if permission not in (b'push', b'pull'): raise error.ProgrammingError( - 'invalid wire protocol permission; ' - 'got %s; expected "push" or "pull"' % permission + b'invalid wire protocol permission; ' + b'got %s; expected "push" or "pull"' % permission ) if args is None: - args = '' + args = b'' if not isinstance(args, bytes): raise error.ProgrammingError( - 'arguments for version 1 commands ' 'must be declared as bytes' + b'arguments for version 1 commands ' b'must be declared as bytes' ) def register(func): if name in commands: raise error.ProgrammingError( - '%s command already registered ' 'for version 1' % name + b'%s command already registered ' b'for version 1' % name ) commands[name] = wireprototypes.commandentry( func, args=args, transports=transports, permission=permission @@ -182,34 +182,34 @@ # TODO define a more appropriate permissions type to use for this. -@wireprotocommand('batch', 'cmds *', permission='pull') +@wireprotocommand(b'batch', b'cmds *', permission=b'pull') def batch(repo, proto, cmds, others): unescapearg = wireprototypes.unescapebatcharg res = [] - for pair in cmds.split(';'): - op, args = pair.split(' ', 1) + for pair in cmds.split(b';'): + op, args = pair.split(b' ', 1) vals = {} - for a in args.split(','): + for a in args.split(b','): if a: - n, v = a.split('=') + n, v = a.split(b'=') vals[unescapearg(n)] = unescapearg(v) func, spec = commands[op] # Validate that client has permissions to perform this command. perm = commands[op].permission - assert perm in ('push', 'pull') + assert perm in (b'push', b'pull') proto.checkperm(perm) if spec: keys = spec.split() data = {} for k in keys: - if k == '*': + if k == b'*': star = {} for key in vals.keys(): if key not in keys: star[key] = vals[key] - data['*'] = star + data[b'*'] = star else: data[k] = vals[k] result = func(repo, proto, *[data[k] for k in keys]) @@ -225,42 +225,42 @@ result = result.data res.append(wireprototypes.escapebatcharg(result)) - return wireprototypes.bytesresponse(';'.join(res)) + return wireprototypes.bytesresponse(b';'.join(res)) -@wireprotocommand('between', 'pairs', permission='pull') +@wireprotocommand(b'between', b'pairs', permission=b'pull') def between(repo, proto, pairs): - pairs = [wireprototypes.decodelist(p, '-') for p in pairs.split(" ")] + pairs = [wireprototypes.decodelist(p, b'-') for p in pairs.split(b" ")] r = [] for b in repo.between(pairs): - r.append(wireprototypes.encodelist(b) + "\n") + r.append(wireprototypes.encodelist(b) + b"\n") - return wireprototypes.bytesresponse(''.join(r)) + return wireprototypes.bytesresponse(b''.join(r)) -@wireprotocommand('branchmap', permission='pull') +@wireprotocommand(b'branchmap', permission=b'pull') def branchmap(repo, proto): branchmap = repo.branchmap() heads = [] for branch, nodes in branchmap.iteritems(): branchname = urlreq.quote(encoding.fromlocal(branch)) branchnodes = wireprototypes.encodelist(nodes) - heads.append('%s %s' % (branchname, branchnodes)) + heads.append(b'%s %s' % (branchname, branchnodes)) - return wireprototypes.bytesresponse('\n'.join(heads)) + return wireprototypes.bytesresponse(b'\n'.join(heads)) -@wireprotocommand('branches', 'nodes', permission='pull') +@wireprotocommand(b'branches', b'nodes', permission=b'pull') def branches(repo, proto, nodes): nodes = wireprototypes.decodelist(nodes) r = [] for b in repo.branches(nodes): - r.append(wireprototypes.encodelist(b) + "\n") + r.append(wireprototypes.encodelist(b) + b"\n") - return wireprototypes.bytesresponse(''.join(r)) + return wireprototypes.bytesresponse(b''.join(r)) -@wireprotocommand('clonebundles', '', permission='pull') +@wireprotocommand(b'clonebundles', b'', permission=b'pull') def clonebundles(repo, proto): """Server command for returning info for available bundles to seed clones. @@ -271,17 +271,17 @@ data center given the client's IP address. """ return wireprototypes.bytesresponse( - repo.vfs.tryread('clonebundles.manifest') + repo.vfs.tryread(b'clonebundles.manifest') ) wireprotocaps = [ - 'lookup', - 'branchmap', - 'pushkey', - 'known', - 'getbundle', - 'unbundlehash', + b'lookup', + b'branchmap', + b'pushkey', + b'known', + b'getbundle', + b'unbundlehash', ] @@ -300,27 +300,27 @@ # Command of same name as capability isn't exposed to version 1 of # transports. So conditionally add it. - if commands.commandavailable('changegroupsubset', proto): - caps.append('changegroupsubset') + if commands.commandavailable(b'changegroupsubset', proto): + caps.append(b'changegroupsubset') if streamclone.allowservergeneration(repo): - if repo.ui.configbool('server', 'preferuncompressed'): - caps.append('stream-preferred') + if repo.ui.configbool(b'server', b'preferuncompressed'): + caps.append(b'stream-preferred') requiredformats = repo.requirements & repo.supportedformats # if our local revlogs are just revlogv1, add 'stream' cap - if not requiredformats - {'revlogv1'}: - caps.append('stream') + if not requiredformats - {b'revlogv1'}: + caps.append(b'stream') # otherwise, add 'streamreqs' detailing our local revlog format else: - caps.append('streamreqs=%s' % ','.join(sorted(requiredformats))) - if repo.ui.configbool('experimental', 'bundle2-advertise'): - capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role='server')) - caps.append('bundle2=' + urlreq.quote(capsblob)) - caps.append('unbundle=%s' % ','.join(bundle2.bundlepriority)) + caps.append(b'streamreqs=%s' % b','.join(sorted(requiredformats))) + if repo.ui.configbool(b'experimental', b'bundle2-advertise'): + capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role=b'server')) + caps.append(b'bundle2=' + urlreq.quote(capsblob)) + caps.append(b'unbundle=%s' % b','.join(bundle2.bundlepriority)) - if repo.ui.configbool('experimental', 'narrow'): + if repo.ui.configbool(b'experimental', b'narrow'): caps.append(wireprototypes.NARROWCAP) - if repo.ui.configbool('experimental', 'narrowservebrokenellipses'): + if repo.ui.configbool(b'experimental', b'narrowservebrokenellipses'): caps.append(wireprototypes.ELLIPSESCAP) return proto.addcapabilities(repo, caps) @@ -328,37 +328,37 @@ # If you are writing an extension and consider wrapping this function. Wrap # `_capabilities` instead. -@wireprotocommand('capabilities', permission='pull') +@wireprotocommand(b'capabilities', permission=b'pull') def capabilities(repo, proto): caps = _capabilities(repo, proto) - return wireprototypes.bytesresponse(' '.join(sorted(caps))) + return wireprototypes.bytesresponse(b' '.join(sorted(caps))) -@wireprotocommand('changegroup', 'roots', permission='pull') +@wireprotocommand(b'changegroup', b'roots', permission=b'pull') def changegroup(repo, proto, roots): nodes = wireprototypes.decodelist(roots) outgoing = discovery.outgoing( repo, missingroots=nodes, missingheads=repo.heads() ) - cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve') - gen = iter(lambda: cg.read(32768), '') + cg = changegroupmod.makechangegroup(repo, outgoing, b'01', b'serve') + gen = iter(lambda: cg.read(32768), b'') return wireprototypes.streamres(gen=gen) -@wireprotocommand('changegroupsubset', 'bases heads', permission='pull') +@wireprotocommand(b'changegroupsubset', b'bases heads', permission=b'pull') def changegroupsubset(repo, proto, bases, heads): bases = wireprototypes.decodelist(bases) heads = wireprototypes.decodelist(heads) outgoing = discovery.outgoing(repo, missingroots=bases, missingheads=heads) - cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve') - gen = iter(lambda: cg.read(32768), '') + cg = changegroupmod.makechangegroup(repo, outgoing, b'01', b'serve') + gen = iter(lambda: cg.read(32768), b'') return wireprototypes.streamres(gen=gen) -@wireprotocommand('debugwireargs', 'one two *', permission='pull') +@wireprotocommand(b'debugwireargs', b'one two *', permission=b'pull') def debugwireargs(repo, proto, one, two, others): # only accept optional args from the known set - opts = options('debugwireargs', ['three', 'four'], others) + opts = options(b'debugwireargs', [b'three', b'four'], others) return wireprototypes.bytesresponse( repo.debugwireargs(one, two, **pycompat.strkwargs(opts)) ) @@ -381,9 +381,9 @@ """ def decodehexstring(s): - return {binascii.unhexlify(h) for h in s.split(';')} + return {binascii.unhexlify(h) for h in s.split(b';')} - manifest = repo.vfs.tryread('pullbundles.manifest') + manifest = repo.vfs.tryread(b'pullbundles.manifest') if not manifest: return None res = exchange.parseclonebundlesmanifest(repo, manifest) @@ -395,15 +395,15 @@ common_anc = cl.ancestors([cl.rev(rev) for rev in common], inclusive=True) compformats = clientcompressionsupport(proto) for entry in res: - comp = entry.get('COMPRESSION') + comp = entry.get(b'COMPRESSION') altcomp = util.compengines._bundlenames.get(comp) if comp and comp not in compformats and altcomp not in compformats: continue # No test yet for VERSION, since V2 is supported by any client # that advertises partial pulls - if 'heads' in entry: + if b'heads' in entry: try: - bundle_heads = decodehexstring(entry['heads']) + bundle_heads = decodehexstring(entry[b'heads']) except TypeError: # Bad heads entry continue @@ -416,61 +416,61 @@ for rev in bundle_heads ): continue - if 'bases' in entry: + if b'bases' in entry: try: - bundle_bases = decodehexstring(entry['bases']) + bundle_bases = decodehexstring(entry[b'bases']) except TypeError: # Bad bases entry continue if not all(cl.rev(rev) in common_anc for rev in bundle_bases): continue - path = entry['URL'] - repo.ui.debug('sending pullbundle "%s"\n' % path) + path = entry[b'URL'] + repo.ui.debug(b'sending pullbundle "%s"\n' % path) try: return repo.vfs.open(path) except IOError: - repo.ui.debug('pullbundle "%s" not accessible\n' % path) + repo.ui.debug(b'pullbundle "%s" not accessible\n' % path) continue return None -@wireprotocommand('getbundle', '*', permission='pull') +@wireprotocommand(b'getbundle', b'*', permission=b'pull') def getbundle(repo, proto, others): opts = options( - 'getbundle', wireprototypes.GETBUNDLE_ARGUMENTS.keys(), others + b'getbundle', wireprototypes.GETBUNDLE_ARGUMENTS.keys(), others ) for k, v in opts.iteritems(): keytype = wireprototypes.GETBUNDLE_ARGUMENTS[k] - if keytype == 'nodes': + if keytype == b'nodes': opts[k] = wireprototypes.decodelist(v) - elif keytype == 'csv': - opts[k] = list(v.split(',')) - elif keytype == 'scsv': - opts[k] = set(v.split(',')) - elif keytype == 'boolean': + elif keytype == b'csv': + opts[k] = list(v.split(b',')) + elif keytype == b'scsv': + opts[k] = set(v.split(b',')) + elif keytype == b'boolean': # Client should serialize False as '0', which is a non-empty string # so it evaluates as a True bool. - if v == '0': + if v == b'0': opts[k] = False else: opts[k] = bool(v) - elif keytype != 'plain': - raise KeyError('unknown getbundle option type %s' % keytype) + elif keytype != b'plain': + raise KeyError(b'unknown getbundle option type %s' % keytype) - if not bundle1allowed(repo, 'pull'): - if not exchange.bundle2requested(opts.get('bundlecaps')): - if proto.name == 'http-v1': + if not bundle1allowed(repo, b'pull'): + if not exchange.bundle2requested(opts.get(b'bundlecaps')): + if proto.name == b'http-v1': return wireprototypes.ooberror(bundle2required) raise error.Abort(bundle2requiredmain, hint=bundle2requiredhint) try: clheads = set(repo.changelog.heads()) - heads = set(opts.get('heads', set())) - common = set(opts.get('common', set())) + heads = set(opts.get(b'heads', set())) + common = set(opts.get(b'common', set())) common.discard(nullid) if ( - repo.ui.configbool('server', 'pullbundle') - and 'partial-pull' in proto.getprotocaps() + repo.ui.configbool(b'server', b'pullbundle') + and b'partial-pull' in proto.getprotocaps() ): # Check if a pre-built bundle covers this request. bundle = find_pullbundle(repo, proto, opts, clheads, heads, common) @@ -479,32 +479,32 @@ gen=util.filechunkiter(bundle), prefer_uncompressed=True ) - if repo.ui.configbool('server', 'disablefullbundle'): + if repo.ui.configbool(b'server', b'disablefullbundle'): # Check to see if this is a full clone. - changegroup = opts.get('cg', True) + changegroup = opts.get(b'cg', True) if changegroup and not common and clheads == heads: raise error.Abort( - _('server has pull-based clones disabled'), - hint=_('remove --pull if specified or upgrade Mercurial'), + _(b'server has pull-based clones disabled'), + hint=_(b'remove --pull if specified or upgrade Mercurial'), ) info, chunks = exchange.getbundlechunks( - repo, 'serve', **pycompat.strkwargs(opts) + repo, b'serve', **pycompat.strkwargs(opts) ) - prefercompressed = info.get('prefercompressed', True) + prefercompressed = info.get(b'prefercompressed', True) except error.Abort as exc: # cleanly forward Abort error to the client - if not exchange.bundle2requested(opts.get('bundlecaps')): - if proto.name == 'http-v1': - return wireprototypes.ooberror(pycompat.bytestr(exc) + '\n') + if not exchange.bundle2requested(opts.get(b'bundlecaps')): + if proto.name == b'http-v1': + return wireprototypes.ooberror(pycompat.bytestr(exc) + b'\n') raise # cannot do better for bundle1 + ssh # bundle2 request expect a bundle2 reply bundler = bundle2.bundle20(repo.ui) - manargs = [('message', pycompat.bytestr(exc))] + manargs = [(b'message', pycompat.bytestr(exc))] advargs = [] if exc.hint is not None: - advargs.append(('hint', exc.hint)) - bundler.addpart(bundle2.bundlepart('error:abort', manargs, advargs)) + advargs.append((b'hint', exc.hint)) + bundler.addpart(bundle2.bundlepart(b'error:abort', manargs, advargs)) chunks = bundler.getchunks() prefercompressed = False @@ -513,13 +513,13 @@ ) -@wireprotocommand('heads', permission='pull') +@wireprotocommand(b'heads', permission=b'pull') def heads(repo, proto): h = repo.heads() - return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + '\n') + return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + b'\n') -@wireprotocommand('hello', permission='pull') +@wireprotocommand(b'hello', permission=b'pull') def hello(repo, proto): """Called as part of SSH handshake to obtain server info. @@ -532,16 +532,16 @@ capabilities: """ caps = capabilities(repo, proto).data - return wireprototypes.bytesresponse('capabilities: %s\n' % caps) + return wireprototypes.bytesresponse(b'capabilities: %s\n' % caps) -@wireprotocommand('listkeys', 'namespace', permission='pull') +@wireprotocommand(b'listkeys', b'namespace', permission=b'pull') def listkeys(repo, proto, namespace): d = sorted(repo.listkeys(encoding.tolocal(namespace)).items()) return wireprototypes.bytesresponse(pushkeymod.encodekeys(d)) -@wireprotocommand('lookup', 'key', permission='pull') +@wireprotocommand(b'lookup', b'key', permission=b'pull') def lookup(repo, proto, key): try: k = encoding.tolocal(key) @@ -551,25 +551,25 @@ except Exception as inst: r = stringutil.forcebytestr(inst) success = 0 - return wireprototypes.bytesresponse('%d %s\n' % (success, r)) + return wireprototypes.bytesresponse(b'%d %s\n' % (success, r)) -@wireprotocommand('known', 'nodes *', permission='pull') +@wireprotocommand(b'known', b'nodes *', permission=b'pull') def known(repo, proto, nodes, others): - v = ''.join( - b and '1' or '0' for b in repo.known(wireprototypes.decodelist(nodes)) + v = b''.join( + b and b'1' or b'0' for b in repo.known(wireprototypes.decodelist(nodes)) ) return wireprototypes.bytesresponse(v) -@wireprotocommand('protocaps', 'caps', permission='pull') +@wireprotocommand(b'protocaps', b'caps', permission=b'pull') def protocaps(repo, proto, caps): if proto.name == wireprototypes.SSHV1: - proto._protocaps = set(caps.split(' ')) - return wireprototypes.bytesresponse('OK') + proto._protocaps = set(caps.split(b' ')) + return wireprototypes.bytesresponse(b'OK') -@wireprotocommand('pushkey', 'namespace key old new', permission='push') +@wireprotocommand(b'pushkey', b'namespace key old new', permission=b'push') def pushkey(repo, proto, namespace, key, old, new): # compatibility with pre-1.8 clients which were accidentally # sending raw binary nodes rather than utf-8-encoded hex @@ -594,11 +594,11 @@ or False ) - output = output.getvalue() if output else '' - return wireprototypes.bytesresponse('%d\n%s' % (int(r), output)) + output = output.getvalue() if output else b'' + return wireprototypes.bytesresponse(b'%d\n%s' % (int(r), output)) -@wireprotocommand('stream_out', permission='pull') +@wireprotocommand(b'stream_out', permission=b'pull') def stream(repo, proto): '''If the server supports streaming clone, it advertises the "stream" capability with a value representing the version and flags of the repo @@ -607,17 +607,17 @@ return wireprototypes.streamreslegacy(streamclone.generatev1wireproto(repo)) -@wireprotocommand('unbundle', 'heads', permission='push') +@wireprotocommand(b'unbundle', b'heads', permission=b'push') def unbundle(repo, proto, heads): their_heads = wireprototypes.decodelist(heads) with proto.mayberedirectstdio() as output: try: - exchange.check_heads(repo, their_heads, 'preparing changes') + exchange.check_heads(repo, their_heads, b'preparing changes') cleanup = lambda: None try: payload = proto.getpayload() - if repo.ui.configbool('server', 'streamunbundle'): + if repo.ui.configbool(b'server', b'streamunbundle'): def cleanup(): # Ensure that the full payload is consumed, so @@ -636,11 +636,11 @@ if tempname: os.unlink(tempname) - fd, tempname = pycompat.mkstemp(prefix='hg-unbundle-') + fd, tempname = pycompat.mkstemp(prefix=b'hg-unbundle-') repo.ui.debug( - 'redirecting incoming bundle to %s\n' % tempname + b'redirecting incoming bundle to %s\n' % tempname ) - fp = os.fdopen(fd, pycompat.sysstr('wb+')) + fp = os.fdopen(fd, pycompat.sysstr(b'wb+')) for p in payload: fp.write(p) fp.seek(0) @@ -648,8 +648,8 @@ gen = exchange.readbundle(repo.ui, fp, None) if isinstance( gen, changegroupmod.cg1unpacker - ) and not bundle1allowed(repo, 'push'): - if proto.name == 'http-v1': + ) and not bundle1allowed(repo, b'push'): + if proto.name == b'http-v1': # need to special case http because stderr do not get to # the http client on failed push so we need to abuse # some other error type to make sure the message get to @@ -660,14 +660,14 @@ ) r = exchange.unbundle( - repo, gen, their_heads, 'serve', proto.client() + repo, gen, their_heads, b'serve', proto.client() ) - if util.safehasattr(r, 'addpart'): + if util.safehasattr(r, b'addpart'): # The return looks streamable, we are in the bundle2 case # and should return a stream. return wireprototypes.streamreslegacy(gen=r.getchunks()) return wireprototypes.pushres( - r, output.getvalue() if output else '' + r, output.getvalue() if output else b'' ) finally: @@ -683,17 +683,17 @@ # We did not change it to minimise code change. # This need to be moved to something proper. # Feel free to do it. - procutil.stderr.write("abort: %s\n" % exc) + procutil.stderr.write(b"abort: %s\n" % exc) if exc.hint is not None: - procutil.stderr.write("(%s)\n" % exc.hint) + procutil.stderr.write(b"(%s)\n" % exc.hint) procutil.stderr.flush() return wireprototypes.pushres( - 0, output.getvalue() if output else '' + 0, output.getvalue() if output else b'' ) except error.PushRaced: return wireprototypes.pusherr( pycompat.bytestr(exc), - output.getvalue() if output else '', + output.getvalue() if output else b'', ) bundler = bundle2.bundle20(repo.ui) @@ -707,41 +707,41 @@ remotecaps = getattr(exc, '_replycaps', None) if ( remotecaps is not None - and 'pushkey' not in remotecaps.get('error', ()) + and b'pushkey' not in remotecaps.get(b'error', ()) ): # no support remote side, fallback to Abort handler. raise - part = bundler.newpart('error:pushkey') - part.addparam('in-reply-to', exc.partid) + part = bundler.newpart(b'error:pushkey') + part.addparam(b'in-reply-to', exc.partid) if exc.namespace is not None: part.addparam( - 'namespace', exc.namespace, mandatory=False + b'namespace', exc.namespace, mandatory=False ) if exc.key is not None: - part.addparam('key', exc.key, mandatory=False) + part.addparam(b'key', exc.key, mandatory=False) if exc.new is not None: - part.addparam('new', exc.new, mandatory=False) + part.addparam(b'new', exc.new, mandatory=False) if exc.old is not None: - part.addparam('old', exc.old, mandatory=False) + part.addparam(b'old', exc.old, mandatory=False) if exc.ret is not None: - part.addparam('ret', exc.ret, mandatory=False) + part.addparam(b'ret', exc.ret, mandatory=False) except error.BundleValueError as exc: - errpart = bundler.newpart('error:unsupportedcontent') + errpart = bundler.newpart(b'error:unsupportedcontent') if exc.parttype is not None: - errpart.addparam('parttype', exc.parttype) + errpart.addparam(b'parttype', exc.parttype) if exc.params: - errpart.addparam('params', '\0'.join(exc.params)) + errpart.addparam(b'params', b'\0'.join(exc.params)) except error.Abort as exc: - manargs = [('message', stringutil.forcebytestr(exc))] + manargs = [(b'message', stringutil.forcebytestr(exc))] advargs = [] if exc.hint is not None: - advargs.append(('hint', exc.hint)) + advargs.append((b'hint', exc.hint)) bundler.addpart( - bundle2.bundlepart('error:abort', manargs, advargs) + bundle2.bundlepart(b'error:abort', manargs, advargs) ) except error.PushRaced as exc: bundler.newpart( - 'error:pushraced', - [('message', stringutil.forcebytestr(exc))], + b'error:pushraced', + [(b'message', stringutil.forcebytestr(exc))], ) return wireprototypes.streamreslegacy(gen=bundler.getchunks())