mercurial/httppeer.py
changeset 37551 946eb204ba67
parent 37550 b5862ee01abe
child 37552 8b8a845c85fc
equal deleted inserted replaced
37550:b5862ee01abe 37551:946eb204ba67
   303     # Insert error handlers for common I/O failures.
   303     # Insert error handlers for common I/O failures.
   304     _wraphttpresponse(res)
   304     _wraphttpresponse(res)
   305 
   305 
   306     return res
   306     return res
   307 
   307 
       
   308 def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible):
       
   309     # record the url we got redirected to
       
   310     respurl = pycompat.bytesurl(resp.geturl())
       
   311     if respurl.endswith(qs):
       
   312         respurl = respurl[:-len(qs)]
       
   313     if baseurl.rstrip('/') != respurl.rstrip('/'):
       
   314         if not ui.quiet:
       
   315             ui.warn(_('real URL is %s\n') % respurl)
       
   316 
       
   317     try:
       
   318         proto = pycompat.bytesurl(resp.getheader(r'content-type', r''))
       
   319     except AttributeError:
       
   320         proto = pycompat.bytesurl(resp.headers.get(r'content-type', r''))
       
   321 
       
   322     safeurl = util.hidepassword(baseurl)
       
   323     if proto.startswith('application/hg-error'):
       
   324         raise error.OutOfBandError(resp.read())
       
   325     # accept old "text/plain" and "application/hg-changegroup" for now
       
   326     if not (proto.startswith('application/mercurial-') or
       
   327             (proto.startswith('text/plain')
       
   328              and not resp.headers.get('content-length')) or
       
   329             proto.startswith('application/hg-changegroup')):
       
   330         ui.debug("requested URL: '%s'\n" % util.hidepassword(requrl))
       
   331         raise error.RepoError(
       
   332             _("'%s' does not appear to be an hg repository:\n"
       
   333               "---%%<--- (%s)\n%s\n---%%<---\n")
       
   334             % (safeurl, proto or 'no content-type', resp.read(1024)))
       
   335 
       
   336     if proto.startswith('application/mercurial-'):
       
   337         try:
       
   338             version = proto.split('-', 1)[1]
       
   339             version_info = tuple([int(n) for n in version.split('.')])
       
   340         except ValueError:
       
   341             raise error.RepoError(_("'%s' sent a broken Content-Type "
       
   342                                     "header (%s)") % (safeurl, proto))
       
   343 
       
   344         # TODO consider switching to a decompression reader that uses
       
   345         # generators.
       
   346         if version_info == (0, 1):
       
   347             if compressible:
       
   348                 resp = util.compengines['zlib'].decompressorreader(resp)
       
   349 
       
   350             return respurl, resp
       
   351 
       
   352         elif version_info == (0, 2):
       
   353             # application/mercurial-0.2 always identifies the compression
       
   354             # engine in the payload header.
       
   355             elen = struct.unpack('B', resp.read(1))[0]
       
   356             ename = resp.read(elen)
       
   357             engine = util.compengines.forwiretype(ename)
       
   358             return respurl, engine.decompressorreader(resp)
       
   359         else:
       
   360             raise error.RepoError(_("'%s' uses newer protocol %s") %
       
   361                                   (safeurl, version))
       
   362 
       
   363     if compressible:
       
   364         resp = util.compengines['zlib'].decompressorreader(resp)
       
   365 
       
   366     return respurl, resp
       
   367 
   308 class httppeer(wireproto.wirepeer):
   368 class httppeer(wireproto.wirepeer):
   309     def __init__(self, ui, path, url, opener, requestbuilder):
   369     def __init__(self, ui, path, url, opener, requestbuilder):
   310         self.ui = ui
   370         self.ui = ui
   311         self._path = path
   371         self._path = path
   312         self._url = url
   372         self._url = url
   360                                            self._caps, self.capable,
   420                                            self._caps, self.capable,
   361                                            self._url, cmd, args)
   421                                            self._url, cmd, args)
   362 
   422 
   363         resp = sendrequest(self.ui, self._urlopener, req)
   423         resp = sendrequest(self.ui, self._urlopener, req)
   364 
   424 
   365         # record the url we got redirected to
   425         self._url, resp = parsev1commandresponse(self.ui, self._url, cu, qs,
   366         resp_url = pycompat.bytesurl(resp.geturl())
   426                                                  resp, _compressible)
   367         if resp_url.endswith(qs):
       
   368             resp_url = resp_url[:-len(qs)]
       
   369         if self._url.rstrip('/') != resp_url.rstrip('/'):
       
   370             if not self.ui.quiet:
       
   371                 self.ui.warn(_('real URL is %s\n') % resp_url)
       
   372         self._url = resp_url
       
   373         try:
       
   374             proto = pycompat.bytesurl(resp.getheader(r'content-type', r''))
       
   375         except AttributeError:
       
   376             proto = pycompat.bytesurl(resp.headers.get(r'content-type', r''))
       
   377 
       
   378         safeurl = util.hidepassword(self._url)
       
   379         if proto.startswith('application/hg-error'):
       
   380             raise error.OutOfBandError(resp.read())
       
   381         # accept old "text/plain" and "application/hg-changegroup" for now
       
   382         if not (proto.startswith('application/mercurial-') or
       
   383                 (proto.startswith('text/plain')
       
   384                  and not resp.headers.get('content-length')) or
       
   385                 proto.startswith('application/hg-changegroup')):
       
   386             self.ui.debug("requested URL: '%s'\n" % util.hidepassword(cu))
       
   387             raise error.RepoError(
       
   388                 _("'%s' does not appear to be an hg repository:\n"
       
   389                   "---%%<--- (%s)\n%s\n---%%<---\n")
       
   390                 % (safeurl, proto or 'no content-type', resp.read(1024)))
       
   391 
       
   392         if proto.startswith('application/mercurial-'):
       
   393             try:
       
   394                 version = proto.split('-', 1)[1]
       
   395                 version_info = tuple([int(n) for n in version.split('.')])
       
   396             except ValueError:
       
   397                 raise error.RepoError(_("'%s' sent a broken Content-Type "
       
   398                                         "header (%s)") % (safeurl, proto))
       
   399 
       
   400             # TODO consider switching to a decompression reader that uses
       
   401             # generators.
       
   402             if version_info == (0, 1):
       
   403                 if _compressible:
       
   404                     return util.compengines['zlib'].decompressorreader(resp)
       
   405                 return resp
       
   406             elif version_info == (0, 2):
       
   407                 # application/mercurial-0.2 always identifies the compression
       
   408                 # engine in the payload header.
       
   409                 elen = struct.unpack('B', resp.read(1))[0]
       
   410                 ename = resp.read(elen)
       
   411                 engine = util.compengines.forwiretype(ename)
       
   412                 return engine.decompressorreader(resp)
       
   413             else:
       
   414                 raise error.RepoError(_("'%s' uses newer protocol %s") %
       
   415                                       (safeurl, version))
       
   416 
       
   417         if _compressible:
       
   418             return util.compengines['zlib'].decompressorreader(resp)
       
   419 
   427 
   420         return resp
   428         return resp
   421 
   429 
   422     def _call(self, cmd, **args):
   430     def _call(self, cmd, **args):
   423         fp = self._callstream(cmd, **args)
   431         fp = self._callstream(cmd, **args)