mercurial/wireprotoserver.py
changeset 37393 afcfdf53e4b5
parent 37296 78103e4138b1
child 37414 2d965bfeb8f6
--- 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