mercurial/wireprotov2server.py
changeset 43076 2372284d9457
parent 42824 2c4f656c8e9f
child 43077 687b865b95ad
--- a/mercurial/wireprotov2server.py	Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/wireprotov2server.py	Sun Oct 06 09:45:02 2019 -0400
@@ -28,9 +28,7 @@
     wireprotoframing,
     wireprototypes,
 )
-from .interfaces import (
-    util as interfaceutil,
-)
+from .interfaces import util as interfaceutil
 from .utils import (
     cborutil,
     stringutil,
@@ -47,6 +45,7 @@
 # there is a change to how caching works, etc.
 GLOBAL_CACHE_VERSION = 1
 
+
 def handlehttpv2request(rctx, req, res, checkperm, urlparts):
     from .hgweb import common as hgwebcommon
 
@@ -63,8 +62,9 @@
     if len(urlparts) == 1:
         res.status = b'404 Not Found'
         res.headers[b'Content-Type'] = b'text/plain'
-        res.setbodybytes(_('do not know how to process %s\n') %
-                         req.dispatchpath)
+        res.setbodybytes(
+            _('do not know how to process %s\n') % req.dispatchpath
+        )
         return
 
     permission, command = urlparts[0:2]
@@ -115,8 +115,10 @@
 
     proto = httpv2protocolhandler(req, ui)
 
-    if (not COMMANDS.commandavailable(command, proto)
-        and command not in extracommands):
+    if (
+        not COMMANDS.commandavailable(command, proto)
+        and command not in extracommands
+    ):
         res.status = b'404 Not Found'
         res.headers[b'Content-Type'] = b'text/plain'
         res.setbodybytes(_('invalid wire protocol command: %s') % command)
@@ -126,8 +128,10 @@
     if req.headers.get(b'Accept') != FRAMINGTYPE:
         res.status = b'406 Not Acceptable'
         res.headers[b'Content-Type'] = b'text/plain'
-        res.setbodybytes(_('client MUST specify Accept header with value: %s\n')
-                           % FRAMINGTYPE)
+        res.setbodybytes(
+            _('client MUST specify Accept header with value: %s\n')
+            % FRAMINGTYPE
+        )
         return
 
     if req.headers.get(b'Content-Type') != FRAMINGTYPE:
@@ -135,12 +139,15 @@
         # TODO we should send a response with appropriate media type,
         # since client does Accept it.
         res.headers[b'Content-Type'] = b'text/plain'
-        res.setbodybytes(_('client MUST send Content-Type header with '
-                           'value: %s\n') % FRAMINGTYPE)
+        res.setbodybytes(
+            _('client MUST send Content-Type header with ' 'value: %s\n')
+            % FRAMINGTYPE
+        )
         return
 
     _processhttpv2request(ui, repo, req, res, permission, command, proto)
 
+
 def _processhttpv2reflectrequest(ui, repo, req, res):
     """Reads unified frame protocol request and dumps out state to client.
 
@@ -171,9 +178,10 @@
             states.append(b'received: <no frame>')
             break
 
-        states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags,
-                                                  frame.requestid,
-                                                  frame.payload))
+        states.append(
+            b'received: %d %d %d %s'
+            % (frame.typeid, frame.flags, frame.requestid, frame.payload)
+        )
 
         action, meta = reactor.onframerecv(frame)
         states.append(templatefilters.json((action, meta)))
@@ -186,6 +194,7 @@
     res.headers[b'Content-Type'] = b'text/plain'
     res.setbodybytes(b'\n'.join(states))
 
+
 def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto):
     """Post-validation handler for HTTPv2 requests.
 
@@ -216,9 +225,18 @@
             if not outstream:
                 outstream = reactor.makeoutputstream()
 
-            sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
-                                           reqcommand, reactor, outstream,
-                                           meta, issubsequent=seencommand)
+            sentoutput = _httpv2runcommand(
+                ui,
+                repo,
+                req,
+                res,
+                authedperm,
+                reqcommand,
+                reactor,
+                outstream,
+                meta,
+                issubsequent=seencommand,
+            )
 
             if sentoutput:
                 return
