author | Gregory Szorc <gregory.szorc@gmail.com> |
Sat, 12 May 2018 10:50:30 -0700 | |
changeset 38053 | 6f5b4ceea95b |
parent 37832 | 6169d95dce3b |
child 37842 | f9dc1d5b676b |
child 38197 | aac4be30e250 |
permissions | -rw-r--r-- |
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 |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
16 |
import tempfile |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
17 |
import weakref |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
18 |
|
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
19 |
from .i18n import _ |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
20 |
from .thirdparty import ( |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
21 |
cbor, |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
22 |
) |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
23 |
from . import ( |
28666
ae53ecc47414
bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
28530
diff
changeset
|
24 |
bundle2, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
25 |
error, |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
26 |
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
|
27 |
pycompat, |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
28 |
repository, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
29 |
statichttprepo, |
36965
43815d87c6aa
httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36843
diff
changeset
|
30 |
url as urlmod, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
31 |
util, |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
32 |
wireprotoframing, |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
33 |
wireprototypes, |
37614
a81d02ea65db
wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37611
diff
changeset
|
34 |
wireprotov1peer, |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
35 |
wireprotov2peer, |
37545
93397c4633f6
wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37544
diff
changeset
|
36 |
wireprotov2server, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
37 |
) |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
38 |
from .utils import ( |
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
39 |
interfaceutil, |
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
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 |
|
37738
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
267 |
def _reqdata(req): |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
268 |
"""Get request data, if any. If no data, returns None.""" |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
269 |
if pycompat.ispy3: |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
270 |
return req.data |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
271 |
if not req.has_data(): |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
272 |
return None |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
273 |
return req.get_data() |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
274 |
|
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
275 |
def sendrequest(ui, opener, req): |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
276 |
"""Send a prepared HTTP request. |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
277 |
|
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
278 |
Returns the response object. |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
279 |
""" |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
280 |
if (ui.debugflag |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
281 |
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
|
282 |
dbg = ui.debug |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
283 |
line = 'devel-peer-request: %s\n' |
37736
e10b695b9c41
httppeer: fix debug prints to work on Python 3
Augie Fackler <augie@google.com>
parents:
37719
diff
changeset
|
284 |
dbg(line % '%s %s' % (pycompat.bytesurl(req.get_method()), |
e10b695b9c41
httppeer: fix debug prints to work on Python 3
Augie Fackler <augie@google.com>
parents:
37719
diff
changeset
|
285 |
pycompat.bytesurl(req.get_full_url()))) |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
286 |
hgargssize = None |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
287 |
|
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
288 |
for header, value in sorted(req.header_items()): |
37737
6cb7e3b91883
httppeer: no matter what Python 3 might think, http headers are bytes
Augie Fackler <augie@google.com>
parents:
37736
diff
changeset
|
289 |
header = pycompat.bytesurl(header) |
6cb7e3b91883
httppeer: no matter what Python 3 might think, http headers are bytes
Augie Fackler <augie@google.com>
parents:
37736
diff
changeset
|
290 |
value = pycompat.bytesurl(value) |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
291 |
if header.startswith('X-hgarg-'): |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
292 |
if hgargssize is None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
293 |
hgargssize = 0 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
294 |
hgargssize += len(value) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
295 |
else: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
296 |
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
|
297 |
|
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
298 |
if hgargssize is not None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
299 |
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
|
300 |
% hgargssize) |
37738
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
301 |
data = _reqdata(req) |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
302 |
if data is not None: |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
303 |
length = getattr(data, 'length', None) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
304 |
if length is None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
305 |
length = len(data) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
306 |
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
|
307 |
|
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
308 |
start = util.timer() |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
309 |
|
37550
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
310 |
try: |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
311 |
res = opener.open(req) |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
312 |
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
|
313 |
if inst.code == 401: |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
314 |
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
|
315 |
raise |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
316 |
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
|
317 |
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
|
318 |
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
|
319 |
ui.traceback() |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
320 |
raise IOError(None, inst) |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
321 |
finally: |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
322 |
if ui.configbool('devel', 'debug.peer-request'): |
37736
e10b695b9c41
httppeer: fix debug prints to work on Python 3
Augie Fackler <augie@google.com>
parents:
37719
diff
changeset
|
323 |
dbg(line % ' finished in %.4f seconds (%d)' |
37550
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
324 |
% (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
|
325 |
|
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
326 |
# 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
|
327 |
_wraphttpresponse(res) |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
328 |
|
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
329 |
return res |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
330 |
|
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
331 |
class RedirectedRepoError(error.RepoError): |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
332 |
def __init__(self, msg, respurl): |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
333 |
super(RedirectedRepoError, self).__init__(msg) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
334 |
self.respurl = respurl |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
335 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
336 |
def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
337 |
allowcbor=False): |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
338 |
# record the url we got redirected to |
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
339 |
redirected = False |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
340 |
respurl = pycompat.bytesurl(resp.geturl()) |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
341 |
if respurl.endswith(qs): |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
342 |
respurl = respurl[:-len(qs)] |
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
343 |
qsdropped = False |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
344 |
else: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
345 |
qsdropped = True |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
346 |
|
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
347 |
if baseurl.rstrip('/') != respurl.rstrip('/'): |
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
348 |
redirected = True |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
349 |
if not ui.quiet: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
350 |
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
|
351 |
|
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
352 |
try: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
353 |
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
|
354 |
except AttributeError: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
355 |
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
|
356 |
|
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
357 |
safeurl = util.hidepassword(baseurl) |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
358 |
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
|
359 |
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
|
360 |
|
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
361 |
# 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
|
362 |
# 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
|
363 |
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
|
364 |
ui.debug("requested URL: '%s'\n" % util.hidepassword(requrl)) |
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
365 |
msg = _("'%s' does not appear to be an hg repository:\n" |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
366 |
"---%%<--- (%s)\n%s\n---%%<---\n") % ( |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
367 |
safeurl, proto or 'no content-type', resp.read(1024)) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
368 |
|
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
369 |
# Some servers may strip the query string from the redirect. We |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
370 |
# raise a special error type so callers can react to this specially. |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
371 |
if redirected and qsdropped: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
372 |
raise RedirectedRepoError(msg, respurl) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
373 |
else: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
374 |
raise error.RepoError(msg) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
375 |
|
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
376 |
try: |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
377 |
subtype = proto.split('-', 1)[1] |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
378 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
379 |
# 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
|
380 |
# this should ONLY be encountered for the initial capabilities |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
381 |
# request during handshake. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
382 |
if subtype == 'cbor': |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
383 |
if allowcbor: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
384 |
return respurl, proto, resp |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
385 |
else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
386 |
raise error.RepoError(_('unexpected CBOR response from ' |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
387 |
'server')) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
388 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
389 |
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
|
390 |
except ValueError: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
391 |
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
|
392 |
"header (%s)") % (safeurl, proto)) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
393 |
|
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
394 |
# 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
|
395 |
# generators. |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
396 |
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
|
397 |
if compressible: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
398 |
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
|
399 |
|
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
400 |
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
|
401 |
# 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
|
402 |
# 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
|
403 |
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
|
404 |
ename = resp.read(elen) |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
405 |
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
|
406 |
|
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
407 |
resp = engine.decompressorreader(resp) |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
408 |
else: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
409 |
raise error.RepoError(_("'%s' uses newer protocol %s") % |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
410 |
(safeurl, subtype)) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
411 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
412 |
return respurl, proto, resp |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
413 |
|
37614
a81d02ea65db
wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37611
diff
changeset
|
414 |
class httppeer(wireprotov1peer.wirepeer): |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
415 |
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
|
416 |
self.ui = ui |
33731
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33730
diff
changeset
|
417 |
self._path = path |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
418 |
self._url = url |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
419 |
self._caps = caps |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
420 |
self._urlopener = opener |
37547
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
421 |
self._requestbuilder = requestbuilder |
4516
96d8a56d4ef9
Removed trailing whitespace and tabs from python files
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4369
diff
changeset
|
422 |
|
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
423 |
def __del__(self): |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
424 |
for h in self._urlopener.handlers: |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
425 |
h.close() |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
426 |
getattr(h, "close_all", lambda: None)() |
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
427 |
|
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
428 |
# Begin of ipeerconnection interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
429 |
|
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
430 |
def url(self): |
33731
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33730
diff
changeset
|
431 |
return self._path |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
432 |
|
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
433 |
def local(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
434 |
return None |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
435 |
|
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
436 |
def peer(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
437 |
return self |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
438 |
|
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
439 |
def canpush(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
440 |
return True |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
441 |
|
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
442 |
def close(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
443 |
pass |
13603
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
444 |
|
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
445 |
# End of ipeerconnection interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
446 |
|
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
447 |
# Begin of ipeercommands interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
448 |
|
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
449 |
def capabilities(self): |
33731
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33730
diff
changeset
|
450 |
return self._caps |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
451 |
|
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37009
diff
changeset
|
452 |
# End of ipeercommands interface. |
33826
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33731
diff
changeset
|
453 |
|
30473
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
454 |
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
|
455 |
args = pycompat.byteskwargs(args) |
36256
e4ccd7a69f77
httppeer: change logic around argument handling
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35924
diff
changeset
|
456 |
|
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
457 |
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
|
458 |
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
|
459 |
self._url, cmd, args) |
30763
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
460 |
|
37550
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
461 |
resp = sendrequest(self.ui, self._urlopener, req) |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30944
diff
changeset
|
462 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
463 |
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
|
464 |
resp, _compressible) |
30473
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
465 |
|
752 | 466 |
return resp |
60 | 467 |
|
11589
e8d22fe2ddab
protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents:
11588
diff
changeset
|
468 |
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
|
469 |
fp = self._callstream(cmd, **args) |
2435
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
470 |
try: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
471 |
return fp.read() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
472 |
finally: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
473 |
# if using keepalive, allow connection to be reused |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
474 |
fp.close() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
475 |
|
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
476 |
def _callpush(self, cmd, cg, **args): |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
477 |
# 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
|
478 |
# http 1.1 chunked transfer. |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
479 |
|
3662
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3661
diff
changeset
|
480 |
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
|
481 |
try: |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
482 |
types = types.split(',') |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
483 |
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
|
484 |
# 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
|
485 |
# 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
|
486 |
# bundles. |
3703
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
487 |
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
|
488 |
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
|
489 |
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
|
490 |
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
|
491 |
break |
3613
cbf352b9a3cd
Client support for hgweb unbundle with versions.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3609
diff
changeset
|
492 |
|
28666
ae53ecc47414
bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
28530
diff
changeset
|
493 |
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
|
494 |
fp = httpconnection.httpsendfile(self.ui, tempname, "rb") |
36330
a59ff82154b8
httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents:
36303
diff
changeset
|
495 |
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
|
496 |
|
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
497 |
try: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
498 |
r = self._call(cmd, data=fp, headers=headers, **args) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
499 |
vals = r.split('\n', 1) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
500 |
if len(vals) < 2: |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
501 |
raise error.ResponseError(_("unexpected response:"), r) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
502 |
return vals |
36460
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36456
diff
changeset
|
503 |
except urlerr.httperror: |
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36456
diff
changeset
|
504 |
# 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
|
505 |
# 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
|
506 |
# .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
|
507 |
raise |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
508 |
except socket.error as err: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
509 |
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
|
510 |
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
|
511 |
raise error.Abort(err.args[1]) |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
512 |
finally: |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
513 |
fp.close() |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
514 |
os.unlink(tempname) |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2435
diff
changeset
|
515 |
|
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
516 |
def _calltwowaystream(self, cmd, fp, **args): |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
517 |
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
|
518 |
fp_ = None |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
519 |
filename = None |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
520 |
try: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
521 |
# dump bundle to disk |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
522 |
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
|
523 |
fh = os.fdopen(fd, r"wb") |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
524 |
d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
525 |
while d: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
526 |
fh.write(d) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
527 |
d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
528 |
fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
529 |
# 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
|
530 |
fp_ = httpconnection.httpsendfile(self.ui, filename, "rb") |
36330
a59ff82154b8
httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents:
36303
diff
changeset
|
531 |
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
|
532 |
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
|
533 |
finally: |
23086
cde6904f1992
httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents:
21188
diff
changeset
|
534 |
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
|
535 |
fp_.close() |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
536 |
if fh is not None: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
537 |
fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
538 |
os.unlink(filename) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
539 |
|
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
|
540 |
def _callcompressable(self, cmd, **args): |
30473
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
541 |
return self._callstream(cmd, _compressible=True, **args) |
11370 | 542 |
|
21188
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
543 |
def _abort(self, exception): |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
544 |
raise exception |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
545 |
|
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
546 |
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
|
547 |
reactor = wireprotoframing.clientreactor(hasmultiplesend=False, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
548 |
buffersends=True) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
549 |
|
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
550 |
handler = wireprotov2peer.clienthandler(ui, reactor) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
551 |
|
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
552 |
url = '%s/%s' % (apiurl, permission) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
553 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
554 |
if len(requests) > 1: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
555 |
url += '/multirequest' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
556 |
else: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
557 |
url += '/%s' % requests[0][0] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
558 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
559 |
for command, args, f in requests: |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
560 |
assert not list(handler.callcommand(command, args, f)) |
37651
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 |
# TODO stream this. |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
563 |
body = b''.join(map(bytes, handler.flushcommands())) |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
564 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
565 |
# 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
|
566 |
headers = { |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
567 |
r'Accept': wireprotov2server.FRAMINGTYPE, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
568 |
r'Content-Type': wireprotov2server.FRAMINGTYPE, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
569 |
} |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
570 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
571 |
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
|
572 |
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
|
573 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
574 |
try: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
575 |
res = opener.open(req) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
576 |
except urlerr.httperror as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
577 |
if e.code == 401: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
578 |
raise error.Abort(_('authorization failed')) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
579 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
580 |
raise |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
581 |
except httplib.HTTPException as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
582 |
ui.traceback() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
583 |
raise IOError(None, e) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
584 |
|
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
585 |
return handler, res |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
586 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
587 |
class queuedcommandfuture(pycompat.futures.Future): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
588 |
"""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
|
589 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
590 |
def result(self, timeout=None): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
591 |
if self.done(): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
592 |
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
|
593 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
594 |
self._peerexecutor.sendcommands() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
595 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
596 |
# 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
|
597 |
# will resolve to Future.result. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
598 |
return self.result(timeout) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
599 |
|
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
600 |
@interfaceutil.implementer(repository.ipeercommandexecutor) |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
601 |
class httpv2executor(object): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
602 |
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
|
603 |
self._ui = ui |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
604 |
self._opener = opener |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
605 |
self._requestbuilder = requestbuilder |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
606 |
self._apiurl = apiurl |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
607 |
self._descriptor = descriptor |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
608 |
self._sent = False |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
609 |
self._closed = False |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
610 |
self._neededpermissions = set() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
611 |
self._calls = [] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
612 |
self._futures = weakref.WeakSet() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
613 |
self._responseexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
614 |
self._responsef = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
615 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
616 |
def __enter__(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
617 |
return self |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
618 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
619 |
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
|
620 |
self.close() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
621 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
622 |
def callcommand(self, command, args): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
623 |
if self._sent: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
624 |
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
|
625 |
'commands are sent') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
626 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
627 |
if self._closed: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
628 |
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
|
629 |
'close()') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
630 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
631 |
# 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
|
632 |
# 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
|
633 |
# for this. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
634 |
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
|
635 |
raise error.ProgrammingError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
636 |
'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
|
637 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
638 |
cmdinfo = self._descriptor['commands'][command] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
639 |
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
|
640 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
641 |
if unknownargs: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
642 |
raise error.ProgrammingError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
643 |
'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
|
644 |
command, ', '.join(sorted(unknownargs)))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
645 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
646 |
self._neededpermissions |= set(cmdinfo['permissions']) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
647 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
648 |
# 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
|
649 |
# includes types... |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
650 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
651 |
f = pycompat.futures.Future() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
652 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
653 |
# 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
|
654 |
# could deadlock. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
655 |
f.__class__ = queuedcommandfuture |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
656 |
f._peerexecutor = self |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
657 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
658 |
self._futures.add(f) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
659 |
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
|
660 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
661 |
return f |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
662 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
663 |
def sendcommands(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
664 |
if self._sent: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
665 |
return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
666 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
667 |
if not self._calls: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
668 |
return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
669 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
670 |
self._sent = True |
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 |
# 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
|
673 |
# break reference cycle. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
674 |
for f in self._futures: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
675 |
if isinstance(f, queuedcommandfuture): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
676 |
f.__class__ = pycompat.futures.Future |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
677 |
f._peerexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
678 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
679 |
# 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
|
680 |
calls = [(command, args, f) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
681 |
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
|
682 |
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
|
683 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
684 |
# 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
|
685 |
self._calls = None |
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 |
if not calls: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
688 |
return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
689 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
690 |
permissions = set(self._neededpermissions) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
691 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
692 |
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
|
693 |
permissions.remove('pull') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
694 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
695 |
if len(permissions) > 1: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
696 |
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
|
697 |
'permissions: %s') % |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
698 |
_(', ').join(sorted(permissions))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
699 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
700 |
permission = { |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
701 |
'push': 'rw', |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
702 |
'pull': 'ro', |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
703 |
}[permissions.pop()] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
704 |
|
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
705 |
handler, resp = sendv2request( |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
706 |
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
|
707 |
permission, calls) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
708 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
709 |
# 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
|
710 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
711 |
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
|
712 |
self._responsef = self._responseexecutor.submit(self._handleresponse, |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
713 |
handler, resp) |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
714 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
715 |
def close(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
716 |
if self._closed: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
717 |
return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
718 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
719 |
self.sendcommands() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
720 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
721 |
self._closed = True |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
722 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
723 |
if not self._responsef: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
724 |
return |
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 |
try: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
727 |
self._responsef.result() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
728 |
finally: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
729 |
self._responseexecutor.shutdown(wait=True) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
730 |
self._responsef = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
731 |
self._responseexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
732 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
733 |
# 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
|
734 |
# 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
|
735 |
for f in self._futures: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
736 |
if not f.done(): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
737 |
f.set_exception(error.ResponseError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
738 |
_('unfulfilled command response'))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
739 |
|
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
740 |
self._futures = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
741 |
|
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
742 |
def _handleresponse(self, handler, resp): |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
743 |
# 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
|
744 |
|
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
745 |
while handler.readframe(resp): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
746 |
pass |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
747 |
|
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
748 |
# TODO implement interface for version 2 peers |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
749 |
@interfaceutil.implementer(repository.ipeerconnection, |
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
750 |
repository.ipeercapabilities, |
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
751 |
repository.ipeerrequests) |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
752 |
class httpv2peer(object): |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
753 |
def __init__(self, ui, repourl, apipath, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
754 |
apidescriptor): |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
755 |
self.ui = ui |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
756 |
|
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
757 |
if repourl.endswith('/'): |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
758 |
repourl = repourl[:-1] |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
759 |
|
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
760 |
self._url = repourl |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
761 |
self._apipath = apipath |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
762 |
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
|
763 |
self._opener = opener |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
764 |
self._requestbuilder = requestbuilder |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
765 |
self._descriptor = apidescriptor |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
766 |
|
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
767 |
# Start of ipeerconnection. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
768 |
|
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
769 |
def url(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
770 |
return self._url |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
771 |
|
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
772 |
def local(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
773 |
return None |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
774 |
|
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
775 |
def peer(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
776 |
return self |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
777 |
|
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
778 |
def canpush(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
779 |
# TODO change once implemented. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
780 |
return False |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
781 |
|
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
782 |
def close(self): |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
783 |
pass |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
784 |
|
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
785 |
# End of ipeerconnection. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
786 |
|
37611
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
787 |
# Start of ipeercapabilities. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
788 |
|
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
789 |
def capable(self, name): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
790 |
# 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
|
791 |
# 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
|
792 |
# version 2 of that command works differently. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
793 |
|
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
794 |
# Maps to commands that are available. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
795 |
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
|
796 |
return True |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
797 |
|
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
798 |
# Other concepts. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
799 |
if name in ('bundle2',): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
800 |
return True |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
801 |
|
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
802 |
return False |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
803 |
|
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
804 |
def requirecap(self, name, purpose): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
805 |
if self.capable(name): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
806 |
return |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
807 |
|
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
808 |
raise error.CapabilityError( |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
809 |
_('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
|
810 |
'capability') % (purpose, name)) |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
811 |
|
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
812 |
# End of ipeercapabilities. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
813 |
|
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
814 |
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
|
815 |
with self.commandexecutor() as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
816 |
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
|
817 |
|
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
818 |
def commandexecutor(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
819 |
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
|
820 |
self._apiurl, self._descriptor) |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
821 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
822 |
# 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
|
823 |
# |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
824 |
# The following keys are meaningful: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
825 |
# |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
826 |
# init |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
827 |
# Callable receiving (ui, repourl, servicepath, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
828 |
# apidescriptor) to create a peer. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
829 |
# |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
830 |
# priority |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
831 |
# 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
|
832 |
# services, we choose the one with the highest priority. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
833 |
API_PEERS = { |
37644
77c9ee77687c
wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37614
diff
changeset
|
834 |
wireprototypes.HTTP_WIREPROTO_V2: { |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
835 |
'init': httpv2peer, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
836 |
'priority': 50, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
837 |
}, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
838 |
} |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
839 |
|
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
840 |
def performhandshake(ui, url, opener, requestbuilder): |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
841 |
# 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
|
842 |
|
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
843 |
caps = None |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
844 |
def capable(x): |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
845 |
raise error.ProgrammingError('should not be called') |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
846 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
847 |
args = {} |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
848 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
849 |
# 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
|
850 |
# 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
|
851 |
# X-HgProto-* header advertising which serializing formats it supports. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
852 |
# 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
|
853 |
# now. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
854 |
advertisev2 = ui.configbool('experimental', 'httppeer.advertise-v2') |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
855 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
856 |
if advertisev2: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
857 |
args['headers'] = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
858 |
r'X-HgProto-1': r'cbor', |
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 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
861 |
args['headers'].update( |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
862 |
encodevalueinheaders(' '.join(sorted(API_PEERS)), |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
863 |
'X-HgUpgrade', |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
864 |
# We don't know the header limit this early. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
865 |
# So make it small. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
866 |
1024)) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
867 |
|
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
868 |
req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps, |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
869 |
capable, url, 'capabilities', |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
870 |
args) |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
871 |
resp = sendrequest(ui, opener, req) |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
872 |
|
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
873 |
# The server may redirect us to the repo root, stripping the |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
874 |
# ?cmd=capabilities query string from the URL. The server would likely |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
875 |
# return HTML in this case and ``parsev1commandresponse()`` would raise. |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
876 |
# We catch this special case and re-issue the capabilities request against |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
877 |
# the new URL. |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
878 |
# |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
879 |
# We should ideally not do this, as a redirect that drops the query |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
880 |
# string from the URL is arguably a server bug. (Garbage in, garbage out). |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
881 |
# However, Mercurial clients for several years appeared to handle this |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
882 |
# issue without behavior degradation. And according to issue 5860, it may |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
883 |
# be a longstanding bug in some server implementations. So we allow a |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
884 |
# redirect that drops the query string to "just work." |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
885 |
try: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
886 |
respurl, ct, resp = parsev1commandresponse(ui, url, requrl, qs, resp, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
887 |
compressible=False, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
888 |
allowcbor=advertisev2) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
889 |
except RedirectedRepoError as e: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
890 |
req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
891 |
capable, e.respurl, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
892 |
'capabilities', args) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
893 |
resp = sendrequest(ui, opener, req) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
894 |
respurl, ct, resp = parsev1commandresponse(ui, url, requrl, qs, resp, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
895 |
compressible=False, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
896 |
allowcbor=advertisev2) |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
897 |
|
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
898 |
try: |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
899 |
rawdata = resp.read() |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
900 |
finally: |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
901 |
resp.close() |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
902 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
903 |
if not ct.startswith('application/mercurial-'): |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
904 |
raise error.ProgrammingError('unexpected content-type: %s' % ct) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
905 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
906 |
if advertisev2: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
907 |
if ct == 'application/mercurial-cbor': |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
908 |
try: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
909 |
info = cbor.loads(rawdata) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
910 |
except cbor.CBORDecodeError: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
911 |
raise error.Abort(_('error decoding CBOR from remote server'), |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
912 |
hint=_('try again and consider contacting ' |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
913 |
'the server operator')) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
914 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
915 |
# We got a legacy response. That's fine. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
916 |
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
|
917 |
info = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
918 |
'v1capabilities': set(rawdata.split()) |
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 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
921 |
else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
922 |
raise error.RepoError( |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
923 |
_('unexpected response type from server: %s') % ct) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
924 |
else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
925 |
info = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
926 |
'v1capabilities': set(rawdata.split()) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
927 |
} |
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 |
return respurl, info |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
930 |
|
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
931 |
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
|
932 |
"""Construct an appropriate HTTP peer instance. |
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
933 |
|
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
934 |
``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
|
935 |
connections, perform HTTP requests. |
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
936 |
|
37547
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
937 |
``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
|
938 |
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
|
939 |
""" |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
940 |
u = util.url(path) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
941 |
if u.query or u.fragment: |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
942 |
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
|
943 |
(u.query or u.fragment)) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
944 |
|
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
945 |
# 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
|
946 |
url, authinfo = u.authinfo() |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
947 |
ui.debug('using %s\n' % url) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
948 |
|
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
949 |
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
|
950 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
951 |
respurl, info = performhandshake(ui, url, opener, requestbuilder) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
952 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
953 |
# 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
|
954 |
# 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
|
955 |
# |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
956 |
# 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
|
957 |
# 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
|
958 |
# 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
|
959 |
# capabilities, we could filter out services not meeting the |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
960 |
# requirements. Possibly by consulting the interfaces defined by the |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
961 |
# peer type. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
962 |
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
|
963 |
|
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
964 |
preferredchoices = sorted(apipeerchoices, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
965 |
key=lambda x: API_PEERS[x]['priority'], |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
966 |
reverse=True) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
967 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
968 |
for service in preferredchoices: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
969 |
apipath = '%s/%s' % (info['apibase'].rstrip('/'), service) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
970 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
971 |
return API_PEERS[service]['init'](ui, respurl, apipath, opener, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
972 |
requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
973 |
info['apis'][service]) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
974 |
|
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
975 |
# 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
|
976 |
return httppeer(ui, path, respurl, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
977 |
info['v1capabilities']) |
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
978 |
|
37717
0664be4f0c1f
hg: pass command intents to repo/peer creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37669
diff
changeset
|
979 |
def instance(ui, path, create, intents=None): |
2740
386f04d6ecb3
clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2673
diff
changeset
|
980 |
if create: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
981 |
raise error.Abort(_('cannot create new http repository')) |
7211 | 982 |
try: |
36965
43815d87c6aa
httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36843
diff
changeset
|
983 |
if path.startswith('https:') and not urlmod.has_https: |
36258
874209855f5c
httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36257
diff
changeset
|
984 |
raise error.Abort(_('Python support for SSL and HTTPS ' |
874209855f5c
httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36257
diff
changeset
|
985 |
'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
|
986 |
|
37009
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36967
diff
changeset
|
987 |
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
|
988 |
|
7211 | 989 |
return inst |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
990 |
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
|
991 |
try: |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
992 |
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
|
993 |
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
|
994 |
return r |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
995 |
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
|
996 |
raise httpexception # use the original http RepoError instead |