annotate mercurial/httppeer.py @ 37616:5e81cf9651c1

hgweb: fallback to checking wsgireq.env for REPO_NAME for 3rd party hosting Starting with d7fd203e36cc, SCM Manager began to 404 any repository access. What's happening is that it is generating a python script that creates an hgweb application (not hgwebdir), and launches hgweb via wsgicgi. It must be setting REPO_NAME in the process environment before launching this script, which gets picked up and put into wsgireq.env when wsgicgi launches the hgweb application. >From there, other variables (notably 'apppath' and 'dispatchpath') are constructed differently. d7fd203e36cc^ (working): apppath: /hg/eng/devsetup dispatchpath: pathinfo: /eng/devsetup reponame: eng/devsetup d7fd203e36cc: apppath: /hg dispatchpath: eng/devsetup pathinfo: /eng/devsetup reponame: None REPO_NAME: eng/devsetup Rather than having an existing installation break when Mercurial is upgraded, just resume checking the environment. I have no idea how many other hosting solutions would break without restoring this.
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 05 Apr 2018 15:42:40 -0400
parents a81d02ea65db
children 77c9ee77687c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
17192
1ac628cd7113 peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 15246
diff changeset
1 # httppeer.py - HTTP repository proxy classes for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
2 #
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2740
diff changeset
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2740
diff changeset
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
5 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8206
diff changeset
6 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9878
diff changeset
7 # GNU General Public License version 2 or any later version.
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
8
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
9 from __future__ import absolute_import
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
10
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
11 import errno
33821
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
12 import io
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
13 import os
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
14 import socket
30763
a520aefb96f1 httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
15 import struct
21074
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
16 import tempfile
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
17
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
18 from .i18n import _
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
19 from .thirdparty import (
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
20 cbor,
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
21 )
37609
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
22 from .thirdparty.zope import (
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
23 interface as zi,
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
24 )
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
25 from . import (
28666
ae53ecc47414 bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 28530
diff changeset
26 bundle2,
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
27 error,
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
28 httpconnection,
30924
48dea083f66d py3: convert the mode argument of os.fdopen to unicodes (1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30763
diff changeset
29 pycompat,
37609
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
30 repository,
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
31 statichttprepo,
36959
43815d87c6aa httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36835
diff changeset
32 url as urlmod,
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
33 util,
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
34 wireproto,
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
35 wireprotoframing,
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
36 wireprototypes,
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37611
diff changeset
37 wireprotov1peer,
37545
93397c4633f6 wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
38 wireprotov2server,
25954
7bbdb78d2842 httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
39 )
4678
a814a5b11fff Work around urllib2 digest auth bug with Python < 2.5
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4633
diff changeset
40
29455
0c741fd6158a py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29241
diff changeset
41 httplib = util.httplib
28883
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28666
diff changeset
42 urlerr = util.urlerr
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28666
diff changeset
43 urlreq = util.urlreq
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28666
diff changeset
44
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
45 def encodevalueinheaders(value, header, limit):
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
46 """Encode a string value into multiple HTTP headers.
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
47
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
48 ``value`` will be encoded into 1 or more HTTP headers with the names
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
49 ``header-<N>`` where ``<N>`` is an integer starting at 1. Each header
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
50 name + value will be at most ``limit`` bytes long.
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
51
34732
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
52 Returns an iterable of 2-tuples consisting of header names and
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
53 values as native strings.
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
54 """
34732
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
55 # HTTP Headers are ASCII. Python 3 requires them to be unicodes,
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
56 # not bytes. This function always takes bytes in as arguments.
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
57 fmt = pycompat.strurl(header) + r'-%s'
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
58 # Note: it is *NOT* a bug that the last bit here is a bytestring
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
59 # and not a unicode: we're just getting the encoded length anyway,
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
60 # and using an r-string to make it portable between Python 2 and 3
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
61 # doesn't work because then the \r is a literal backslash-r
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
62 # instead of a carriage return.
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
63 valuelen = limit - len(fmt % r'000') - len(': \r\n')
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
64 result = []
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
65
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
66 n = 0
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
67 for i in xrange(0, len(value), valuelen):
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
68 n += 1
34732
67e9678efd98 httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents: 34725
diff changeset
69 result.append((fmt % str(n), pycompat.strurl(value[i:i + valuelen])))
30759
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
70
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
71 return result
3f5f0c98cd18 httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30564
diff changeset
72
32002
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
73 def _wraphttpresponse(resp):
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
74 """Wrap an HTTPResponse with common error handlers.
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
75
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
76 This ensures that any I/O from any consumer raises the appropriate
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
77 error and messaging.
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
78 """
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
79 origread = resp.read
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
80
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
81 class readerproxy(resp.__class__):
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
82 def read(self, size=None):
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
83 try:
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
84 return origread(size)
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
85 except httplib.IncompleteRead as e:
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
86 # e.expected is an integer if length known or None otherwise.
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
87 if e.expected:
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
88 msg = _('HTTP request error (incomplete response; '
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
89 'expected %d bytes got %d)') % (e.expected,
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
90 len(e.partial))
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
91 else:
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
92 msg = _('HTTP request error (incomplete response)')
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
93
32023
a29580905771 error: rename RichIOError to PeerTransportError
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32022
diff changeset
94 raise error.PeerTransportError(
32002
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
95 msg,
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
96 hint=_('this may be an intermittent network failure; '
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
97 'if the error persists, consider contacting the '
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
98 'network or server operator'))
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
99 except httplib.HTTPException as e:
32023
a29580905771 error: rename RichIOError to PeerTransportError
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32022
diff changeset
100 raise error.PeerTransportError(
32002
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
101 _('HTTP request error (%s)') % e,
32086
b59a292d0a53 httppeer: unify hint message for PeerTransportError
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 32023
diff changeset
102 hint=_('this may be an intermittent network failure; '
32002
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
103 'if the error persists, consider contacting the '
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
104 'network or server operator'))
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
105
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
106 resp.__class__ = readerproxy
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
107
33821
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
108 class _multifile(object):
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
109 def __init__(self, *fileobjs):
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
110 for f in fileobjs:
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
111 if not util.safehasattr(f, 'length'):
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
112 raise ValueError(
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
113 '_multifile only supports file objects that '
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
114 'have a length but this one does not:', type(f), f)
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
115 self._fileobjs = fileobjs
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
116 self._index = 0
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
117
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
118 @property
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
119 def length(self):
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
120 return sum(f.length for f in self._fileobjs)
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
121
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
122 def read(self, amt=None):
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
123 if amt <= 0:
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
124 return ''.join(f.read() for f in self._fileobjs)
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
125 parts = []
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
126 while amt and self._index < len(self._fileobjs):
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
127 parts.append(self._fileobjs[self._index].read(amt))
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
128 got = len(parts[-1])
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
129 if got < amt:
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
130 self._index += 1
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
131 amt -= got
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
132 return ''.join(parts)
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
133
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
134 def seek(self, offset, whence=os.SEEK_SET):
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
135 if whence != os.SEEK_SET:
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
136 raise NotImplementedError(
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
137 '_multifile does not support anything other'
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
138 ' than os.SEEK_SET for whence on seek()')
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
139 if offset != 0:
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
140 raise NotImplementedError(
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
141 '_multifile only supports seeking to start, but that '
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
142 'could be fixed if you need it')
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
143 for f in self._fileobjs:
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
144 f.seek(0)
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
145 self._index = 0
3c91cc0c5fde httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents: 33806
diff changeset
146
37549
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
147 def makev1commandrequest(ui, requestbuilder, caps, capablefn,
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
148 repobaseurl, cmd, args):
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
149 """Make an HTTP request to run a command for a version 1 client.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
150
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
151 ``caps`` is a set of known server capabilities. The value may be
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
152 None if capabilities are not yet known.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
153
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
154 ``capablefn`` is a function to evaluate a capability.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
155
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
156 ``cmd``, ``args``, and ``data`` define the command, its arguments, and
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
157 raw data to pass to it.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
158 """
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
159 if cmd == 'pushkey':
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
160 args['data'] = ''
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
161 data = args.pop('data', None)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
162 headers = args.pop('headers', {})
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
163
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
164 ui.debug("sending %s command\n" % cmd)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
165 q = [('cmd', cmd)]
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
166 headersize = 0
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
167 # Important: don't use self.capable() here or else you end up
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
168 # with infinite recursion when trying to look up capabilities
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
169 # for the first time.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
170 postargsok = caps is not None and 'httppostargs' in caps
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
171
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
172 # Send arguments via POST.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
173 if postargsok and args:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
174 strargs = urlreq.urlencode(sorted(args.items()))
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
175 if not data:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
176 data = strargs
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
177 else:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
178 if isinstance(data, bytes):
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
179 i = io.BytesIO(data)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
180 i.length = len(data)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
181 data = i
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
182 argsio = io.BytesIO(strargs)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
183 argsio.length = len(strargs)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
184 data = _multifile(argsio, data)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
185 headers[r'X-HgArgs-Post'] = len(strargs)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
186 elif args:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
187 # Calling self.capable() can infinite loop if we are calling
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
188 # "capabilities". But that command should never accept wire
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
189 # protocol arguments. So this should never happen.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
190 assert cmd != 'capabilities'
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
191 httpheader = capablefn('httpheader')
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
192 if httpheader:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
193 headersize = int(httpheader.split(',', 1)[0])
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
194
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
195 # Send arguments via HTTP headers.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
196 if headersize > 0:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
197 # The headers can typically carry more data than the URL.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
198 encargs = urlreq.urlencode(sorted(args.items()))
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
199 for header, value in encodevalueinheaders(encargs, 'X-HgArg',
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
200 headersize):
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
201 headers[header] = value
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
202 # Send arguments via query string (Mercurial <1.9).
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
203 else:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
204 q += sorted(args.items())
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
205
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
206 qs = '?%s' % urlreq.urlencode(q)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
207 cu = "%s%s" % (repobaseurl, qs)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
208 size = 0
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
209 if util.safehasattr(data, 'length'):
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
210 size = data.length
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
211 elif data is not None:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
212 size = len(data)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
213 if data is not None and r'Content-Type' not in headers:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
214 headers[r'Content-Type'] = r'application/mercurial-0.1'
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
215
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
216 # Tell the server we accept application/mercurial-0.2 and multiple
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
217 # compression formats if the server is capable of emitting those
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
218 # payloads.
37556
b77aa48ba690 httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37555
diff changeset
219 # Note: Keep this set empty by default, as client advertisement of
b77aa48ba690 httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37555
diff changeset
220 # protocol parameters should only occur after the handshake.
b77aa48ba690 httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37555
diff changeset
221 protoparams = set()
37549
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
222
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
223 mediatypes = set()
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
224 if caps is not None:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
225 mt = capablefn('httpmediatype')
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
226 if mt:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
227 protoparams.add('0.1')
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
228 mediatypes = set(mt.split(','))
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
229
37556
b77aa48ba690 httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37555
diff changeset
230 protoparams.add('partial-pull')
b77aa48ba690 httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37555
diff changeset
231
37549
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
232 if '0.2tx' in mediatypes:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
233 protoparams.add('0.2')
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
234
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
235 if '0.2tx' in mediatypes and capablefn('compression'):
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
236 # We /could/ compare supported compression formats and prune
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
237 # non-mutually supported or error if nothing is mutually supported.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
238 # For now, send the full list to the server and have it error.
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
239 comps = [e.wireprotosupport().name for e in
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
240 util.compengines.supportedwireengines(util.CLIENTROLE)]
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
241 protoparams.add('comp=%s' % ','.join(comps))
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
242
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
243 if protoparams:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
244 protoheaders = encodevalueinheaders(' '.join(sorted(protoparams)),
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
245 'X-HgProto',
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
246 headersize or 1024)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
247 for header, value in protoheaders:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
248 headers[header] = value
37555
930c433eb311 httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37554
diff changeset
249
930c433eb311 httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37554
diff changeset
250 varyheaders = []
930c433eb311 httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37554
diff changeset
251 for header in headers:
930c433eb311 httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37554
diff changeset
252 if header.lower().startswith(r'x-hg'):
37549
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
253 varyheaders.append(header)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
254
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
255 if varyheaders:
37555
930c433eb311 httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37554
diff changeset
256 headers[r'Vary'] = r','.join(sorted(varyheaders))
37549
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
257
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
258 req = requestbuilder(pycompat.strurl(cu), data, headers)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
259
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
260 if data is not None:
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
261 ui.debug("sending %d bytes\n" % size)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
262 req.add_unredirected_header(r'Content-Length', r'%d' % size)
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
263
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
264 return req, cu, qs
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
265
37548
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
266 def sendrequest(ui, opener, req):
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
267 """Send a prepared HTTP request.
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
268
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
269 Returns the response object.
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
270 """
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
271 if (ui.debugflag
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
272 and ui.configbool('devel', 'debug.peer-request')):
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
273 dbg = ui.debug
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
274 line = 'devel-peer-request: %s\n'
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
275 dbg(line % '%s %s' % (req.get_method(), req.get_full_url()))
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
276 hgargssize = None
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
277
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
278 for header, value in sorted(req.header_items()):
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
279 if header.startswith('X-hgarg-'):
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
280 if hgargssize is None:
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
281 hgargssize = 0
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
282 hgargssize += len(value)
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
283 else:
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
284 dbg(line % ' %s %s' % (header, value))
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
285
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
286 if hgargssize is not None:
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
287 dbg(line % ' %d bytes of commands arguments in headers'
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
288 % hgargssize)
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
289
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
290 if req.has_data():
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
291 data = req.get_data()
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
292 length = getattr(data, 'length', None)
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
293 if length is None:
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
294 length = len(data)
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
295 dbg(line % ' %d bytes of data' % length)
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
296
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
297 start = util.timer()
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
298
37550
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
299 try:
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
300 res = opener.open(req)
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
301 except urlerr.httperror as inst:
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
302 if inst.code == 401:
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
303 raise error.Abort(_('authorization failed'))
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
304 raise
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
305 except httplib.HTTPException as inst:
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
306 ui.debug('http error requesting %s\n' %
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
307 util.hidepassword(req.get_full_url()))
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
308 ui.traceback()
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
309 raise IOError(None, inst)
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
310 finally:
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
311 if ui.configbool('devel', 'debug.peer-request'):
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
312 dbg(line % ' finished in %.4f seconds (%s)'
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
313 % (util.timer() - start, res.code))
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
314
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
315 # Insert error handlers for common I/O failures.
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
316 _wraphttpresponse(res)
37548
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
317
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
318 return res
8e7a4435ab6d httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37547
diff changeset
319
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
320 def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
321 allowcbor=False):
37551
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
322 # record the url we got redirected to
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
323 respurl = pycompat.bytesurl(resp.geturl())
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
324 if respurl.endswith(qs):
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
325 respurl = respurl[:-len(qs)]
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
326 if baseurl.rstrip('/') != respurl.rstrip('/'):
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
327 if not ui.quiet:
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
328 ui.warn(_('real URL is %s\n') % respurl)
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
329
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
330 try:
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
331 proto = pycompat.bytesurl(resp.getheader(r'content-type', r''))
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
332 except AttributeError:
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
333 proto = pycompat.bytesurl(resp.headers.get(r'content-type', r''))
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
334
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
335 safeurl = util.hidepassword(baseurl)
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
336 if proto.startswith('application/hg-error'):
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
337 raise error.OutOfBandError(resp.read())
37554
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
338
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
339 # Pre 1.0 versions of Mercurial used text/plain and
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
340 # application/hg-changegroup. We don't support such old servers.
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
341 if not proto.startswith('application/mercurial-'):
37551
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
342 ui.debug("requested URL: '%s'\n" % util.hidepassword(requrl))
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
343 raise error.RepoError(
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
344 _("'%s' does not appear to be an hg repository:\n"
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
345 "---%%<--- (%s)\n%s\n---%%<---\n")
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
346 % (safeurl, proto or 'no content-type', resp.read(1024)))
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
347
37554
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
348 try:
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
349 subtype = proto.split('-', 1)[1]
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
350
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
351 # Unless we end up supporting CBOR in the legacy wire protocol,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
352 # this should ONLY be encountered for the initial capabilities
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
353 # request during handshake.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
354 if subtype == 'cbor':
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
355 if allowcbor:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
356 return respurl, proto, resp
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
357 else:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
358 raise error.RepoError(_('unexpected CBOR response from '
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
359 'server'))
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
360
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
361 version_info = tuple([int(n) for n in subtype.split('.')])
37554
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
362 except ValueError:
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
363 raise error.RepoError(_("'%s' sent a broken Content-Type "
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
364 "header (%s)") % (safeurl, proto))
37551
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
365
37554
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
366 # TODO consider switching to a decompression reader that uses
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
367 # generators.
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
368 if version_info == (0, 1):
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
369 if compressible:
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
370 resp = util.compengines['zlib'].decompressorreader(resp)
37551
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
371
37554
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
372 elif version_info == (0, 2):
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
373 # application/mercurial-0.2 always identifies the compression
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
374 # engine in the payload header.
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
375 elen = struct.unpack('B', resp.read(1))[0]
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
376 ename = resp.read(elen)
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
377 engine = util.compengines.forwiretype(ename)
37551
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
378
37554
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
379 resp = engine.decompressorreader(resp)
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
380 else:
301a1d2e8016 httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37553
diff changeset
381 raise error.RepoError(_("'%s' uses newer protocol %s") %
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
382 (safeurl, subtype))
37551
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
383
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
384 return respurl, proto, resp
37551
946eb204ba67 httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37550
diff changeset
385
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37611
diff changeset
386 class httppeer(wireprotov1peer.wirepeer):
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
387 def __init__(self, ui, path, url, opener, requestbuilder, caps):
37321
e826fe7a08c7 peer: make ui an attribute
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37320
diff changeset
388 self.ui = ui
33705
73fd395ee29e httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33704
diff changeset
389 self._path = path
37006
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
390 self._url = url
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
391 self._caps = caps
37006
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
392 self._urlopener = opener
37547
835ccc2a5ef1 httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
393 self._requestbuilder = requestbuilder
4516
96d8a56d4ef9 Removed trailing whitespace and tabs from python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4369
diff changeset
394
7752
998fc8f62539 close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents: 7641
diff changeset
395 def __del__(self):
37006
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
396 for h in self._urlopener.handlers:
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
397 h.close()
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
398 getattr(h, "close_all", lambda: None)()
7752
998fc8f62539 close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents: 7641
diff changeset
399
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37006
diff changeset
400 # Begin of ipeerconnection interface.
33805
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
401
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
402 def url(self):
33705
73fd395ee29e httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33704
diff changeset
403 return self._path
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
404
33805
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
405 def local(self):
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
406 return None
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
407
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
408 def peer(self):
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
409 return self
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
410
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
411 def canpush(self):
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
412 return True
2442
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
413
33805
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
414 def close(self):
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
415 pass
13603
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
416
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37006
diff changeset
417 # End of ipeerconnection interface.
33805
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
418
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37006
diff changeset
419 # Begin of ipeercommands interface.
33805
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
420
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
421 def capabilities(self):
33705
73fd395ee29e httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33704
diff changeset
422 return self._caps
2442
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
423
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37006
diff changeset
424 # End of ipeercommands interface.
33805
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
425
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
426 # look up capabilities only when needed
f913e90f15a0 httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33705
diff changeset
427
30464
e16e234b9ca3 httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30241
diff changeset
428 def _callstream(self, cmd, _compressible=False, **args):
35359
98bc4c43f570 py3: handle keyword arguments correctly in httppeer.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35197
diff changeset
429 args = pycompat.byteskwargs(args)
36218
e4ccd7a69f77 httppeer: change logic around argument handling
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35884
diff changeset
430
37549
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
431 req, cu, qs = makev1commandrequest(self.ui, self._requestbuilder,
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
432 self._caps, self.capable,
66d1001e1500 httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37548
diff changeset
433 self._url, cmd, args)
30763
a520aefb96f1 httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30759
diff changeset
434
37550
b5862ee01abe httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37549
diff changeset
435 resp = sendrequest(self.ui, self._urlopener, req)
32002
bf855efe5664 httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30924
diff changeset
436
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
437 self._url, ct, resp = parsev1commandresponse(self.ui, self._url, cu, qs,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
438 resp, _compressible)
30464
e16e234b9ca3 httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30241
diff changeset
439
752
c693eafd5967 Simplify content type checking
mpm@selenic.com
parents: 751
diff changeset
440 return resp
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
441
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
442 def _call(self, cmd, **args):
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
443 fp = self._callstream(cmd, **args)
2435
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
444 try:
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
445 return fp.read()
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
446 finally:
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
447 # if using keepalive, allow connection to be reused
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
448 fp.close()
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
449
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
450 def _callpush(self, cmd, cg, **args):
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
451 # have to stream bundle to a temp file because we do not have
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
452 # http 1.1 chunked transfer.
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
453
3662
f4dc02d7fb71 unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents: 3661
diff changeset
454 types = self.capable('unbundle')
3703
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
455 try:
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
456 types = types.split(',')
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
457 except AttributeError:
14060
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
458 # servers older than d1b16a746db6 will send 'unbundle' as a
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
459 # boolean capability. They only support headerless/uncompressed
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
460 # bundles.
3703
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
461 types = [""]
14060
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
462 for x in types:
28666
ae53ecc47414 bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 28530
diff changeset
463 if x in bundle2.bundletypes:
14060
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
464 type = x
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
465 break
3613
cbf352b9a3cd Client support for hgweb unbundle with versions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3609
diff changeset
466
28666
ae53ecc47414 bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 28530
diff changeset
467 tempname = bundle2.writebundle(self.ui, cg, None, type)
14244
e7525a555a64 url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents: 14149
diff changeset
468 fp = httpconnection.httpsendfile(self.ui, tempname, "rb")
36297
a59ff82154b8 httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents: 36270
diff changeset
469 headers = {r'Content-Type': r'application/mercurial-0.1'}
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
470
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
471 try:
25085
e05734cd7902 httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 23895
diff changeset
472 r = self._call(cmd, data=fp, headers=headers, **args)
e05734cd7902 httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 23895
diff changeset
473 vals = r.split('\n', 1)
e05734cd7902 httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 23895
diff changeset
474 if len(vals) < 2:
e05734cd7902 httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 23895
diff changeset
475 raise error.ResponseError(_("unexpected response:"), r)
e05734cd7902 httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 23895
diff changeset
476 return vals
36430
efebfa9b4cab httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents: 36426
diff changeset
477 except urlerr.httperror:
efebfa9b4cab httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents: 36426
diff changeset
478 # Catch and re-raise these so we don't try and treat them
efebfa9b4cab httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents: 36426
diff changeset
479 # like generic socket errors. They lack any values in
efebfa9b4cab httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents: 36426
diff changeset
480 # .args on Python 3 which breaks our socket.error block.
efebfa9b4cab httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents: 36426
diff changeset
481 raise
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25500
diff changeset
482 except socket.error as err:
25085
e05734cd7902 httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 23895
diff changeset
483 if err.args[0] in (errno.ECONNRESET, errno.EPIPE):
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25954
diff changeset
484 raise error.Abort(_('push failed: %s') % err.args[1])
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25954
diff changeset
485 raise error.Abort(err.args[1])
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
486 finally:
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
487 fp.close()
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
488 os.unlink(tempname)
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2435
diff changeset
489
21074
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
490 def _calltwowaystream(self, cmd, fp, **args):
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
491 fh = None
23086
cde6904f1992 httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents: 21188
diff changeset
492 fp_ = None
21074
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
493 filename = None
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
494 try:
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
495 # dump bundle to disk
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
496 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
36835
5bc7ff103081 py3: use r'' instead of sysstr('') to get around code transformer
Yuya Nishihara <yuya@tcha.org>
parents: 36430
diff changeset
497 fh = os.fdopen(fd, r"wb")
21074
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
498 d = fp.read(4096)
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
499 while d:
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
500 fh.write(d)
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
501 d = fp.read(4096)
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
502 fh.close()
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
503 # start http push
23086
cde6904f1992 httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents: 21188
diff changeset
504 fp_ = httpconnection.httpsendfile(self.ui, filename, "rb")
36297
a59ff82154b8 httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents: 36270
diff changeset
505 headers = {r'Content-Type': r'application/mercurial-0.1'}
23086
cde6904f1992 httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents: 21188
diff changeset
506 return self._callstream(cmd, data=fp_, headers=headers, **args)
21074
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
507 finally:
23086
cde6904f1992 httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents: 21188
diff changeset
508 if fp_ is not None:
cde6904f1992 httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents: 21188
diff changeset
509 fp_.close()
21074
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
510 if fh is not None:
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
511 fh.close()
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
512 os.unlink(filename)
f8a0d82b0463 httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
513
20905
167047ba3cfa wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 18742
diff changeset
514 def _callcompressable(self, cmd, **args):
30464
e16e234b9ca3 httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30241
diff changeset
515 return self._callstream(cmd, _compressible=True, **args)
11370
db3f6f0e4e7d pushkey: add http support
Matt Mackall <mpm@selenic.com>
parents: 11153
diff changeset
516
21188
d36440d84328 httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents: 21074
diff changeset
517 def _abort(self, exception):
d36440d84328 httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents: 21074
diff changeset
518 raise exception
d36440d84328 httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents: 21074
diff changeset
519
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
520 # TODO implement interface for version 2 peers
37611
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
521 @zi.implementer(repository.ipeerconnection, repository.ipeercapabilities)
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
522 class httpv2peer(object):
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
523 def __init__(self, ui, repourl, apipath, opener, requestbuilder,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
524 apidescriptor):
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
525 self.ui = ui
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
526
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
527 if repourl.endswith('/'):
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
528 repourl = repourl[:-1]
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
529
37609
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
530 self._url = repourl
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
531 self._apipath = apipath
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
532 self._opener = opener
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
533 self._requestbuilder = requestbuilder
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
534 self._descriptor = apidescriptor
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
535
37609
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
536 # Start of ipeerconnection.
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
537
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
538 def url(self):
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
539 return self._url
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
540
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
541 def local(self):
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
542 return None
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
543
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
544 def peer(self):
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
545 return self
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
546
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
547 def canpush(self):
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
548 # TODO change once implemented.
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
549 return False
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
550
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
551 def close(self):
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
552 pass
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
553
37609
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
554 # End of ipeerconnection.
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
555
37611
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
556 # Start of ipeercapabilities.
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
557
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
558 def capable(self, name):
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
559 # The capabilities used internally historically map to capabilities
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
560 # advertised from the "capabilities" wire protocol command. However,
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
561 # version 2 of that command works differently.
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
562
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
563 # Maps to commands that are available.
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
564 if name in ('branchmap', 'getbundle', 'known', 'lookup', 'pushkey'):
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
565 return True
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
566
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
567 # Other concepts.
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
568 if name in ('bundle2',):
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
569 return True
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
570
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
571 return False
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
572
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
573 def requirecap(self, name, purpose):
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
574 if self.capable(name):
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
575 return
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
576
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
577 raise error.CapabilityError(
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
578 _('cannot %s; client or remote repository does not support the %r '
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
579 'capability') % (purpose, name))
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
580
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
581 # End of ipeercapabilities.
ae8730877371 httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37609
diff changeset
582
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
583 # TODO require to be part of a batched primitive, use futures.
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
584 def _call(self, name, **args):
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
585 """Call a wire protocol command with arguments."""
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
586
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
587 # Having this early has a side-effect of importing wireprotov2server,
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
588 # which has the side-effect of ensuring commands are registered.
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
589
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
590 # TODO modify user-agent to reflect v2.
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
591 headers = {
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
592 r'Accept': wireprotov2server.FRAMINGTYPE,
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
593 r'Content-Type': wireprotov2server.FRAMINGTYPE,
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
594 }
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
595
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
596 # TODO permissions should come from capabilities results.
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
597 permission = wireproto.commandsv2[name].permission
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
598 if permission not in ('push', 'pull'):
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
599 raise error.ProgrammingError('unknown permission type: %s' %
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
600 permission)
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
601
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
602 permission = {
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
603 'push': 'rw',
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
604 'pull': 'ro',
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
605 }[permission]
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
606
37609
01bfe5ad0c53 httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37558
diff changeset
607 url = '%s/%s/%s/%s' % (self._url, self._apipath, permission, name)
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
608
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
609 # TODO this should be part of a generic peer for the frame-based
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
610 # protocol.
37543
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
611 reactor = wireprotoframing.clientreactor(hasmultiplesend=False,
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
612 buffersends=True)
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
613
37543
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
614 request, action, meta = reactor.callcommand(name, args)
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
615 assert action == 'noop'
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
616
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
617 action, meta = reactor.flushcommands()
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
618 assert action == 'sendframes'
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
619
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
620 body = b''.join(map(bytes, meta['framegen']))
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
621 req = self._requestbuilder(pycompat.strurl(url), body, headers)
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
622 req.add_unredirected_header(r'Content-Length', r'%d' % len(body))
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
623
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
624 # TODO unify this code with httppeer.
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
625 try:
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
626 res = self._opener.open(req)
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
627 except urlerr.httperror as e:
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
628 if e.code == 401:
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
629 raise error.Abort(_('authorization failed'))
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
630
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
631 raise
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
632 except httplib.HTTPException as e:
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
633 self.ui.traceback()
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
634 raise IOError(None, e)
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
635
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
636 # TODO validate response type, wrap response to handle I/O errors.
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
637 # TODO more robust frame receiver.
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
638 results = []
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
639
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
640 while True:
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
641 frame = wireprotoframing.readframe(res)
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
642 if frame is None:
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
643 break
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
644
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
645 self.ui.note(_('received %r\n') % frame)
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
646
37544
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
647 action, meta = reactor.onframerecv(frame)
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
648
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
649 if action == 'responsedata':
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
650 if meta['cbor']:
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
651 payload = util.bytesio(meta['data'])
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
652
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
653 decoder = cbor.CBORDecoder(payload)
37544
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
654 while payload.tell() + 1 < len(meta['data']):
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
655 results.append(decoder.decode())
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
656 else:
37544
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
657 results.append(meta['data'])
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
658 else:
37544
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
659 error.ProgrammingError('unhandled action: %s' % action)
37483
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
660
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
661 return results
61e405fb6372 wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37411
diff changeset
662
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
663 # Registry of API service names to metadata about peers that handle it.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
664 #
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
665 # The following keys are meaningful:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
666 #
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
667 # init
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
668 # Callable receiving (ui, repourl, servicepath, opener, requestbuilder,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
669 # apidescriptor) to create a peer.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
670 #
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
671 # priority
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
672 # Integer priority for the service. If we could choose from multiple
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
673 # services, we choose the one with the highest priority.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
674 API_PEERS = {
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
675 wireprototypes.HTTPV2: {
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
676 'init': httpv2peer,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
677 'priority': 50,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
678 },
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
679 }
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
680
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
681 def performhandshake(ui, url, opener, requestbuilder):
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
682 # The handshake is a request to the capabilities command.
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
683
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
684 caps = None
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
685 def capable(x):
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
686 raise error.ProgrammingError('should not be called')
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
687
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
688 args = {}
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
689
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
690 # The client advertises support for newer protocols by adding an
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
691 # X-HgUpgrade-* header with a list of supported APIs and an
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
692 # X-HgProto-* header advertising which serializing formats it supports.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
693 # We only support the HTTP version 2 transport and CBOR responses for
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
694 # now.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
695 advertisev2 = ui.configbool('experimental', 'httppeer.advertise-v2')
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
696
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
697 if advertisev2:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
698 args['headers'] = {
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
699 r'X-HgProto-1': r'cbor',
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
700 }
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
701
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
702 args['headers'].update(
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
703 encodevalueinheaders(' '.join(sorted(API_PEERS)),
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
704 'X-HgUpgrade',
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
705 # We don't know the header limit this early.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
706 # So make it small.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
707 1024))
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
708
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
709 req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps,
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
710 capable, url, 'capabilities',
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
711 args)
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
712
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
713 resp = sendrequest(ui, opener, req)
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
714
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
715 respurl, ct, resp = parsev1commandresponse(ui, url, requrl, qs, resp,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
716 compressible=False,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
717 allowcbor=advertisev2)
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
718
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
719 try:
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
720 rawdata = resp.read()
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
721 finally:
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
722 resp.close()
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
723
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
724 if not ct.startswith('application/mercurial-'):
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
725 raise error.ProgrammingError('unexpected content-type: %s' % ct)
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
726
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
727 if advertisev2:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
728 if ct == 'application/mercurial-cbor':
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
729 try:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
730 info = cbor.loads(rawdata)
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
731 except cbor.CBORDecodeError:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
732 raise error.Abort(_('error decoding CBOR from remote server'),
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
733 hint=_('try again and consider contacting '
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
734 'the server operator'))
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
735
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
736 # We got a legacy response. That's fine.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
737 elif ct in ('application/mercurial-0.1', 'application/mercurial-0.2'):
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
738 info = {
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
739 'v1capabilities': set(rawdata.split())
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
740 }
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
741
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
742 else:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
743 raise error.RepoError(
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
744 _('unexpected response type from server: %s') % ct)
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
745 else:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
746 info = {
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
747 'v1capabilities': set(rawdata.split())
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
748 }
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
749
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
750 return respurl, info
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
751
37553
6b08cf6b900f httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37552
diff changeset
752 def makepeer(ui, path, opener=None, requestbuilder=urlreq.request):
37547
835ccc2a5ef1 httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
753 """Construct an appropriate HTTP peer instance.
835ccc2a5ef1 httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
754
37553
6b08cf6b900f httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37552
diff changeset
755 ``opener`` is an ``url.opener`` that should be used to establish
6b08cf6b900f httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37552
diff changeset
756 connections, perform HTTP requests.
6b08cf6b900f httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37552
diff changeset
757
37547
835ccc2a5ef1 httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
758 ``requestbuilder`` is the type used for constructing HTTP requests.
835ccc2a5ef1 httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
759 It exists as an argument so extensions can override the default.
835ccc2a5ef1 httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
760 """
37006
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
761 u = util.url(path)
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
762 if u.query or u.fragment:
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
763 raise error.Abort(_('unsupported URL component: "%s"') %
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
764 (u.query or u.fragment))
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
765
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
766 # urllib cannot handle URLs with embedded user or passwd.
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
767 url, authinfo = u.authinfo()
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
768 ui.debug('using %s\n' % url)
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
769
37553
6b08cf6b900f httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37552
diff changeset
770 opener = opener or urlmod.opener(ui, authinfo)
37006
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
771
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
772 respurl, info = performhandshake(ui, url, opener, requestbuilder)
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
773
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
774 # Given the intersection of APIs that both we and the server support,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
775 # sort by their advertised priority and pick the first one.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
776 #
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
777 # TODO consider making this request-based and interface driven. For
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
778 # example, the caller could say "I want a peer that does X." It's quite
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
779 # possible that not all peers would do that. Since we know the service
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
780 # capabilities, we could filter out services not meeting the
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
781 # requirements. Possibly by consulting the interfaces defined by the
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
782 # peer type.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
783 apipeerchoices = set(info.get('apis', {}).keys()) & set(API_PEERS.keys())
37552
8b8a845c85fc httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37551
diff changeset
784
37558
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
785 preferredchoices = sorted(apipeerchoices,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
786 key=lambda x: API_PEERS[x]['priority'],
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
787 reverse=True)
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
788
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
789 for service in preferredchoices:
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
790 apipath = '%s/%s' % (info['apibase'].rstrip('/'), service)
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
791
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
792 return API_PEERS[service]['init'](ui, respurl, apipath, opener,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
793 requestbuilder,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
794 info['apis'][service])
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
795
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
796 # Failed to construct an API peer. Fall back to legacy.
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
797 return httppeer(ui, path, respurl, opener, requestbuilder,
8a73132214a3 httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37556
diff changeset
798 info['v1capabilities'])
37006
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
799
2740
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2673
diff changeset
800 def instance(ui, path, create):
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2673
diff changeset
801 if create:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25954
diff changeset
802 raise error.Abort(_('cannot create new http repository'))
7211
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
803 try:
36959
43815d87c6aa httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36835
diff changeset
804 if path.startswith('https:') and not urlmod.has_https:
36220
874209855f5c httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36219
diff changeset
805 raise error.Abort(_('Python support for SSL and HTTPS '
874209855f5c httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36219
diff changeset
806 'is not installed'))
35884
197d10e157ce httppeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35698
diff changeset
807
37006
8e89c2bec1f7 httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36961
diff changeset
808 inst = makepeer(ui, path)
35884
197d10e157ce httppeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35698
diff changeset
809
7211
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
810 return inst
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25500
diff changeset
811 except error.RepoError as httpexception:
14148
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
812 try:
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
813 r = statichttprepo.instance(ui, "static-" + path, create)
29241
269f7ea08983 httppeer: make a message translatable
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28883
diff changeset
814 ui.note(_('(falling back to static-http)\n'))
14148
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
815 return r
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
816 except error.RepoError:
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
817 raise httpexception # use the original http RepoError instead