@@ -233,7 +251,8 @@
             return
         else:
             raise error.ProgrammingError(
-                'unhandled action from frame processor: %s' % action)
+                'unhandled action from frame processor: %s' % action
+            )
 
     action, meta = reactor.oninputeof()
     if action == 'sendframes':
@@ -245,11 +264,23 @@
     elif action == 'noop':
         pass
     else:
-        raise error.ProgrammingError('unhandled action from frame processor: %s'
-                                     % action)
+        raise error.ProgrammingError(
+            'unhandled action from frame processor: %s' % action
+        )
+
 
-def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
-                      outstream, command, issubsequent):
+def _httpv2runcommand(
+    ui,
+    repo,
+    req,
+    res,
+    authedperm,
+    reqcommand,
+    reactor,
+    outstream,
+    command,
+    issubsequent,
+):
     """Dispatch a wire protocol command made from HTTPv2 requests.
 
     The authenticated permission (``authedperm``) along with the original
@@ -277,8 +308,10 @@
             # TODO proper error mechanism
             res.status = b'200 OK'
             res.headers[b'Content-Type'] = b'text/plain'
-            res.setbodybytes(_('wire protocol command not available: %s') %
-                             command['command'])
+            res.setbodybytes(
+                _('wire protocol command not available: %s')
+                % command['command']
+            )
             return True
 
         # TODO don't use assert here, since it may be elided by -O.
@@ -290,8 +323,10 @@
             # TODO proper error mechanism
             res.status = b'403 Forbidden'
             res.headers[b'Content-Type'] = b'text/plain'
-            res.setbodybytes(_('insufficient permissions to execute '
-                               'command: %s') % command['command'])
+            res.setbodybytes(
+                _('insufficient permissions to execute ' 'command: %s')
+                % command['command']
+            )
             return True
 
         # TODO should we also call checkperm() here? Maybe not if we're going
@@ -304,8 +339,9 @@
             # TODO proper error mechanism
             res.status = b'200 OK'
             res.headers[b'Content-Type'] = b'text/plain'
-            res.setbodybytes(_('multiple commands cannot be issued to this '
-                               'URL'))
+            res.setbodybytes(
+                _('multiple commands cannot be issued to this ' 'URL')
+            )
             return True
 
         if reqcommand != command['command']:
@@ -322,17 +358,21 @@
         objs = dispatch(repo, proto, command['command'], command['redirect'])
 
         action, meta = reactor.oncommandresponsereadyobjects(
-            outstream, command['requestid'], objs)
+            outstream, command['requestid'], objs
+        )
 
     except error.WireprotoCommandError as e:
         action, meta = reactor.oncommanderror(
-            outstream, command['requestid'], e.message, e.messageargs)
+            outstream, command['requestid'], e.message, e.messageargs
+        )
 
     except Exception as e:
         action, meta = reactor.onservererror(
-            outstream, command['requestid'],
-            _('exception when invoking command: %s') %
-            stringutil.forcebytestr(e))
+            outstream,
+            command['requestid'],
+            _('exception when invoking command: %s')
+            % stringutil.forcebytestr(e),
+        )
 
     if action == 'sendframes':
         res.setbodygen(meta['framegen'])
@@ -340,13 +380,16 @@
     elif action == 'noop':
         return False
     else:
-        raise error.ProgrammingError('unhandled event from reactor: %s' %
-                                     action)
+        raise error.ProgrammingError(
+            'unhandled event from reactor: %s' % action
+        )
+
 
 def getdispatchrepo(repo, proto, command):
     viewconfig = repo.ui.config('server', 'view')
     return repo.filtered(viewconfig)
 
+
 def dispatch(repo, proto, command, redirect):
     """Run a wire protocol command.
 
@@ -379,10 +422,15 @@
         redirecttargets = []
         redirecthashes = []
 
