indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Previously, we constructed an httppeer then always ran _fetchcaps()
  to issue the capabilities command.
  
  We want to issue the capabilities command before constructing a
  peer instance so we can construct an appropriate peer instance
  depending on the capabilities result.
  
  With the code for making and sending requests moved out of httppeer,
  it is now possible to send command requests without an httppeer.
  
  This commit creates a new function for making the capabilities
  request and calls it as part of makepeer().
  
  This code should be functionality equivalent to what existed before.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3237

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/httppeer.py
  tests/test-check-interfaces.py

CHANGE DETAILS

diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py
--- a/tests/test-check-interfaces.py
+++ b/tests/test-check-interfaces.py
@@ -67,10 +67,11 @@
 class dummyopener(object):
     handlers = []
 
-# Facilitates testing sshpeer without requiring an SSH server.
+# Facilitates testing sshpeer without requiring a server.
 class badpeer(httppeer.httppeer):
     def __init__(self):
-        super(badpeer, self).__init__(None, None, None, dummyopener(), None)
+        super(badpeer, self).__init__(None, None, None, dummyopener(), None,
+                                      None)
         self.badattribute = True
 
     def badmethod(self):
@@ -89,7 +90,7 @@
 
     ziverify.verifyClass(repository.ipeerbaselegacycommands,
                          httppeer.httppeer)
-    checkzobject(httppeer.httppeer(None, None, None, dummyopener(), None))
+    checkzobject(httppeer.httppeer(None, None, None, dummyopener(), None, 
None))
 
     ziverify.verifyClass(repository.ipeerbase,
                          localrepo.localpeer)
diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py
--- a/mercurial/httppeer.py
+++ b/mercurial/httppeer.py
@@ -366,11 +366,11 @@
     return respurl, resp
 
 class httppeer(wireproto.wirepeer):
-    def __init__(self, ui, path, url, opener, requestbuilder):
+    def __init__(self, ui, path, url, opener, requestbuilder, caps):
         self.ui = ui
         self._path = path
         self._url = url
-        self._caps = None
+        self._caps = caps
         self._urlopener = opener
         self._requestbuilder = requestbuilder
 
@@ -401,18 +401,12 @@
     # Begin of ipeercommands interface.
 
     def capabilities(self):
-        # self._fetchcaps() should have been called as part of peer
-        # handshake. So self._caps should always be set.
-        assert self._caps is not None
         return self._caps
 
     # End of ipeercommands interface.
 
     # look up capabilities only when needed
 
-    def _fetchcaps(self):
-        self._caps = set(self._call('capabilities').split())
-
     def _callstream(self, cmd, _compressible=False, **args):
         args = pycompat.byteskwargs(args)
 
@@ -603,6 +597,29 @@
 
         return results
 
+def performhandshake(ui, url, opener, requestbuilder):
+    # The handshake is a request to the capabilities command.
+
+    caps = None
+    def capable(x):
+        raise error.ProgrammingError('should not be called')
+
+    req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps,
+                                           capable, url, 'capabilities',
+                                           {})
+
+    resp = sendrequest(ui, opener, req)
+
+    respurl, resp = parsev1commandresponse(ui, url, requrl, qs, resp,
+                                           compressible=False)
+
+    try:
+        rawcaps = resp.read()
+    finally:
+        resp.close()
+
+    return respurl, set(rawcaps.split())
+
 def makepeer(ui, path, requestbuilder=urlreq.request):
     """Construct an appropriate HTTP peer instance.
 
@@ -620,7 +637,9 @@
 
     opener = urlmod.opener(ui, authinfo)
 
-    return httppeer(ui, path, url, opener, requestbuilder)
+    respurl, caps = performhandshake(ui, url, opener, requestbuilder)
+
+    return httppeer(ui, path, respurl, opener, requestbuilder, caps)
 
 def instance(ui, path, create):
     if create:
@@ -631,7 +650,6 @@
                                 'is not installed'))
 
         inst = makepeer(ui, path)
-        inst._fetchcaps()
 
         return inst
     except error.RepoError as httpexception:
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -2915,9 +2915,12 @@
             raise error.Abort(_('--peer %s not supported with HTTP peers') %
                               opts['peer'])
         else:
+            url, caps = httppeer.performhandshake(ui, url, opener,
+                                                  httppeer.urlreq.request)
+
             peer = httppeer.httppeer(ui, path, url, opener,
-                                     requestbuilder=httppeer.urlreq.request)
-            peer._fetchcaps()
+                                     httppeer.urlreq.request,
+                                     caps)
 
         # We /could/ populate stdin/stdout with sock.makefile()...
     else:



To: indygreg, #hg-reviewers
Cc: mercurial-devel
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to