Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/httppeer.py @ 37669:1cb54e6193a6
py3: paper over differences in future exception handling
It looks like Python 3's futures library lacks set_exception_info
entirely. We'll just give up and use set_exception in that case.
# no-check-commit because the underbar naming is just saner here
Differential Revision: https://phab.mercurial-scm.org/D3336
author | Augie Fackler <augie@google.com> |
---|---|
date | Fri, 13 Apr 2018 18:17:45 -0400 |
parents | 8cea0d57bf37 |
children | 0664be4f0c1f |
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 | 3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
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 | 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 |
33842
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
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 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
16 import sys |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
17 import tempfile |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
18 import weakref |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
19 |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
20 from .i18n import _ |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
21 from .thirdparty import ( |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
22 cbor, |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
23 ) |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
24 from .thirdparty.zope import ( |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
25 interface as zi, |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
26 ) |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
27 from . import ( |
28666
ae53ecc47414
bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
28530
diff
changeset
|
28 bundle2, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
29 error, |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
30 httpconnection, |
30944
48dea083f66d
py3: convert the mode argument of os.fdopen to unicodes (1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30763
diff
changeset
|
31 pycompat, |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
32 repository, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
33 statichttprepo, |
36965
43815d87c6aa
httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36843
diff
changeset
|
34 url as urlmod, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
35 util, |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
36 wireprotoframing, |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
37 wireprototypes, |
37614
a81d02ea65db
wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37611
diff
changeset
|
38 wireprotov1peer, |
37545
93397c4633f6
wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37544
diff
changeset
|
39 wireprotov2server, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
40 ) |
4678
a814a5b11fff
Work around urllib2 digest auth bug with Python < 2.5
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4633
diff
changeset
|
41 |
29455
0c741fd6158a
py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29241
diff
changeset
|
42 httplib = util.httplib |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
43 urlerr = util.urlerr |
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
44 urlreq = util.urlreq |
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
45 |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
46 def encodevalueinheaders(value, header, limit): |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
47 """Encode a string value into multiple HTTP headers. |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
48 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
49 ``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:
30569
diff
changeset
|
50 ``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:
30569
diff
changeset
|
51 name + value will be at most ``limit`` bytes long. |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
52 |
34732
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
53 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
|
54 values as native strings. |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
55 """ |
34732
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
56 # 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
|
57 # 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
|
58 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
|
59 # 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
|
60 # 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
|
61 # 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
|
62 # 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
|
63 # instead of a carriage return. |
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
64 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:
30569
diff
changeset
|
65 result = [] |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
66 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
67 n = 0 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
68 for i in xrange(0, len(value), valuelen): |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
69 n += 1 |
34732
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
70 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:
30569
diff
changeset
|
71 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
72 return result |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30569
diff
changeset
|
73 |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
74 def _wraphttpresponse(resp): |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
75 """Wrap an HTTPResponse with common error handlers. |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
76 |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
77 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:
30944
diff
changeset
|
78 error and messaging. |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
79 """ |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
80 origread = resp.read |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
81 |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
82 class readerproxy(resp.__class__): |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
83 def read(self, size=None): |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
84 try: |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
85 return origread(size) |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
86 except httplib.IncompleteRead as e: |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
87 # e.expected is an integer if length known or None otherwise. |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
88 if e.expected: |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
89 msg = _('HTTP request error (incomplete response; ' |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
90 'expected %d bytes got %d)') % (e.expected, |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
91 len(e.partial)) |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
92 else: |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
93 msg = _('HTTP request error (incomplete response)') |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
94 |
32023
a29580905771
error: rename RichIOError to PeerTransportError
Gregory Szorc <gregory.szorc@gmail.com>
parents:
32022
diff
changeset
|
95 raise error.PeerTransportError( |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
96 msg, |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
97 hint=_('this may be an intermittent network failure; ' |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
98 'if the error persists, consider contacting the ' |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
99 'network or server operator')) |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
100 except httplib.HTTPException as e: |
32023
a29580905771
error: rename RichIOError to PeerTransportError
Gregory Szorc <gregory.szorc@gmail.com>
parents:
32022
diff
changeset
|
101 raise error.PeerTransportError( |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
102 _('HTTP request error (%s)') % e, |
32086
b59a292d0a53
httppeer: unify hint message for PeerTransportError
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32023
diff
changeset
|
103 hint=_('this may be an intermittent network failure; ' |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
104 'if the error persists, consider contacting the ' |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
105 'network or server operator')) |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
106 |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
107 resp.__class__ = readerproxy |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
108 |
33842
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
109 class _multifile(object): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
110 def __init__(self, *fileobjs): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
111 for f in fileobjs: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
112 if not util.safehasattr(f, 'length'): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
113 raise ValueError( |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
114 '_multifile only supports file objects that ' |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
115 '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:
33827
diff
changeset
|
116 self._fileobjs = fileobjs |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
117 self._index = 0 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
118 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
119 @property |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
120 def length(self): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
121 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:
33827
diff
changeset
|
122 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
123 def read(self, amt=None): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
124 if amt <= 0: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
125 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:
33827
diff
changeset
|
126 parts = [] |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
127 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:
33827
diff
changeset
|
128 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:
33827
diff
changeset
|
129 got = len(parts[-1]) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
130 if got < amt: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
131 self._index += 1 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
132 amt -= got |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
133 return ''.join(parts) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
134 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
135 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:
33827
diff
changeset
|
136 if whence != os.SEEK_SET: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
137 raise NotImplementedError( |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
138 '_multifile does not support anything other' |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
139 ' 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:
33827
diff
changeset
|
140 if offset != 0: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
141 raise NotImplementedError( |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
142 '_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:
33827
diff
changeset
|
143 '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:
33827
diff
changeset
|
144 for f in self._fileobjs: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
145 f.seek(0) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
146 self._index = 0 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33827
diff
changeset
|
147 |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
148 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
|
149 repobaseurl, cmd, args): |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
150 """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
|
151 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
152 ``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
|
153 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
|
154 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
155 ``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
|
156 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
157 ``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
|
158 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
|
159 """ |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
160 if cmd == 'pushkey': |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
161 args['data'] = '' |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
162 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
|
163 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
|
164 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
165 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
|
166 q = [('cmd', cmd)] |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
167 headersize = 0 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
168 # 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
|
169 # 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
|
170 # 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
|
171 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
|
172 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
173 # 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
|
174 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
|
175 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
|
176 if not data: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
177 data = strargs |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
178 else: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
179 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
|
180 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
|
181 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
|
182 data = i |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
183 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
|
184 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
|
185 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
|
186 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
|
187 elif args: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
188 # 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
|
189 # "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
|
190 # 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
|
191 assert cmd != 'capabilities' |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
192 httpheader = capablefn('httpheader') |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
193 if httpheader: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
194 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
|
195 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
196 # 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
|
197 if headersize > 0: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
198 # 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
|
199 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
|
200 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
|
201 headersize): |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
202 headers[header] = value |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
203 # 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
|
204 else: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
205 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
|
206 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
207 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
|
208 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
|
209 size = 0 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
210 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
|
211 size = data.length |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
212 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
|
213 size = len(data) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
214 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
|
215 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
|
216 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
217 # 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
|
218 # 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
|
219 # payloads. |
37556
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
220 # 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
|
221 # 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
|
222 protoparams = set() |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
223 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
224 mediatypes = set() |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
225 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
|
226 mt = capablefn('httpmediatype') |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
227 if mt: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
228 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
|
229 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
|
230 |
37556
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
231 protoparams.add('partial-pull') |
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
232 |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
233 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
|
234 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
|
235 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
236 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
|
237 # 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
|
238 # 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
|
239 # 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
|
240 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
|
241 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
|
242 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
|
243 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
244 if protoparams: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
245 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
|
246 'X-HgProto', |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
247 headersize or 1024) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
248 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
|
249 headers[header] = value |
37555
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
250 |
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
251 varyheaders = [] |
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
252 for header in headers: |
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
253 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
|
254 varyheaders.append(header) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
255 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
256 if varyheaders: |
37555
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
257 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
|
258 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
259 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
|
260 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
261 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
|
262 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
|
263 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
|
264 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
265 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
|
266 |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
267 def sendrequest(ui, opener, req): |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
268 """Send a prepared HTTP request. |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
269 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
270 Returns the response object. |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
271 """ |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
272 if (ui.debugflag |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
273 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
|
274 dbg = ui.debug |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
275 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
|
276 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
|
277 hgargssize = None |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
278 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
279 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
|
280 if header.startswith('X-hgarg-'): |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
281 if hgargssize is None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
282 hgargssize = 0 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
283 hgargssize += len(value) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
284 else: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
285 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
|
286 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
287 if hgargssize is not None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
288 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
|
289 % hgargssize) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
290 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
291 if req.has_data(): |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
292 data = req.get_data() |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
293 length = getattr(data, 'length', None) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
294 if length is None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
295 length = len(data) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
296 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
|
297 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
298 start = util.timer() |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
299 |
37550
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
300 try: |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
301 res = opener.open(req) |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
302 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
|
303 if inst.code == 401: |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
304 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
|
305 raise |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
306 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
|
307 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
|
308 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
|
309 ui.traceback() |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
310 raise IOError(None, inst) |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
311 finally: |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
312 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
|
313 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
|
314 % (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
|
315 |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
316 # 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
|
317 _wraphttpresponse(res) |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
318 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
319 return res |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
320 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
321 def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
322 allowcbor=False): |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
323 # 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
|
324 respurl = pycompat.bytesurl(resp.geturl()) |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
325 if respurl.endswith(qs): |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
326 respurl = respurl[:-len(qs)] |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
327 if baseurl.rstrip('/') != respurl.rstrip('/'): |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
328 if not ui.quiet: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
329 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
|
330 |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
331 try: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
332 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
|
333 except AttributeError: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
334 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
|
335 |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
336 safeurl = util.hidepassword(baseurl) |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
337 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
|
338 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
|
339 |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
340 # 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
|
341 # 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
|
342 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
|
343 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
|
344 raise error.RepoError( |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
345 _("'%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
|
346 "---%%<--- (%s)\n%s\n---%%<---\n") |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
347 % (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
|
348 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
349 try: |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
350 subtype = proto.split('-', 1)[1] |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
351 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
352 # 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
|
353 # this should ONLY be encountered for the initial capabilities |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
354 # request during handshake. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
355 if subtype == 'cbor': |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
356 if allowcbor: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
357 return respurl, proto, resp |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
358 else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
359 raise error.RepoError(_('unexpected CBOR response from ' |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
360 'server')) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
361 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
362 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
|
363 except ValueError: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
364 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
|
365 "header (%s)") % (safeurl, proto)) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
366 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
367 # 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
|
368 # generators. |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
369 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
|
370 if compressible: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
371 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
|
372 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
373 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
|
374 # 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
|
375 # 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
|
376 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
|
377 ename = resp.read(elen) |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
378 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
|
379 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
380 resp = engine.decompressorreader(resp) |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
381 else: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
382 raise error.RepoError(_("'%s' uses newer protocol %s") % |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
383 (safeurl, subtype)) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
384 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
385 return respurl, proto, resp |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
386 |
37614
a81d02ea65db
wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37611
diff
changeset
|
387 class httppeer(wireprotov1peer.wirepeer): |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
388 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
|
389 self.ui = ui |
33731
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33730
diff
changeset
|
390 self._path = path |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
391 self._url = url |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
392 self._caps = caps |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
393 self._urlopener = opener |
37547
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
394 self._requestbuilder = requestbuilder |
4516
96d8a56d4ef9
Removed trailing whitespace and tabs from python files
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4369
diff
changeset
|
395 |
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
396 def __del__(self): |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
397 for h in self._urlopener.handlers: |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
398 h.close() |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
399 getattr(h, "close_all", lambda: None)() |
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
400 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
401 # Begin of ipeerconnection interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
402 |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
403 def url(self): |
33731
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33730
diff
changeset
|
404 return self._path |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
405 |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
406 def local(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
407 return None |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
408 |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
409 def peer(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
410 return self |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
411 |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
412 def canpush(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
413 return True |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
414 |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
415 def close(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
416 pass |
13603
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
417 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
418 # End of ipeerconnection interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
419 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
420 # Begin of ipeercommands interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
421 |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
422 def capabilities(self): |
33731
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33730
diff
changeset
|
423 return self._caps |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
424 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
425 # End of ipeercommands interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
426 |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
427 # look up capabilities only when needed |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
428 |
30473
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
429 def _callstream(self, cmd, _compressible=False, **args): |
35368
98bc4c43f570
py3: handle keyword arguments correctly in httppeer.py
Pulkit Goyal <7895pulkit@gmail.com>
parents:
35208
diff
changeset
|
430 args = pycompat.byteskwargs(args) |
36256
e4ccd7a69f77
httppeer: change logic around argument handling
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35924
diff
changeset
|
431 |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
432 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
|
433 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
|
434 self._url, cmd, args) |
30763
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
435 |
37550
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
436 resp = sendrequest(self.ui, self._urlopener, req) |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
437 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
438 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
|
439 resp, _compressible) |
30473
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
440 |
752 | 441 return resp |
60 | 442 |
11589
e8d22fe2ddab
protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents:
11588
diff
changeset
|
443 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
|
444 fp = self._callstream(cmd, **args) |
2435
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
445 try: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
446 return fp.read() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
447 finally: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
448 # if using keepalive, allow connection to be reused |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
449 fp.close() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
450 |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
451 def _callpush(self, cmd, cg, **args): |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
452 # 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
|
453 # http 1.1 chunked transfer. |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
454 |
3662
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3661
diff
changeset
|
455 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
|
456 try: |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
457 types = types.split(',') |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
458 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
|
459 # 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
|
460 # 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
|
461 # bundles. |
3703
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
462 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
|
463 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
|
464 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
|
465 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
|
466 break |
3613
cbf352b9a3cd
Client support for hgweb unbundle with versions.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3609
diff
changeset
|
467 |
28666
ae53ecc47414
bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
28530
diff
changeset
|
468 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
|
469 fp = httpconnection.httpsendfile(self.ui, tempname, "rb") |
36330
a59ff82154b8
httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents:
36303
diff
changeset
|
470 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
|
471 |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
472 try: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
473 r = self._call(cmd, data=fp, headers=headers, **args) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
474 vals = r.split('\n', 1) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
475 if len(vals) < 2: |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
476 raise error.ResponseError(_("unexpected response:"), r) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
477 return vals |
36460
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36456
diff
changeset
|
478 except urlerr.httperror: |
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36456
diff
changeset
|
479 # 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:
36456
diff
changeset
|
480 # like generic socket errors. They lack any values in |
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36456
diff
changeset
|
481 # .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:
36456
diff
changeset
|
482 raise |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
483 except socket.error as err: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
484 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
|
485 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
|
486 raise error.Abort(err.args[1]) |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
487 finally: |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
488 fp.close() |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
489 os.unlink(tempname) |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2435
diff
changeset
|
490 |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
491 def _calltwowaystream(self, cmd, fp, **args): |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
492 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
|
493 fp_ = None |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
494 filename = None |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
495 try: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
496 # dump bundle to disk |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
497 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg") |
36843
5bc7ff103081
py3: use r'' instead of sysstr('') to get around code transformer
Yuya Nishihara <yuya@tcha.org>
parents:
36460
diff
changeset
|
498 fh = os.fdopen(fd, r"wb") |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
499 d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
500 while d: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
501 fh.write(d) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
502 d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
503 fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
504 # 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
|
505 fp_ = httpconnection.httpsendfile(self.ui, filename, "rb") |
36330
a59ff82154b8
httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents:
36303
diff
changeset
|
506 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
|
507 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
|
508 finally: |
23086
cde6904f1992
httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents:
21188
diff
changeset
|
509 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
|
510 fp_.close() |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
511 if fh is not None: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
512 fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
513 os.unlink(filename) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
514 |
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
|
515 def _callcompressable(self, cmd, **args): |
30473
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
516 return self._callstream(cmd, _compressible=True, **args) |
11370 | 517 |
21188
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
518 def _abort(self, exception): |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
519 raise exception |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
520 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
521 def sendv2request(ui, opener, requestbuilder, apiurl, permission, requests): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
522 reactor = wireprotoframing.clientreactor(hasmultiplesend=False, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
523 buffersends=True) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
524 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
525 url = '%s/%s' % (apiurl, permission) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
526 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
527 if len(requests) > 1: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
528 url += '/multirequest' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
529 else: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
530 url += '/%s' % requests[0][0] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
531 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
532 # Request ID to (request, future) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
533 requestmap = {} |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
534 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
535 for command, args, f in requests: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
536 request, action, meta = reactor.callcommand(command, args) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
537 assert action == 'noop' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
538 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
539 requestmap[request.requestid] = (request, f) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
540 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
541 action, meta = reactor.flushcommands() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
542 assert action == 'sendframes' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
543 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
544 # TODO stream this. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
545 body = b''.join(map(bytes, meta['framegen'])) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
546 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
547 # TODO modify user-agent to reflect v2 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
548 headers = { |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
549 r'Accept': wireprotov2server.FRAMINGTYPE, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
550 r'Content-Type': wireprotov2server.FRAMINGTYPE, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
551 } |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
552 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
553 req = requestbuilder(pycompat.strurl(url), body, headers) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
554 req.add_unredirected_header(r'Content-Length', r'%d' % len(body)) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
555 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
556 try: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
557 res = opener.open(req) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
558 except urlerr.httperror as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
559 if e.code == 401: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
560 raise error.Abort(_('authorization failed')) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
561 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
562 raise |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
563 except httplib.HTTPException as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
564 ui.traceback() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
565 raise IOError(None, e) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
566 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
567 return reactor, requestmap, res |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
568 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
569 class queuedcommandfuture(pycompat.futures.Future): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
570 """Wraps result() on command futures to trigger submission on call.""" |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
571 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
572 def result(self, timeout=None): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
573 if self.done(): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
574 return pycompat.futures.Future.result(self, timeout) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
575 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
576 self._peerexecutor.sendcommands() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
577 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
578 # sendcommands() will restore the original __class__ and self.result |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
579 # will resolve to Future.result. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
580 return self.result(timeout) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
581 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
582 @zi.implementer(repository.ipeercommandexecutor) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
583 class httpv2executor(object): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
584 def __init__(self, ui, opener, requestbuilder, apiurl, descriptor): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
585 self._ui = ui |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
586 self._opener = opener |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
587 self._requestbuilder = requestbuilder |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
588 self._apiurl = apiurl |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
589 self._descriptor = descriptor |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
590 self._sent = False |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
591 self._closed = False |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
592 self._neededpermissions = set() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
593 self._calls = [] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
594 self._futures = weakref.WeakSet() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
595 self._responseexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
596 self._responsef = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
597 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
598 def __enter__(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
599 return self |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
600 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
601 def __exit__(self, exctype, excvalue, exctb): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
602 self.close() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
603 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
604 def callcommand(self, command, args): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
605 if self._sent: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
606 raise error.ProgrammingError('callcommand() cannot be used after ' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
607 'commands are sent') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
608 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
609 if self._closed: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
610 raise error.ProgrammingError('callcommand() cannot be used after ' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
611 'close()') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
612 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
613 # The service advertises which commands are available. So if we attempt |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
614 # to call an unknown command or pass an unknown argument, we can screen |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
615 # for this. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
616 if command not in self._descriptor['commands']: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
617 raise error.ProgrammingError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
618 'wire protocol command %s is not available' % command) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
619 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
620 cmdinfo = self._descriptor['commands'][command] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
621 unknownargs = set(args.keys()) - set(cmdinfo.get('args', {})) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
622 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
623 if unknownargs: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
624 raise error.ProgrammingError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
625 'wire protocol command %s does not accept argument: %s' % ( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
626 command, ', '.join(sorted(unknownargs)))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
627 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
628 self._neededpermissions |= set(cmdinfo['permissions']) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
629 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
630 # TODO we /could/ also validate types here, since the API descriptor |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
631 # includes types... |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
632 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
633 f = pycompat.futures.Future() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
634 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
635 # Monkeypatch it so result() triggers sendcommands(), otherwise result() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
636 # could deadlock. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
637 f.__class__ = queuedcommandfuture |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
638 f._peerexecutor = self |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
639 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
640 self._futures.add(f) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
641 self._calls.append((command, args, f)) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
642 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
643 return f |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
644 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
645 def sendcommands(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
646 if self._sent: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
647 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
648 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
649 if not self._calls: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
650 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
651 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
652 self._sent = True |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
653 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
654 # Unhack any future types so caller sees a clean type and so we |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
655 # break reference cycle. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
656 for f in self._futures: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
657 if isinstance(f, queuedcommandfuture): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
658 f.__class__ = pycompat.futures.Future |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
659 f._peerexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
660 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
661 # Mark the future as running and filter out cancelled futures. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
662 calls = [(command, args, f) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
663 for command, args, f in self._calls |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
664 if f.set_running_or_notify_cancel()] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
665 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
666 # Clear out references, prevent improper object usage. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
667 self._calls = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
668 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
669 if not calls: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
670 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
671 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
672 permissions = set(self._neededpermissions) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
673 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
674 if 'push' in permissions and 'pull' in permissions: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
675 permissions.remove('pull') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
676 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
677 if len(permissions) > 1: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
678 raise error.RepoError(_('cannot make request requiring multiple ' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
679 'permissions: %s') % |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
680 _(', ').join(sorted(permissions))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
681 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
682 permission = { |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
683 'push': 'rw', |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
684 'pull': 'ro', |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
685 }[permissions.pop()] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
686 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
687 reactor, requests, resp = sendv2request( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
688 self._ui, self._opener, self._requestbuilder, self._apiurl, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
689 permission, calls) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
690 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
691 # TODO we probably want to validate the HTTP code, media type, etc. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
692 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
693 self._responseexecutor = pycompat.futures.ThreadPoolExecutor(1) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
694 self._responsef = self._responseexecutor.submit(self._handleresponse, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
695 reactor, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
696 requests, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
697 resp) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
698 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
699 def close(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
700 if self._closed: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
701 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
702 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
703 self.sendcommands() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
704 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
705 self._closed = True |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
706 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
707 if not self._responsef: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
708 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
709 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
710 try: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
711 self._responsef.result() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
712 finally: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
713 self._responseexecutor.shutdown(wait=True) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
714 self._responsef = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
715 self._responseexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
716 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
717 # If any of our futures are still in progress, mark them as |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
718 # errored, otherwise a result() could wait indefinitely. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
719 for f in self._futures: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
720 if not f.done(): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
721 f.set_exception(error.ResponseError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
722 _('unfulfilled command response'))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
723 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
724 self._futures = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
725 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
726 def _handleresponse(self, reactor, requests, resp): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
727 # Called in a thread to read the response. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
728 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
729 results = {k: [] for k in requests} |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
730 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
731 while True: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
732 frame = wireprotoframing.readframe(resp) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
733 if frame is None: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
734 break |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
735 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
736 self._ui.note(_('received %r\n') % frame) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
737 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
738 # Guard against receiving a frame with a request ID that we |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
739 # didn't issue. This should never happen. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
740 request, f = requests.get(frame.requestid, [None, None]) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
741 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
742 action, meta = reactor.onframerecv(frame) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
743 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
744 if action == 'responsedata': |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
745 assert request.requestid == meta['request'].requestid |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
746 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
747 result = results[request.requestid] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
748 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
749 if meta['cbor']: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
750 payload = util.bytesio(meta['data']) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
751 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
752 decoder = cbor.CBORDecoder(payload) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
753 while payload.tell() + 1 < len(meta['data']): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
754 try: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
755 result.append(decoder.decode()) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
756 except Exception: |
37669
1cb54e6193a6
py3: paper over differences in future exception handling
Augie Fackler <augie@google.com>
parents:
37654
diff
changeset
|
757 pycompat.future_set_exception_info( |
1cb54e6193a6
py3: paper over differences in future exception handling
Augie Fackler <augie@google.com>
parents:
37654
diff
changeset
|
758 f, sys.exc_info()[1:]) |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
759 continue |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
760 else: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
761 result.append(meta['data']) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
762 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
763 if meta['eos']: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
764 f.set_result(result) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
765 del results[request.requestid] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
766 |
37654
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
767 elif action == 'error': |
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
768 e = error.RepoError(meta['message']) |
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
769 |
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
770 if f: |
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
771 f.set_exception(e) |
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
772 else: |
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
773 raise e |
8cea0d57bf37
httppeer: handle error response from client reactor
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37651
diff
changeset
|
774 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
775 else: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
776 e = error.ProgrammingError('unhandled action: %s' % action) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
777 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
778 if f: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
779 f.set_exception(e) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
780 else: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
781 raise e |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
782 |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
783 # TODO implement interface for version 2 peers |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
784 @zi.implementer(repository.ipeerconnection, repository.ipeercapabilities, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
785 repository.ipeerrequests) |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
786 class httpv2peer(object): |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
787 def __init__(self, ui, repourl, apipath, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
788 apidescriptor): |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
789 self.ui = ui |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
790 |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
791 if repourl.endswith('/'): |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
792 repourl = repourl[:-1] |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
793 |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
794 self._url = repourl |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
795 self._apipath = apipath |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
796 self._apiurl = '%s/%s' % (repourl, apipath) |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
797 self._opener = opener |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
798 self._requestbuilder = requestbuilder |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
799 self._descriptor = apidescriptor |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
800 |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
801 # Start of ipeerconnection. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
802 |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
803 def url(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
804 return self._url |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
805 |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
806 def local(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
807 return None |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
808 |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
809 def peer(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
810 return self |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
811 |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
812 def canpush(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
813 # TODO change once implemented. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
814 return False |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
815 |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
816 def close(self): |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
817 pass |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
818 |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
819 # End of ipeerconnection. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
820 |
37611
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
821 # Start of ipeercapabilities. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
822 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
823 def capable(self, name): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
824 # 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
|
825 # 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
|
826 # version 2 of that command works differently. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
827 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
828 # Maps to commands that are available. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
829 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
|
830 return True |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
831 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
832 # Other concepts. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
833 if name in ('bundle2',): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
834 return True |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
835 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
836 return False |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
837 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
838 def requirecap(self, name, purpose): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
839 if self.capable(name): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
840 return |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
841 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
842 raise error.CapabilityError( |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
843 _('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
|
844 'capability') % (purpose, name)) |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
845 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
846 # End of ipeercapabilities. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
847 |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
848 def _call(self, name, **args): |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
849 with self.commandexecutor() as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
850 return e.callcommand(name, args).result() |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37498
diff
changeset
|
851 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
852 def commandexecutor(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
853 return httpv2executor(self.ui, self._opener, self._requestbuilder, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
854 self._apiurl, self._descriptor) |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
855 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
856 # 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
|
857 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
858 # The following keys are meaningful: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
859 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
860 # init |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
861 # Callable receiving (ui, repourl, servicepath, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
862 # apidescriptor) to create a peer. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
863 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
864 # priority |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
865 # 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
|
866 # services, we choose the one with the highest priority. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
867 API_PEERS = { |
37644
77c9ee77687c
wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37614
diff
changeset
|
868 wireprototypes.HTTP_WIREPROTO_V2: { |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
869 'init': httpv2peer, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
870 'priority': 50, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
871 }, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
872 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
873 |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
874 def performhandshake(ui, url, opener, requestbuilder): |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
875 # 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
|
876 |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
877 caps = None |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
878 def capable(x): |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
879 raise error.ProgrammingError('should not be called') |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
880 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
881 args = {} |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
882 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
883 # 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
|
884 # 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
|
885 # X-HgProto-* header advertising which serializing formats it supports. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
886 # 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
|
887 # now. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
888 advertisev2 = ui.configbool('experimental', 'httppeer.advertise-v2') |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
889 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
890 if advertisev2: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
891 args['headers'] = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
892 r'X-HgProto-1': r'cbor', |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
893 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
894 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
895 args['headers'].update( |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
896 encodevalueinheaders(' '.join(sorted(API_PEERS)), |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
897 'X-HgUpgrade', |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
898 # We don't know the header limit this early. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
899 # So make it small. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
900 1024)) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
901 |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
902 req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps, |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
903 capable, url, 'capabilities', |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
904 args) |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
905 |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
906 resp = sendrequest(ui, opener, req) |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
907 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
908 respurl, ct, resp = parsev1commandresponse(ui, url, requrl, qs, resp, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
909 compressible=False, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
910 allowcbor=advertisev2) |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
911 |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
912 try: |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
913 rawdata = resp.read() |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
914 finally: |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
915 resp.close() |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
916 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
917 if not ct.startswith('application/mercurial-'): |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
918 raise error.ProgrammingError('unexpected content-type: %s' % ct) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
919 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
920 if advertisev2: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
921 if ct == 'application/mercurial-cbor': |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
922 try: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
923 info = cbor.loads(rawdata) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
924 except cbor.CBORDecodeError: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
925 raise error.Abort(_('error decoding CBOR from remote server'), |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
926 hint=_('try again and consider contacting ' |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
927 'the server operator')) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
928 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
929 # We got a legacy response. That's fine. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
930 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
|
931 info = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
932 'v1capabilities': set(rawdata.split()) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
933 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
934 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
935 else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
936 raise error.RepoError( |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
937 _('unexpected response type from server: %s') % ct) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
938 else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
939 info = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
940 'v1capabilities': set(rawdata.split()) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
941 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
942 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
943 return respurl, info |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
944 |
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
945 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
|
946 """Construct an appropriate HTTP peer instance. |
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
947 |
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
948 ``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
|
949 connections, perform HTTP requests. |
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
950 |
37547
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
951 ``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
|
952 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
|
953 """ |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
954 u = util.url(path) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
955 if u.query or u.fragment: |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
956 raise error.Abort(_('unsupported URL component: "%s"') % |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
957 (u.query or u.fragment)) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
958 |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
959 # urllib cannot handle URLs with embedded user or passwd. |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
960 url, authinfo = u.authinfo() |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
961 ui.debug('using %s\n' % url) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
962 |
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
963 opener = opener or urlmod.opener(ui, authinfo) |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
964 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
965 respurl, info = performhandshake(ui, url, opener, requestbuilder) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
966 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
967 # 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
|
968 # 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
|
969 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
970 # 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
|
971 # 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
|
972 # 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
|
973 # capabilities, we could filter out services not meeting the |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
974 # requirements. Possibly by consulting the interfaces defined by the |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
975 # peer type. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
976 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
|
977 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
978 preferredchoices = sorted(apipeerchoices, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
979 key=lambda x: API_PEERS[x]['priority'], |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
980 reverse=True) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
981 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
982 for service in preferredchoices: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
983 apipath = '%s/%s' % (info['apibase'].rstrip('/'), service) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
984 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
985 return API_PEERS[service]['init'](ui, respurl, apipath, opener, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
986 requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
987 info['apis'][service]) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
988 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
989 # 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
|
990 return httppeer(ui, path, respurl, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
991 info['v1capabilities']) |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
992 |
2740
386f04d6ecb3
clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2673
diff
changeset
|
993 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
|
994 if create: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
995 raise error.Abort(_('cannot create new http repository')) |
7211 | 996 try: |
36965
43815d87c6aa
httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36843
diff
changeset
|
997 if path.startswith('https:') and not urlmod.has_https: |
36258
874209855f5c
httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36257
diff
changeset
|
998 raise error.Abort(_('Python support for SSL and HTTPS ' |
874209855f5c
httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36257
diff
changeset
|
999 'is not installed')) |
35924
197d10e157ce
httppeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35698
diff
changeset
|
1000 |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
1001 inst = makepeer(ui, path) |
35924
197d10e157ce
httppeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35698
diff
changeset
|
1002 |
7211 | 1003 return inst |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
1004 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
|
1005 try: |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
1006 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
|
1007 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
|
1008 return r |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
1009 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
|
1010 raise httpexception # use the original http RepoError instead |