mercurial/sshpeer.py
changeset 35979 a622a927fe03
parent 35978 80a2b8ae42a1
child 35980 556218e08e25
equal deleted inserted replaced
35978:80a2b8ae42a1 35979:a622a927fe03
   160     def badresponse():
   160     def badresponse():
   161         msg = _('no suitable response from remote hg')
   161         msg = _('no suitable response from remote hg')
   162         hint = ui.config('ui', 'ssherrorhint')
   162         hint = ui.config('ui', 'ssherrorhint')
   163         raise error.RepoError(msg, hint=hint)
   163         raise error.RepoError(msg, hint=hint)
   164 
   164 
       
   165     # The handshake consists of sending 2 wire protocol commands:
       
   166     # ``hello`` and ``between``.
       
   167     #
       
   168     # The ``hello`` command (which was introduced in Mercurial 0.9.1)
       
   169     # instructs the server to advertise its capabilities.
       
   170     #
       
   171     # The ``between`` command (which has existed in all Mercurial servers
       
   172     # for as long as SSH support has existed), asks for the set of revisions
       
   173     # between a pair of revisions.
       
   174     #
       
   175     # The ``between`` command is issued with a request for the null
       
   176     # range. If the remote is a Mercurial server, this request will
       
   177     # generate a specific response: ``1\n\n``. This represents the
       
   178     # wire protocol encoded value for ``\n``. We look for ``1\n\n``
       
   179     # in the output stream and know this is the response to ``between``
       
   180     # and we're at the end of our handshake reply.
       
   181     #
       
   182     # The response to the ``hello`` command will be a line with the
       
   183     # length of the value returned by that command followed by that
       
   184     # value. If the server doesn't support ``hello`` (which should be
       
   185     # rare), that line will be ``0\n``. Otherwise, the value will contain
       
   186     # RFC 822 like lines. Of these, the ``capabilities:`` line contains
       
   187     # the capabilities of the server.
       
   188     #
       
   189     # In addition to the responses to our command requests, the server
       
   190     # may emit "banner" output on stdout. SSH servers are allowed to
       
   191     # print messages to stdout on login. Issuing commands on connection
       
   192     # allows us to flush this banner output from the server by scanning
       
   193     # for output to our well-known ``between`` command. Of course, if
       
   194     # the banner contains ``1\n\n``, this will throw off our detection.
       
   195 
   165     requestlog = ui.configbool('devel', 'debug.peer-request')
   196     requestlog = ui.configbool('devel', 'debug.peer-request')
   166 
   197 
   167     try:
   198     try:
   168         pairsarg = '%s-%s' % ('0' * 40, '0' * 40)
   199         pairsarg = '%s-%s' % ('0' * 40, '0' * 40)
   169         handshake = [
   200         handshake = [
   203     else:
   234     else:
   204         badresponse()
   235         badresponse()
   205 
   236 
   206     caps = set()
   237     caps = set()
   207     for l in reversed(lines):
   238     for l in reversed(lines):
       
   239         # Look for response to ``hello`` command. Scan from the back so
       
   240         # we don't misinterpret banner output as the command reply.
   208         if l.startswith('capabilities:'):
   241         if l.startswith('capabilities:'):
   209             caps.update(l[:-1].split(':')[1].split())
   242             caps.update(l[:-1].split(':')[1].split())
   210             break
   243             break
   211 
   244 
   212     return caps
   245     return caps