-    cacher = makeresponsecacher(repo, proto, command, args,
-                                cborutil.streamencode,
-                                redirecttargets=redirecttargets,
-                                redirecthashes=redirecthashes)
+    cacher = makeresponsecacher(
+        repo,
+        proto,
+        command,
+        args,
+        cborutil.streamencode,
+        redirecttargets=redirecttargets,
+        redirecthashes=redirecthashes,
+    )
 
     # But we have no cacher. Do default handling.
     if not cacher:
@@ -391,8 +439,9 @@
         return
 
     with cacher:
-        cachekey = entry.cachekeyfn(repo, proto, cacher,
-                                    **pycompat.strkwargs(args))
+        cachekey = entry.cachekeyfn(
+            repo, proto, cacher, **pycompat.strkwargs(args)
+        )
 
         # No cache key or the cacher doesn't like it. Do default handling.
         if cachekey is None or not cacher.setcachekey(cachekey):
@@ -417,6 +466,7 @@
         for o in cacher.onfinished():
             yield o
 
+
 @interfaceutil.implementer(wireprototypes.baseprotocolhandler)
 class httpv2protocolhandler(object):
     def __init__(self, req, ui, args=None):
@@ -434,15 +484,16 @@
         extra = set(self._args) - set(args)
         if extra:
             raise error.WireprotoCommandError(
-                'unsupported argument to command: %s' %
-                ', '.join(sorted(extra)))
+                'unsupported argument to command: %s' % ', '.join(sorted(extra))
+            )
 
         # And look for required arguments that are missing.
         missing = {a for a in args if args[a]['required']} - set(self._args)
 
         if missing:
             raise error.WireprotoCommandError(
-                'missing required arguments: %s' % ', '.join(sorted(missing)))
+                'missing required arguments: %s' % ', '.join(sorted(missing))
+            )
 
         # Now derive the arguments to pass to the command, taking into
         # account the arguments specified by the client.
@@ -485,11 +536,13 @@
     def checkperm(self, perm):
         raise NotImplementedError
 
+
 def httpv2apidescriptor(req, repo):
     proto = httpv2protocolhandler(req, repo.ui)
 
     return _capabilitiesv2(repo, proto)
 
+
 def _capabilitiesv2(repo, proto):
     """Obtain the set of capabilities for version 2 transports.
 
@@ -520,8 +573,10 @@
                 args[arg][b'validvalues'] = meta['validvalues']
 
         # TODO this type of check should be defined in a per-command callback.
-        if (command == b'rawstorefiledata'
-            and not streamclone.allowservergeneration(repo)):
+        if (
+            command == b'rawstorefiledata'
+            and not streamclone.allowservergeneration(repo)
+        ):
             continue
 
         caps['commands'][command] = {
@@ -533,8 +588,7 @@
             extracaps = entry.extracapabilitiesfn(repo, proto)
             caps['commands'][command].update(extracaps)
 
-    caps['rawrepoformats'] = sorted(repo.requirements &
-                                    repo.supportedformats)
+    caps['rawrepoformats'] = sorted(repo.requirements & repo.supportedformats)
 
     targets = getadvertisedredirecttargets(repo, proto)
     if targets:
@@ -558,6 +612,7 @@
 
     return proto.addcapabilities(repo, caps)
 
+
 def getadvertisedredirecttargets(repo, proto):
     """Obtain a list of content redirect targets.
 
@@ -596,8 +651,14 @@
     """
     return []
 
-def wireprotocommand(name, args=None, permission='push', cachekeyfn=None,
-                     extracapabilitiesfn=None):
+
+def wireprotocommand(
+    name,
+    args=None,
+    permission='push',
+    cachekeyfn=None,
+    extracapabilitiesfn=None,
+):
     """Decorator to declare a wire protocol command.
 
     ``name`` is the name of the wire protocol command being provided.
