Mercurial > public > mercurial-scm > hg-stable
diff mercurial/wireprotoserver.py @ 37393:afcfdf53e4b5
wireproto: provide accessors for client capabilities
For HTTP, this refactors the existing logic, including the parsing of
the compression engine capability.
For SSH, this adds a ssh-only capability "protocaps" and a command for
informing the server on what the client supports. Since SSH is stateful,
keep track of the capabilities in the server instance.
Differential Revision: https://phab.mercurial-scm.org/D1944
author | Joerg Sonnenberger <joerg@bec.de> |
---|---|
date | Sat, 24 Mar 2018 17:57:22 +0100 |
parents | 78103e4138b1 |
children | 2d965bfeb8f6 |
line wrap: on
line diff
--- a/mercurial/wireprotoserver.py Thu Apr 05 17:51:10 2018 +0200 +++ b/mercurial/wireprotoserver.py Sat Mar 24 17:57:22 2018 +0100 @@ -67,6 +67,7 @@ self._req = req self._ui = ui self._checkperm = checkperm + self._protocaps = None @property def name(self): @@ -99,6 +100,12 @@ args.update(urlreq.parseqs(argvalue, keep_blank_values=True)) return args + def getprotocaps(self): + if self._protocaps is None: + value = decodevaluefromheaders(self._req, r'X-HgProto') + self._protocaps = set(value.split(' ')) + return self._protocaps + def forwardpayload(self, fp): # Existing clients *always* send Content-Length. length = int(self._req.headers[b'Content-Length']) @@ -599,6 +606,10 @@ return [data[k] for k in args.split()] + def getprotocaps(self): + # Protocol capabilities are currently not implemented for HTTP V2. + return set() + def forwardpayload(self, fp): raise NotImplementedError @@ -615,28 +626,21 @@ def checkperm(self, perm): raise NotImplementedError -def _httpresponsetype(ui, req, prefer_uncompressed): +def _httpresponsetype(ui, proto, prefer_uncompressed): """Determine the appropriate response type and compression settings. Returns a tuple of (mediatype, compengine, engineopts). """ # Determine the response media type and compression engine based # on the request parameters. - protocaps = decodevaluefromheaders(req, 'X-HgProto').split(' ') - if '0.2' in protocaps: + if '0.2' in proto.getprotocaps(): # All clients are expected to support uncompressed data. if prefer_uncompressed: return HGTYPE2, util._noopengine(), {} - # Default as defined by wire protocol spec. - compformats = ['zlib', 'none'] - for cap in protocaps: - if cap.startswith('comp='): - compformats = cap[5:].split(',') - break - # Now find an agreed upon compression format. + compformats = wireproto.clientcompressionsupport(proto) for engine in wireproto.supportedcompengines(ui, util.SERVERROLE): if engine.wireprotosupport().name in compformats: opts = {} @@ -705,7 +709,7 @@ # This code for compression should not be streamres specific. It # is here because we only compress streamres at the moment. mediatype, engine, engineopts = _httpresponsetype( - repo.ui, req, rsp.prefer_uncompressed) + repo.ui, proto, rsp.prefer_uncompressed) gen = engine.compressstream(gen, engineopts) if mediatype == HGTYPE2: @@ -749,6 +753,7 @@ self._ui = ui self._fin = fin self._fout = fout + self._protocaps = set() @property def name(self): @@ -775,6 +780,9 @@ data[arg] = val return [data[k] for k in keys] + def getprotocaps(self): + return self._protocaps + def forwardpayload(self, fpout): # We initially send an empty response. This tells the client it is # OK to start sending data. If a client sees any other response, it @@ -800,6 +808,8 @@ return 'remote:ssh:' + client def addcapabilities(self, repo, caps): + if self.name == wireprototypes.SSHV1: + caps.append(b'protocaps') caps.append(b'batch') return caps