@@ -648,42 +709,53 @@
     containing the key in a cache the response to this command may be cached
     under.
     """
-    transports = {k for k, v in wireprototypes.TRANSPORTS.items()
-                  if v['version'] == 2}
+    transports = {
+        k for k, v in wireprototypes.TRANSPORTS.items() if v['version'] == 2
+    }
 
     if permission not in ('push', 'pull'):
-        raise error.ProgrammingError('invalid wire protocol permission; '
-                                     'got %s; expected "push" or "pull"' %
-                                     permission)
+        raise error.ProgrammingError(
+            'invalid wire protocol permission; '
+            'got %s; expected "push" or "pull"' % permission
+        )
 
     if args is None:
         args = {}
 
     if not isinstance(args, dict):
-        raise error.ProgrammingError('arguments for version 2 commands '
-                                     'must be declared as dicts')
+        raise error.ProgrammingError(
+            'arguments for version 2 commands ' 'must be declared as dicts'
+        )
 
     for arg, meta in args.items():
         if arg == '*':
-            raise error.ProgrammingError('* argument name not allowed on '
-                                         'version 2 commands')
+            raise error.ProgrammingError(
+                '* argument name not allowed on ' 'version 2 commands'
+            )
 
         if not isinstance(meta, dict):
-            raise error.ProgrammingError('arguments for version 2 commands '
-                                         'must declare metadata as a dict')
+            raise error.ProgrammingError(
+                'arguments for version 2 commands '
+                'must declare metadata as a dict'
+            )
 
         if 'type' not in meta:
-            raise error.ProgrammingError('%s argument for command %s does not '
-                                         'declare type field' % (arg, name))
+            raise error.ProgrammingError(
+                '%s argument for command %s does not '
+                'declare type field' % (arg, name)
+            )
 
         if meta['type'] not in ('bytes', 'int', 'list', 'dict', 'set', 'bool'):
-            raise error.ProgrammingError('%s argument for command %s has '
-                                         'illegal type: %s' % (arg, name,
-                                                               meta['type']))
+            raise error.ProgrammingError(
+                '%s argument for command %s has '
+                'illegal type: %s' % (arg, name, meta['type'])
+            )
 
         if 'example' not in meta:
-            raise error.ProgrammingError('%s argument for command %s does not '
-                                         'declare example field' % (arg, name))
+            raise error.ProgrammingError(
+                '%s argument for command %s does not '
+                'declare example field' % (arg, name)
+            )
 
         meta['required'] = 'default' not in meta
 
@@ -692,17 +764,24 @@
 
     def register(func):
         if name in COMMANDS:
-            raise error.ProgrammingError('%s command already registered '
-                                         'for version 2' % name)
+            raise error.ProgrammingError(
+                '%s command already registered ' 'for version 2' % name
+            )
 
         COMMANDS[name] = wireprototypes.commandentry(
-            func, args=args, transports=transports, permission=permission,
-            cachekeyfn=cachekeyfn, extracapabilitiesfn=extracapabilitiesfn)
+            func,
+            args=args,
+            transports=transports,
+            permission=permission,
+            cachekeyfn=cachekeyfn,
+            extracapabilitiesfn=extracapabilitiesfn,
+        )
 
         return func
 
     return register
 
+
 def makecommandcachekeyfn(command, localversion=None, allargs=False):
     """Construct a cache key derivation function with common features.
 
@@ -777,8 +856,10 @@
 
     return cachekeyfn
 
-def makeresponsecacher(repo, proto, command, args, objencoderfn,
-                       redirecttargets, redirecthashes):
+
+def makeresponsecacher(
+    repo, proto, command, args, objencoderfn, redirecttargets, redirecthashes
+):
     """Construct a cacher for a cacheable command.
 
     Returns an ``iwireprotocolcommandcacher`` instance.
@@ -788,6 +869,7 @@
     """
     return None
 
+
 def resolvenodes(repo, revisions):
     """Resolve nodes from a revisions specifier data structure."""
     cl = repo.changelog
@@ -797,13 +879,15 @@
     nodes = []
 
     if not isinstance(revisions, list):
-        raise error.WireprotoCommandError('revisions must be defined as an '
-                                          'array')
+        raise error.WireprotoCommandError(
+            'revisions must be defined as an ' 'array'
+        )
 
     for spec in revisions:
         if b'type' not in spec:
             raise error.WireprotoCommandError(
-                'type key not present in revision specifier')
+                'type key not present in revision specifier'
+            )
 
         typ = spec[b'type']
 
@@ -811,7 +895,8 @@
             if b'nodes' not in spec:
                 raise error.WireprotoCommandError(
                     'nodes key not present in changesetexplicit revision '
-                    'specifier')
+                    'specifier'
+                )
 
             for node in spec[b'nodes']:
                 if node not in seen:
@@ -823,10 +908,13 @@
                 if key not in spec:
                     raise error.WireprotoCommandError(
                         '%s key not present in changesetexplicitdepth revision '
-                        'specifier', (key,))
+                        'specifier',
+                        (key,),
+                    )
 
-            for rev in repo.revs(b'ancestors(%ln, %s)', spec[b'nodes'],
-                                 spec[b'depth'] - 1):
+            for rev in repo.revs(
+                b'ancestors(%ln, %s)', spec[b'nodes'], spec[b'depth'] - 1
+            ):
                 node = cl.node(rev)
 
                 if node not in seen:
@@ -838,11 +926,14 @@
                 if key not in spec:
                     raise error.WireprotoCommandError(
                         '%s key not present in changesetdagrange revision '
-                        'specifier', (key,))
+                        'specifier',
+                        (key,),
+                    )
 
             if not spec[b'heads']:
                 raise error.WireprotoCommandError(
-                    'heads key in changesetdagrange cannot be empty')
+                    'heads key in changesetdagrange cannot be empty'
+                )
 
             if spec[b'roots']:
                 common = [n for n in spec[b'roots'] if clhasnode(n)]
@@ -856,28 +947,30 @@
 
         else:
             raise error.WireprotoCommandError(
-                'unknown revision specifier type: %s', (typ,))
+                'unknown revision specifier type: %s', (typ,)
+            )
 
     return nodes
 
+
 @wireprotocommand('branchmap', permission='pull')
 def branchmapv2(repo, proto):
-    yield {encoding.fromlocal(k): v
-           for k, v in repo.branchmap().iteritems()}
+    yield {encoding.fromlocal(k): v for k, v in repo.branchmap().iteritems()}
+
 
 @wireprotocommand('capabilities', permission='pull')
 def capabilitiesv2(repo, proto):
     yield _capabilitiesv2(repo, proto)
 
+
 @wireprotocommand(
     'changesetdata',
     args={
         'revisions': {
             'type': 'list',
-            'example': [{
-                b'type': b'changesetexplicit',
-                b'nodes': [b'abcdef...'],
-            }],
+            'example': [
+                {b'type': b'changesetexplicit', b'nodes': [b'abcdef...'],}
+            ],
         },
         'fields': {
             'type': 'set',
@@ -886,7 +979,8 @@
             'validvalues': {b'bookmarks', b'parents', b'phase', b'revision'},
         },
     },
-    permission='pull')
+    permission='pull',
+)
 def changesetdata(repo, proto, revisions, fields):
     # TODO look for unknown fields and abort when they can't be serviced.
     # This could probably be validated by dispatcher using validvalues.
@@ -963,6 +1057,7 @@
                 b'bookmarks': sorted(marks),
             }
 
+
 class FileAccessError(Exception):
     """Represents an error accessing a specific file."""
 
@@ -971,6 +1066,7 @@
         self.msg = msg
         self.args = args
 
+
 def getfilestore(repo, proto, path):
     """Obtain a file storage object for use with wire protocol.
 
@@ -986,6 +1082,7 @@
 
     return fl
 
+
 def emitfilerevisions(repo, path, revisions, linknodes, fields):
     for revision in revisions:
         d = {
@@ -1018,6 +1115,7 @@
         for extra in followingdata:
             yield extra
 
+
 def makefilematcher(repo, pathfilter):
     """Construct a matcher from a path filter dict."""
 
@@ -1028,12 +1126,17 @@
                 if not pattern.startswith((b'path:', b'rootfilesin:')):
                     raise error.WireprotoCommandError(
                         '%s pattern must begin with `path:` or `rootfilesin:`; '
-                        'got %s', (key, pattern))
+                        'got %s',
+                        (key, pattern),
+                    )
 
     if pathfilter:
-        matcher = matchmod.match(repo.root, b'',
-                                 include=pathfilter.get(b'include', []),
-                                 exclude=pathfilter.get(b'exclude', []))
+        matcher = matchmod.match(
+            repo.root,
+            b'',
+            include=pathfilter.get(b'include', []),
+            exclude=pathfilter.get(b'exclude', []),
+        )
     else:
         matcher = matchmod.match(repo.root, b'')
 
@@ -1041,6 +1144,7 @@
     # filter those out.
     return repo.narrowmatch(matcher)
 
+
 @wireprotocommand(
     'filedata',
     args={
@@ -1049,26 +1153,21 @@
             'default': lambda: False,
             'example': True,
         },
-        'nodes': {
-            'type': 'list',
-            'example': [b'0123456...'],
-        },
+        'nodes': {'type': 'list', 'example': [b'0123456...'],},
         'fields': {
             'type': 'set',
             'default': set,
             'example': {b'parents', b'revision'},
             'validvalues': {b'parents', b'revision', b'linknode'},
         },
-        'path': {
-            'type': 'bytes',
-            'example': b'foo.txt',
-        }
+        'path': {'type': 'bytes', 'example': b'foo.txt',},
     },
     permission='pull',
     # TODO censoring a file revision won't invalidate the cache.
     # Figure out a way to take censoring into account when deriving
     # the cache key.
-    cachekeyfn=makecommandcachekeyfn('filedata', 1, allargs=True))
+    cachekeyfn=makecommandcachekeyfn('filedata', 1, allargs=True),
+)
 def filedata(repo, proto, haveparents, nodes, fields, path):
     # TODO this API allows access to file revisions that are attached to
     # secret changesets. filesdata does not have this problem. Maybe this
@@ -1088,8 +1187,9 @@
         try:
             store.rev(node)
         except error.LookupError:
-            raise error.WireprotoCommandError('unknown file node: %s',
-                                              (hex(node),))
+            raise error.WireprotoCommandError(
+                'unknown file node: %s', (hex(node),)
+            )
 
         # TODO by creating the filectx against a specific file revision
         # instead of changeset, linkrev() is always used. This is wrong for
@@ -1099,9 +1199,11 @@
         fctx = repo.filectx(path, fileid=node)
         linknodes[node] = clnode(fctx.introrev())
 
-    revisions = store.emitrevisions(nodes,
-                                    revisiondata=b'revision' in fields,
-                                    assumehaveparentrevisions=haveparents)
+    revisions = store.emitrevisions(
+        nodes,
+        revisiondata=b'revision' in fields,
+        assumehaveparentrevisions=haveparents,
+    )
 
     yield {
         b'totalitems': len(nodes),
@@ -1110,13 +1212,16 @@
     for o in emitfilerevisions(repo, path, revisions, linknodes, fields):
         yield o
 
+
 def filesdatacapabilities(repo, proto):
     batchsize = repo.ui.configint(
-        b'experimental', b'server.filesdata.recommended-batch-size')
+        b'experimental', b'server.filesdata.recommended-batch-size'
+    )
     return {
         b'recommendedbatchsize': batchsize,
     }
 
+
 @wireprotocommand(
     'filesdata',
     args={
@@ -1129,8 +1234,12 @@
             'type': 'set',
             'default': set,
             'example': {b'parents', b'revision'},
-            'validvalues': {b'firstchangeset', b'linknode', b'parents',
-                            b'revision'},
+            'validvalues': {
+                b'firstchangeset',
+                b'linknode',
+                b'parents',
+                b'revision',
+            },
         },
         'pathfilter': {
             'type': 'dict',
@@ -1139,10 +1248,9 @@
         },
         'revisions': {
             'type': 'list',
-            'example': [{
-                b'type': b'changesetexplicit',
-                b'nodes': [b'abcdef...'],
-            }],
+            'example': [
+                {b'type': b'changesetexplicit', b'nodes': [b'abcdef...'],}
+            ],
         },
     },
     permission='pull',
@@ -1150,7 +1258,8 @@
     # Figure out a way to take censoring into account when deriving
     # the cache key.
     cachekeyfn=makecommandcachekeyfn('filesdata', 1, allargs=True),
-    extracapabilitiesfn=filesdatacapabilities)
+    extracapabilitiesfn=filesdatacapabilities,
+)
 def filesdata(repo, proto, haveparents, fields, pathfilter, revisions):
     # TODO This should operate on a repo that exposes obsolete changesets. There
     # is a race between a client making a push that obsoletes a changeset and
@@ -1193,7 +1302,7 @@
 
     yield {
         b'totalpaths': len(fnodes),
-        b'totalitems': sum(len(v) for v in fnodes.values())
+        b'totalitems': sum(len(v) for v in fnodes.values()),
     }
 
     for path, filenodes in sorted(fnodes.items()):
@@ -1207,13 +1316,16 @@
             b'totalitems': len(filenodes),
         }
 
-        revisions = store.emitrevisions(filenodes.keys(),
-                                        revisiondata=b'revision' in fields,
-                                        assumehaveparentrevisions=haveparents)
+        revisions = store.emitrevisions(
+            filenodes.keys(),
+            revisiondata=b'revision' in fields,
+            assumehaveparentrevisions=haveparents,
+        )
 
         for o in emitfilerevisions(repo, path, revisions, filenodes, fields):
             yield o
 
+
 @wireprotocommand(
     'heads',
     args={
@@ -1223,52 +1335,47 @@
             'example': False,
         },
     },
-    permission='pull')
+    permission='pull',
+)
 def headsv2(repo, proto, publiconly):
     if publiconly:
         repo = repo.filtered('immutable')
 
     yield repo.heads()
 
+
 @wireprotocommand(
     'known',
     args={
-        'nodes': {
-            'type': 'list',
-            'default': list,
-            'example': [b'deadbeef'],
-        },
+        'nodes': {'type': 'list', 'default': list, 'example': [b'deadbeef'],},
     },
-    permission='pull')
+    permission='pull',
+)
 def knownv2(repo, proto, nodes):
     result = b''.join(b'1' if n else b'0' for n in repo.known(nodes))
     yield result
 
+
 @wireprotocommand(
     'listkeys',
-    args={
-        'namespace': {
-            'type': 'bytes',
-            'example': b'ns',
-        },
-    },
-    permission='pull')
+    args={'namespace': {'type': 'bytes', 'example': b'ns',},},
+    permission='pull',
+)
 def listkeysv2(repo, proto, namespace):
     keys = repo.listkeys(encoding.tolocal(namespace))
-    keys = {encoding.fromlocal(k): encoding.fromlocal(v)
-            for k, v in keys.iteritems()}
+    keys = {
+        encoding.fromlocal(k): encoding.fromlocal(v)
+        for k, v in keys.iteritems()
+    }
 
     yield keys
 
+
 @wireprotocommand(
     'lookup',
-    args={
-        'key': {
-            'type': 'bytes',
-            'example': b'foo',
-        },
-    },
-    permission='pull')
+    args={'key': {'type': 'bytes', 'example': b'foo',},},
+    permission='pull',
+)
 def lookupv2(repo, proto, key):
     key = encoding.tolocal(key)
 
@@ -1277,21 +1384,21 @@
 
     yield node
 
+
 def manifestdatacapabilities(repo, proto):
     batchsize = repo.ui.configint(
-        b'experimental', b'server.manifestdata.recommended-batch-size')
+        b'experimental', b'server.manifestdata.recommended-batch-size'
+    )
 
     return {
         b'recommendedbatchsize': batchsize,
     }
 
+
 @wireprotocommand(
     'manifestdata',
     args={
-        'nodes': {
-            'type': 'list',
-            'example': [b'0123456...'],
-        },
+        'nodes': {'type': 'list', 'example': [b'0123456...'],},
         'haveparents': {
             'type': 'bool',
             'default': lambda: False,
@@ -1303,14 +1410,12 @@
             'example': {b'parents', b'revision'},
             'validvalues': {b'parents', b'revision'},
         },
-        'tree': {
-            'type': 'bytes',
-            'example': b'',
-        },
+        'tree': {'type': 'bytes', 'example': b'',},
     },
     permission='pull',
     cachekeyfn=makecommandcachekeyfn('manifestdata', 1, allargs=True),
-    extracapabilitiesfn=manifestdatacapabilities)
+    extracapabilitiesfn=manifestdatacapabilities,
+)
 def manifestdata(repo, proto, haveparents, nodes, fields, tree):
     store = repo.manifestlog.getstorage(tree)
 
@@ -1319,12 +1424,13 @@
         try:
             store.rev(node)
         except error.LookupError:
-            raise error.WireprotoCommandError(
-                'unknown node: %s', (node,))
+            raise error.WireprotoCommandError('unknown node: %s', (node,))
 
-    revisions = store.emitrevisions(nodes,
-                                    revisiondata=b'revision' in fields,
-                                    assumehaveparentrevisions=haveparents)
+    revisions = store.emitrevisions(
+        nodes,
+        revisiondata=b'revision' in fields,
+        assumehaveparentrevisions=haveparents,
+    )
 
     yield {
         b'totalitems': len(nodes),
@@ -1358,49 +1464,39 @@
         for extra in followingdata:
             yield extra
 
+
 @wireprotocommand(
     'pushkey',
     args={
-        'namespace': {
-            'type': 'bytes',
-            'example': b'ns',
-        },
-        'key': {
-            'type': 'bytes',
-            'example': b'key',
-        },
-        'old': {
-            'type': 'bytes',
-            'example': b'old',
-        },
-        'new': {
-            'type': 'bytes',
-            'example': 'new',
-        },
+        'namespace': {'type': 'bytes', 'example': b'ns',},
+        'key': {'type': 'bytes', 'example': b'key',},
+        'old': {'type': 'bytes', 'example': b'old',},
+        'new': {'type': 'bytes', 'example': 'new',},
     },
-    permission='push')
+    permission='push',
+)
 def pushkeyv2(repo, proto, namespace, key, old, new):
     # TODO handle ui output redirection
-    yield repo.pushkey(encoding.tolocal(namespace),
-                       encoding.tolocal(key),
-                       encoding.tolocal(old),
-                       encoding.tolocal(new))
+    yield repo.pushkey(
+        encoding.tolocal(namespace),
+        encoding.tolocal(key),
+        encoding.tolocal(old),
+        encoding.tolocal(new),
+    )
 
 
 @wireprotocommand(
     'rawstorefiledata',
     args={
-        'files': {
-            'type': 'list',
-            'example': [b'changelog', b'manifestlog'],
-        },
+        'files': {'type': 'list', 'example': [b'changelog', b'manifestlog'],},
         'pathfilter': {
             'type': 'list',
             'default': lambda: None,
             'example': {b'include': [b'path:tests']},
         },
     },
-    permission='pull')
+    permission='pull',
+)
 def rawstorefiledata(repo, proto, files, pathfilter):
     if not streamclone.allowservergeneration(repo):
         raise error.WireprotoCommandError(b'stream clone is disabled')
@@ -1412,8 +1508,9 @@
 
     unsupported = files - allowedfiles
     if unsupported:
-        raise error.WireprotoCommandError(b'unknown file type: %s',
-                                          (b', '.join(sorted(unsupported)),))
+        raise error.WireprotoCommandError(
+            b'unknown file type: %s', (b', '.join(sorted(unsupported)),)
+        )
 
     with repo.lock():
         topfiles = list(repo.store.topfiles())
@@ -1453,5 +1550,4 @@
                 for chunk in util.filechunkiter(fh, limit=size):
                     yield chunk
 
-        yield wireprototypes.indefinitebytestringresponse(
-            getfiledata())
+        yield wireprototypes.indefinitebytestringresponse(getfiledata())