Mercurial > hg
annotate mercurial/httppeer.py @ 39629:a86d21e70b2b
exchangev2: start to implement pull with wire protocol v2
Wire protocol version 2 will take a substantially different
approach to exchange than version 1 (at least as far as pulling
is concerned).
This commit establishes a new exchangev2 module for holding
code related to exchange using wire protocol v2. I could have
added things to the existing exchange module. But it is already
quite big. And doing things inline isn't in question because
the existing code is already littered with conditional code
for various states of support for the existing wire protocol
as it evolved over 10+ years. A new module gives us a chance
to make a clean break.
This approach does mean we'll end up writing some duplicate
code. And there's a significant chance we'll miss functionality
as code is ported. The plan is to eventually add #testcase's
to existing tests so the new wire protocol is tested side-by-side
with the existing one. This will hopefully tease out any
features that weren't ported properly. But before we get there,
we need to build up support for the new exchange methods.
Our journey towards implementing a new exchange begins with pulling.
And pulling begins with discovery.
The discovery code added to exchangev2 is heavily drawn from
the following functions:
* exchange._pulldiscoverychangegroup
* discovery.findcommonincoming
For now, we build on top of existing discovery mechanisms. The
new wire protocol should be capable of doing things more efficiently.
But I'd rather defer on this problem.
To foster the transition, we invent a fake capability on the HTTPv2
peer and have the main pull code in exchange.py call into exchangev2
when the new wire protocol is being used.
Differential Revision: https://phab.mercurial-scm.org/D4480
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 12 Sep 2018 09:58:23 -0700 |
parents | a5de21c9e370 |
children | 9c2c77c73f23 |
rev | line source |
---|---|
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
15246
diff
changeset
|
1 # httppeer.py - HTTP repository proxy classes for mercurial |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
2 # |
2859 | 3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
5 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8206
diff
changeset
|
6 # This software may be used and distributed according to the terms of the |
10263 | 7 # GNU General Public License version 2 or any later version. |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
8 |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
9 from __future__ import absolute_import |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
10 |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
11 import errno |
33821
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
12 import io |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
13 import os |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
14 import socket |
30763
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
15 import struct |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
16 import weakref |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
17 |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
18 from .i18n import _ |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
19 from . import ( |
28666
ae53ecc47414
bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
28530
diff
changeset
|
20 bundle2, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
21 error, |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
22 httpconnection, |
30924
48dea083f66d
py3: convert the mode argument of os.fdopen to unicodes (1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30763
diff
changeset
|
23 pycompat, |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
24 repository, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
25 statichttprepo, |
36959
43815d87c6aa
httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36835
diff
changeset
|
26 url as urlmod, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
27 util, |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
28 wireprotoframing, |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
29 wireprototypes, |
37614
a81d02ea65db
wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37611
diff
changeset
|
30 wireprotov1peer, |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
31 wireprotov2peer, |
37545
93397c4633f6
wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37544
diff
changeset
|
32 wireprotov2server, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
33 ) |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
34 from .utils import ( |
39445
cdb56f295b03
httppeer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39437
diff
changeset
|
35 cborutil, |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
36 interfaceutil, |
39436
3fe028b657bf
httppeer: log commands for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
38783
diff
changeset
|
37 stringutil, |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
38 ) |
4678
a814a5b11fff
Work around urllib2 digest auth bug with Python < 2.5
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4633
diff
changeset
|
39 |
29455
0c741fd6158a
py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29241
diff
changeset
|
40 httplib = util.httplib |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
41 urlerr = util.urlerr |
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
42 urlreq = util.urlreq |
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
43 |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
44 def encodevalueinheaders(value, header, limit): |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
45 """Encode a string value into multiple HTTP headers. |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
46 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
47 ``value`` will be encoded into 1 or more HTTP headers with the names |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
48 ``header-<N>`` where ``<N>`` is an integer starting at 1. Each header |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
49 name + value will be at most ``limit`` bytes long. |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
50 |
34732
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
51 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
|
52 values as native strings. |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
53 """ |
34732
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
54 # 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
|
55 # 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
|
56 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
|
57 # 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
|
58 # 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
|
59 # 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
|
60 # 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
|
61 # instead of a carriage return. |
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
62 valuelen = limit - len(fmt % r'000') - len(': \r\n') |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
63 result = [] |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
64 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
65 n = 0 |
38783
e7aa113b14f7
global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
38502
diff
changeset
|
66 for i in pycompat.xrange(0, len(value), valuelen): |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
67 n += 1 |
34732
67e9678efd98
httppeer: always produce native str header keys and values
Augie Fackler <augie@google.com>
parents:
34725
diff
changeset
|
68 result.append((fmt % str(n), pycompat.strurl(value[i:i + valuelen]))) |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
69 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
70 return result |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
71 |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
72 def _wraphttpresponse(resp): |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
73 """Wrap an HTTPResponse with common error handlers. |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
74 |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
75 This ensures that any I/O from any consumer raises the appropriate |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
76 error and messaging. |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
77 """ |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
78 origread = resp.read |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
79 |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
80 class readerproxy(resp.__class__): |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
81 def read(self, size=None): |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
82 try: |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
83 return origread(size) |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
84 except httplib.IncompleteRead as e: |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
85 # e.expected is an integer if length known or None otherwise. |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
86 if e.expected: |
39483
1fc39367eafd
httppeer: calculate total expected bytes correctly
Anton Shestakov <av6@dwimlabs.net>
parents:
39445
diff
changeset
|
87 got = len(e.partial) |
1fc39367eafd
httppeer: calculate total expected bytes correctly
Anton Shestakov <av6@dwimlabs.net>
parents:
39445
diff
changeset
|
88 total = e.expected + got |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
89 msg = _('HTTP request error (incomplete response; ' |
39483
1fc39367eafd
httppeer: calculate total expected bytes correctly
Anton Shestakov <av6@dwimlabs.net>
parents:
39445
diff
changeset
|
90 'expected %d bytes got %d)') % (total, got) |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
91 else: |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
92 msg = _('HTTP request error (incomplete response)') |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
93 |
32023
a29580905771
error: rename RichIOError to PeerTransportError
Gregory Szorc <gregory.szorc@gmail.com>
parents:
32022
diff
changeset
|
94 raise error.PeerTransportError( |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
95 msg, |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
96 hint=_('this may be an intermittent network failure; ' |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
97 'if the error persists, consider contacting the ' |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
98 'network or server operator')) |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
99 except httplib.HTTPException as e: |
32023
a29580905771
error: rename RichIOError to PeerTransportError
Gregory Szorc <gregory.szorc@gmail.com>
parents:
32022
diff
changeset
|
100 raise error.PeerTransportError( |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
101 _('HTTP request error (%s)') % e, |
32086
b59a292d0a53
httppeer: unify hint message for PeerTransportError
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32023
diff
changeset
|
102 hint=_('this may be an intermittent network failure; ' |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
103 'if the error persists, consider contacting the ' |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
104 'network or server operator')) |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
105 |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
106 resp.__class__ = readerproxy |
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
107 |
33821
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
108 class _multifile(object): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
109 def __init__(self, *fileobjs): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
110 for f in fileobjs: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
111 if not util.safehasattr(f, 'length'): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
112 raise ValueError( |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
113 '_multifile only supports file objects that ' |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
114 'have a length but this one does not:', type(f), f) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
115 self._fileobjs = fileobjs |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
116 self._index = 0 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
117 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
118 @property |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
119 def length(self): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
120 return sum(f.length for f in self._fileobjs) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
121 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
122 def read(self, amt=None): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
123 if amt <= 0: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
124 return ''.join(f.read() for f in self._fileobjs) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
125 parts = [] |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
126 while amt and self._index < len(self._fileobjs): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
127 parts.append(self._fileobjs[self._index].read(amt)) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
128 got = len(parts[-1]) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
129 if got < amt: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
130 self._index += 1 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
131 amt -= got |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
132 return ''.join(parts) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
133 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
134 def seek(self, offset, whence=os.SEEK_SET): |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
135 if whence != os.SEEK_SET: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
136 raise NotImplementedError( |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
137 '_multifile does not support anything other' |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
138 ' than os.SEEK_SET for whence on seek()') |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
139 if offset != 0: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
140 raise NotImplementedError( |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
141 '_multifile only supports seeking to start, but that ' |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
142 'could be fixed if you need it') |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
143 for f in self._fileobjs: |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
144 f.seek(0) |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
145 self._index = 0 |
3c91cc0c5fde
httppeer: add support for httppostargs when we're sending a file
Augie Fackler <augie@google.com>
parents:
33806
diff
changeset
|
146 |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
147 def makev1commandrequest(ui, requestbuilder, caps, capablefn, |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
148 repobaseurl, cmd, args): |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
149 """Make an HTTP request to run a command for a version 1 client. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
150 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
151 ``caps`` is a set of known server capabilities. The value may be |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
152 None if capabilities are not yet known. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
153 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
154 ``capablefn`` is a function to evaluate a capability. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
155 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
156 ``cmd``, ``args``, and ``data`` define the command, its arguments, and |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
157 raw data to pass to it. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
158 """ |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
159 if cmd == 'pushkey': |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
160 args['data'] = '' |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
161 data = args.pop('data', None) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
162 headers = args.pop('headers', {}) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
163 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
164 ui.debug("sending %s command\n" % cmd) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
165 q = [('cmd', cmd)] |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
166 headersize = 0 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
167 # Important: don't use self.capable() here or else you end up |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
168 # with infinite recursion when trying to look up capabilities |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
169 # for the first time. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
170 postargsok = caps is not None and 'httppostargs' in caps |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
171 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
172 # Send arguments via POST. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
173 if postargsok and args: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
174 strargs = urlreq.urlencode(sorted(args.items())) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
175 if not data: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
176 data = strargs |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
177 else: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
178 if isinstance(data, bytes): |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
179 i = io.BytesIO(data) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
180 i.length = len(data) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
181 data = i |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
182 argsio = io.BytesIO(strargs) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
183 argsio.length = len(strargs) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
184 data = _multifile(argsio, data) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
185 headers[r'X-HgArgs-Post'] = len(strargs) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
186 elif args: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
187 # Calling self.capable() can infinite loop if we are calling |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
188 # "capabilities". But that command should never accept wire |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
189 # protocol arguments. So this should never happen. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
190 assert cmd != 'capabilities' |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
191 httpheader = capablefn('httpheader') |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
192 if httpheader: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
193 headersize = int(httpheader.split(',', 1)[0]) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
194 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
195 # Send arguments via HTTP headers. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
196 if headersize > 0: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
197 # The headers can typically carry more data than the URL. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
198 encargs = urlreq.urlencode(sorted(args.items())) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
199 for header, value in encodevalueinheaders(encargs, 'X-HgArg', |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
200 headersize): |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
201 headers[header] = value |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
202 # Send arguments via query string (Mercurial <1.9). |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
203 else: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
204 q += sorted(args.items()) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
205 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
206 qs = '?%s' % urlreq.urlencode(q) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
207 cu = "%s%s" % (repobaseurl, qs) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
208 size = 0 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
209 if util.safehasattr(data, 'length'): |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
210 size = data.length |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
211 elif data is not None: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
212 size = len(data) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
213 if data is not None and r'Content-Type' not in headers: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
214 headers[r'Content-Type'] = r'application/mercurial-0.1' |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
215 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
216 # Tell the server we accept application/mercurial-0.2 and multiple |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
217 # compression formats if the server is capable of emitting those |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
218 # payloads. |
37556
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
219 # Note: Keep this set empty by default, as client advertisement of |
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
220 # protocol parameters should only occur after the handshake. |
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
221 protoparams = set() |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
222 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
223 mediatypes = set() |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
224 if caps is not None: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
225 mt = capablefn('httpmediatype') |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
226 if mt: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
227 protoparams.add('0.1') |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
228 mediatypes = set(mt.split(',')) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
229 |
37556
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
230 protoparams.add('partial-pull') |
b77aa48ba690
httppeer: only advertise partial-pull if capabilities are known
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37555
diff
changeset
|
231 |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
232 if '0.2tx' in mediatypes: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
233 protoparams.add('0.2') |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
234 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
235 if '0.2tx' in mediatypes and capablefn('compression'): |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
236 # We /could/ compare supported compression formats and prune |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
237 # non-mutually supported or error if nothing is mutually supported. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
238 # For now, send the full list to the server and have it error. |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
239 comps = [e.wireprotosupport().name for e in |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
240 util.compengines.supportedwireengines(util.CLIENTROLE)] |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
241 protoparams.add('comp=%s' % ','.join(comps)) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
242 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
243 if protoparams: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
244 protoheaders = encodevalueinheaders(' '.join(sorted(protoparams)), |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
245 'X-HgProto', |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
246 headersize or 1024) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
247 for header, value in protoheaders: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
248 headers[header] = value |
37555
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
249 |
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
250 varyheaders = [] |
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
251 for header in headers: |
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
252 if header.lower().startswith(r'x-hg'): |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
253 varyheaders.append(header) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
254 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
255 if varyheaders: |
37555
930c433eb311
httppeer: always add x-hg* headers to Vary header
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37554
diff
changeset
|
256 headers[r'Vary'] = r','.join(sorted(varyheaders)) |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
257 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
258 req = requestbuilder(pycompat.strurl(cu), data, headers) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
259 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
260 if data is not None: |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
261 ui.debug("sending %d bytes\n" % size) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
262 req.add_unredirected_header(r'Content-Length', r'%d' % size) |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
263 |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
264 return req, cu, qs |
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
265 |
37738
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
266 def _reqdata(req): |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
267 """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
|
268 if pycompat.ispy3: |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
269 return req.data |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
270 if not req.has_data(): |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
271 return None |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
272 return req.get_data() |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
273 |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
274 def sendrequest(ui, opener, req): |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
275 """Send a prepared HTTP request. |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
276 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
277 Returns the response object. |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
278 """ |
38033
13b2812cff2b
httppeer: declare 'dbg' at the function level
Boris Feld <boris.feld@octobus.net>
parents:
38032
diff
changeset
|
279 dbg = ui.debug |
37548
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 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
|
283 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
|
284 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
|
285 hgargssize = None |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
286 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
287 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
|
288 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
|
289 value = pycompat.bytesurl(value) |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
290 if header.startswith('X-hgarg-'): |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
291 if hgargssize is None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
292 hgargssize = 0 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
293 hgargssize += len(value) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
294 else: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
295 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
|
296 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
297 if hgargssize is not None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
298 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
|
299 % hgargssize) |
37738
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
300 data = _reqdata(req) |
a1f785148097
httppeer: work around API differences on urllib Request objects
Augie Fackler <augie@google.com>
parents:
37737
diff
changeset
|
301 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
|
302 length = getattr(data, 'length', None) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
303 if length is None: |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
304 length = len(data) |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
305 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
|
306 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
307 start = util.timer() |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
308 |
38502
2279d90eed9a
httppeer: fix use of uninitialized variable with devel logging
Martin von Zweigbergk <martinvonz@google.com>
parents:
38239
diff
changeset
|
309 res = None |
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: |
38032
f9dc1d5b676b
httppeer: properly gate debug usage behind debug flag check
Boris Feld <boris.feld@octobus.net>
parents:
37832
diff
changeset
|
322 if ui.debugflag and ui.configbool('devel', 'debug.peer-request'): |
38502
2279d90eed9a
httppeer: fix use of uninitialized variable with devel logging
Martin von Zweigbergk <martinvonz@google.com>
parents:
38239
diff
changeset
|
323 code = res.code if res else -1 |
37736
e10b695b9c41
httppeer: fix debug prints to work on Python 3
Augie Fackler <augie@google.com>
parents:
37719
diff
changeset
|
324 dbg(line % ' finished in %.4f seconds (%d)' |
38502
2279d90eed9a
httppeer: fix use of uninitialized variable with devel logging
Martin von Zweigbergk <martinvonz@google.com>
parents:
38239
diff
changeset
|
325 % (util.timer() - start, code)) |
37550
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
326 |
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
327 # 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
|
328 _wraphttpresponse(res) |
37548
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
329 |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
330 return res |
8e7a4435ab6d
httppeer: extract code for performing an HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37547
diff
changeset
|
331 |
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
332 class RedirectedRepoError(error.RepoError): |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
333 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
|
334 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
|
335 self.respurl = respurl |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
336 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
337 def parsev1commandresponse(ui, baseurl, requrl, qs, resp, compressible, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
338 allowcbor=False): |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
339 # 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
|
340 redirected = False |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
341 respurl = pycompat.bytesurl(resp.geturl()) |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
342 if respurl.endswith(qs): |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
343 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
|
344 qsdropped = False |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
345 else: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
346 qsdropped = True |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
347 |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
348 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
|
349 redirected = True |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
350 if not ui.quiet: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
351 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
|
352 |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
353 try: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
354 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
|
355 except AttributeError: |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
356 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
|
357 |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
358 safeurl = util.hidepassword(baseurl) |
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
359 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
|
360 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
|
361 |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
362 # 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
|
363 # 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
|
364 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
|
365 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
|
366 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
|
367 "---%%<--- (%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
|
368 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
|
369 |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
370 # 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
|
371 # 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
|
372 if redirected and qsdropped: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
373 raise RedirectedRepoError(msg, respurl) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
374 else: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
375 raise error.RepoError(msg) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
376 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
377 try: |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
378 subtype = proto.split('-', 1)[1] |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
379 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
380 # 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
|
381 # this should ONLY be encountered for the initial capabilities |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
382 # request during handshake. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
383 if subtype == 'cbor': |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
384 if allowcbor: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
385 return respurl, proto, resp |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
386 else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
387 raise error.RepoError(_('unexpected CBOR response from ' |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
388 'server')) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
389 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
390 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
|
391 except ValueError: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
392 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
|
393 "header (%s)") % (safeurl, proto)) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
394 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
395 # 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
|
396 # generators. |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
397 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
|
398 if compressible: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
399 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
|
400 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
401 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
|
402 # 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
|
403 # engine in the payload header. |
39484
98995b689e03
httppeer: use util.readexactly() to abort on incomplete responses
Anton Shestakov <av6@dwimlabs.net>
parents:
39483
diff
changeset
|
404 elen = struct.unpack('B', util.readexactly(resp, 1))[0] |
98995b689e03
httppeer: use util.readexactly() to abort on incomplete responses
Anton Shestakov <av6@dwimlabs.net>
parents:
39483
diff
changeset
|
405 ename = util.readexactly(resp, elen) |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
406 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
|
407 |
37554
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
408 resp = engine.decompressorreader(resp) |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
409 else: |
301a1d2e8016
httppeer: don't accept very old media types (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37553
diff
changeset
|
410 raise error.RepoError(_("'%s' uses newer protocol %s") % |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
411 (safeurl, subtype)) |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
412 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
413 return respurl, proto, resp |
37551
946eb204ba67
httppeer: extract common response handling into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37550
diff
changeset
|
414 |
37614
a81d02ea65db
wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37611
diff
changeset
|
415 class httppeer(wireprotov1peer.wirepeer): |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
416 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
|
417 self.ui = ui |
33705
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33704
diff
changeset
|
418 self._path = path |
37006
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
419 self._url = url |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
420 self._caps = caps |
37006
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
421 self._urlopener = opener |
37547
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
422 self._requestbuilder = requestbuilder |
4516
96d8a56d4ef9
Removed trailing whitespace and tabs from python files
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4369
diff
changeset
|
423 |
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
424 def __del__(self): |
37006
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
425 for h in self._urlopener.handlers: |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
426 h.close() |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
427 getattr(h, "close_all", lambda: None)() |
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
428 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37006
diff
changeset
|
429 # Begin of ipeerconnection interface. |
33805
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
430 |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
431 def url(self): |
33705
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33704
diff
changeset
|
432 return self._path |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
433 |
33805
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
434 def local(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
435 return None |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
436 |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
437 def peer(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
438 return self |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
439 |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
440 def canpush(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
441 return True |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
442 |
33805
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
443 def close(self): |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
444 pass |
13603
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
445 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37006
diff
changeset
|
446 # End of ipeerconnection interface. |
33805
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
447 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37006
diff
changeset
|
448 # Begin of ipeercommands interface. |
33805
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
449 |
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
450 def capabilities(self): |
33705
73fd395ee29e
httppeer: make several instance attributes internal (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33704
diff
changeset
|
451 return self._caps |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
452 |
37320
39f7d4ee8bcd
repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37006
diff
changeset
|
453 # End of ipeercommands interface. |
33805
f913e90f15a0
httppeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33705
diff
changeset
|
454 |
30464
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
455 def _callstream(self, cmd, _compressible=False, **args): |
35359
98bc4c43f570
py3: handle keyword arguments correctly in httppeer.py
Pulkit Goyal <7895pulkit@gmail.com>
parents:
35197
diff
changeset
|
456 args = pycompat.byteskwargs(args) |
36218
e4ccd7a69f77
httppeer: change logic around argument handling
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35884
diff
changeset
|
457 |
37549
66d1001e1500
httppeer: extract code for creating a request into own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37548
diff
changeset
|
458 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
|
459 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
|
460 self._url, cmd, args) |
30763
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
461 |
37550
b5862ee01abe
httppeer: move error handling and response wrapping into sendrequest
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37549
diff
changeset
|
462 resp = sendrequest(self.ui, self._urlopener, req) |
32002
bf855efe5664
httppeer: wrap HTTPResponse.read() globally
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30924
diff
changeset
|
463 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
464 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
|
465 resp, _compressible) |
30464
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
466 |
752 | 467 return resp |
60 | 468 |
11589
e8d22fe2ddab
protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents:
11588
diff
changeset
|
469 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
|
470 fp = self._callstream(cmd, **args) |
2435
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
471 try: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
472 return fp.read() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
473 finally: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
474 # if using keepalive, allow connection to be reused |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
475 fp.close() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
476 |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
477 def _callpush(self, cmd, cg, **args): |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
478 # 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
|
479 # http 1.1 chunked transfer. |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
480 |
3662
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3661
diff
changeset
|
481 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
|
482 try: |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
483 types = types.split(',') |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
484 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
|
485 # 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
|
486 # 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
|
487 # bundles. |
3703
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
488 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
|
489 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
|
490 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
|
491 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
|
492 break |
3613
cbf352b9a3cd
Client support for hgweb unbundle with versions.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3609
diff
changeset
|
493 |
28666
ae53ecc47414
bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
28530
diff
changeset
|
494 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
|
495 fp = httpconnection.httpsendfile(self.ui, tempname, "rb") |
36297
a59ff82154b8
httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents:
36270
diff
changeset
|
496 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
|
497 |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
498 try: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
499 r = self._call(cmd, data=fp, headers=headers, **args) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
500 vals = r.split('\n', 1) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
501 if len(vals) < 2: |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
502 raise error.ResponseError(_("unexpected response:"), r) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
503 return vals |
36430
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36426
diff
changeset
|
504 except urlerr.httperror: |
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36426
diff
changeset
|
505 # Catch and re-raise these so we don't try and treat them |
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36426
diff
changeset
|
506 # like generic socket errors. They lack any values in |
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36426
diff
changeset
|
507 # .args on Python 3 which breaks our socket.error block. |
efebfa9b4cab
httppeer: explicitly catch urlerr.httperror and re-raise
Augie Fackler <augie@google.com>
parents:
36426
diff
changeset
|
508 raise |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
509 except socket.error as err: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
510 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
|
511 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
|
512 raise error.Abort(err.args[1]) |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
513 finally: |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
514 fp.close() |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
515 os.unlink(tempname) |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2435
diff
changeset
|
516 |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
517 def _calltwowaystream(self, cmd, fp, **args): |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
518 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
|
519 fp_ = None |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
520 filename = None |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
521 try: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
522 # dump bundle to disk |
38164
aac4be30e250
py3: wrap tempfile.mkstemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents:
37832
diff
changeset
|
523 fd, filename = pycompat.mkstemp(prefix="hg-bundle-", suffix=".hg") |
36835
5bc7ff103081
py3: use r'' instead of sysstr('') to get around code transformer
Yuya Nishihara <yuya@tcha.org>
parents:
36430
diff
changeset
|
524 fh = os.fdopen(fd, r"wb") |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
525 d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
526 while d: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
527 fh.write(d) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
528 d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
529 fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
530 # 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
|
531 fp_ = httpconnection.httpsendfile(self.ui, filename, "rb") |
36297
a59ff82154b8
httppeer: headers are native strings
Augie Fackler <augie@google.com>
parents:
36270
diff
changeset
|
532 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
|
533 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
|
534 finally: |
23086
cde6904f1992
httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents:
21188
diff
changeset
|
535 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
|
536 fp_.close() |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
537 if fh is not None: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
538 fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
539 os.unlink(filename) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
540 |
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
|
541 def _callcompressable(self, cmd, **args): |
30464
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
542 return self._callstream(cmd, _compressible=True, **args) |
11370 | 543 |
21188
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
544 def _abort(self, exception): |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
545 raise exception |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
546 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
547 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
|
548 reactor = wireprotoframing.clientreactor(hasmultiplesend=False, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
549 buffersends=True) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
550 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
551 handler = wireprotov2peer.clienthandler(ui, reactor) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
552 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
553 url = '%s/%s' % (apiurl, permission) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
554 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
555 if len(requests) > 1: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
556 url += '/multirequest' |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
557 else: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
558 url += '/%s' % requests[0][0] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
559 |
39436
3fe028b657bf
httppeer: log commands for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
38783
diff
changeset
|
560 ui.debug('sending %d commands\n' % len(requests)) |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
561 for command, args, f in requests: |
39436
3fe028b657bf
httppeer: log commands for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
38783
diff
changeset
|
562 ui.debug('sending command %s: %s\n' % ( |
3fe028b657bf
httppeer: log commands for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
38783
diff
changeset
|
563 command, stringutil.pprint(args, indent=2))) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
564 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
|
565 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
566 # TODO stream this. |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
567 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
|
568 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
569 # 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
|
570 headers = { |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
571 r'Accept': wireprotov2server.FRAMINGTYPE, |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
572 r'Content-Type': wireprotov2server.FRAMINGTYPE, |
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 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
575 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
|
576 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
|
577 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
578 try: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
579 res = opener.open(req) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
580 except urlerr.httperror as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
581 if e.code == 401: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
582 raise error.Abort(_('authorization failed')) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
583 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
584 raise |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
585 except httplib.HTTPException as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
586 ui.traceback() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
587 raise IOError(None, e) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
588 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
589 return handler, res |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
590 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
591 class queuedcommandfuture(pycompat.futures.Future): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
592 """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
|
593 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
594 def result(self, timeout=None): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
595 if self.done(): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
596 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
|
597 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
598 self._peerexecutor.sendcommands() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
599 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
600 # 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
|
601 # will resolve to Future.result. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
602 return self.result(timeout) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
603 |
37810
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
604 @interfaceutil.implementer(repository.ipeercommandexecutor) |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
605 class httpv2executor(object): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
606 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
|
607 self._ui = ui |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
608 self._opener = opener |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
609 self._requestbuilder = requestbuilder |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
610 self._apiurl = apiurl |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
611 self._descriptor = descriptor |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
612 self._sent = False |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
613 self._closed = False |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
614 self._neededpermissions = set() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
615 self._calls = [] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
616 self._futures = weakref.WeakSet() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
617 self._responseexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
618 self._responsef = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
619 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
620 def __enter__(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
621 return self |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
622 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
623 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
|
624 self.close() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
625 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
626 def callcommand(self, command, args): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
627 if self._sent: |
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 'commands are sent') |
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 if self._closed: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
632 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
|
633 'close()') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
634 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
635 # 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
|
636 # 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
|
637 # for this. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
638 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
|
639 raise error.ProgrammingError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
640 '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
|
641 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
642 cmdinfo = self._descriptor['commands'][command] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
643 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
|
644 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
645 if unknownargs: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
646 raise error.ProgrammingError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
647 '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
|
648 command, ', '.join(sorted(unknownargs)))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
649 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
650 self._neededpermissions |= set(cmdinfo['permissions']) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
651 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
652 # 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
|
653 # includes types... |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
654 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
655 f = pycompat.futures.Future() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
656 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
657 # 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
|
658 # could deadlock. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
659 f.__class__ = queuedcommandfuture |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
660 f._peerexecutor = self |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
661 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
662 self._futures.add(f) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
663 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
|
664 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
665 return f |
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 def sendcommands(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
668 if self._sent: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
669 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
670 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
671 if not self._calls: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
672 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
673 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
674 self._sent = True |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
675 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
676 # 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
|
677 # break reference cycle. |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
678 for f in self._futures: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
679 if isinstance(f, queuedcommandfuture): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
680 f.__class__ = pycompat.futures.Future |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
681 f._peerexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
682 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
683 # 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
|
684 calls = [(command, args, f) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
685 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
|
686 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
|
687 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
688 # 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
|
689 self._calls = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
690 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
691 if not calls: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
692 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
693 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
694 permissions = set(self._neededpermissions) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
695 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
696 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
|
697 permissions.remove('pull') |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
698 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
699 if len(permissions) > 1: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
700 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
|
701 'permissions: %s') % |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
702 _(', ').join(sorted(permissions))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
703 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
704 permission = { |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
705 'push': 'rw', |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
706 'pull': 'ro', |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
707 }[permissions.pop()] |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
708 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
709 handler, resp = sendv2request( |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
710 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
|
711 permission, calls) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
712 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
713 # 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
|
714 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
715 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
|
716 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
|
717 handler, resp) |
37651
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 def close(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
720 if self._closed: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
721 return |
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 self.sendcommands() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
724 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
725 self._closed = True |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
726 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
727 if not self._responsef: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
728 return |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
729 |
39437
3c6f7eebc010
httppeer: add TODO about delayed handling of ^C
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39436
diff
changeset
|
730 # TODO ^C here may not result in immediate program termination. |
3c6f7eebc010
httppeer: add TODO about delayed handling of ^C
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39436
diff
changeset
|
731 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
732 try: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
733 self._responsef.result() |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
734 finally: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
735 self._responseexecutor.shutdown(wait=True) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
736 self._responsef = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
737 self._responseexecutor = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
738 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
739 # 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
|
740 # 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
|
741 for f in self._futures: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
742 if not f.done(): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
743 f.set_exception(error.ResponseError( |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
744 _('unfulfilled command response'))) |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
745 |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
746 self._futures = None |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
747 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
748 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
|
749 # 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
|
750 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
751 while handler.readframe(resp): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37717
diff
changeset
|
752 pass |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
753 |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
754 # 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
|
755 @interfaceutil.implementer(repository.ipeerconnection, |
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
756 repository.ipeercapabilities, |
856f381ad74b
interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37738
diff
changeset
|
757 repository.ipeerrequests) |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
758 class httpv2peer(object): |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
759 def __init__(self, ui, repourl, apipath, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
760 apidescriptor): |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
761 self.ui = ui |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
762 |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
763 if repourl.endswith('/'): |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
764 repourl = repourl[:-1] |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
765 |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
766 self._url = repourl |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
767 self._apipath = apipath |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
768 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
|
769 self._opener = opener |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
770 self._requestbuilder = requestbuilder |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
771 self._descriptor = apidescriptor |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
772 |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
773 # Start of ipeerconnection. |
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 url(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
776 return self._url |
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 local(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
779 return None |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
780 |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
781 def peer(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
782 return self |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
783 |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
784 def canpush(self): |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
785 # TODO change once implemented. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
786 return False |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
787 |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
788 def close(self): |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
789 pass |
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
790 |
37609
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
791 # End of ipeerconnection. |
01bfe5ad0c53
httppeer: implement ipeerconnection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37558
diff
changeset
|
792 |
37611
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
793 # Start of ipeercapabilities. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
794 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
795 def capable(self, name): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
796 # 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
|
797 # 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
|
798 # version 2 of that command works differently. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
799 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
800 # Maps to commands that are available. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
801 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
|
802 return True |
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 # Other concepts. |
39629
a86d21e70b2b
exchangev2: start to implement pull with wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39628
diff
changeset
|
805 # TODO remove exchangev2 once we have a command implemented. |
a86d21e70b2b
exchangev2: start to implement pull with wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39628
diff
changeset
|
806 if name in ('bundle2', 'exchangev2'): |
37611
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
807 return True |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
808 |
39628
a5de21c9e370
httppeer: expose capabilities for each command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39549
diff
changeset
|
809 # Alias command-* to presence of command of that name. |
a5de21c9e370
httppeer: expose capabilities for each command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39549
diff
changeset
|
810 if name.startswith('command-'): |
a5de21c9e370
httppeer: expose capabilities for each command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39549
diff
changeset
|
811 return name[len('command-'):] in self._descriptor['commands'] |
a5de21c9e370
httppeer: expose capabilities for each command
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39549
diff
changeset
|
812 |
37611
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
813 return False |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
814 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
815 def requirecap(self, name, purpose): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
816 if self.capable(name): |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
817 return |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
818 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
819 raise error.CapabilityError( |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
820 _('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
|
821 'capability') % (purpose, name)) |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
822 |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
823 # End of ipeercapabilities. |
ae8730877371
httppeer: basic implementation of capabilities interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37609
diff
changeset
|
824 |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
825 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
|
826 with self.commandexecutor() as e: |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
827 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
|
828 |
37651
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
829 def commandexecutor(self): |
950294e28136
httppeer: implement command executor for version 2 peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37644
diff
changeset
|
830 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
|
831 self._apiurl, self._descriptor) |
37483
61e405fb6372
wireproto: crude support for version 2 HTTP peer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37411
diff
changeset
|
832 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
833 # 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
|
834 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
835 # The following keys are meaningful: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
836 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
837 # init |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
838 # Callable receiving (ui, repourl, servicepath, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
839 # apidescriptor) to create a peer. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
840 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
841 # priority |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
842 # 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
|
843 # services, we choose the one with the highest priority. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
844 API_PEERS = { |
37644
77c9ee77687c
wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37614
diff
changeset
|
845 wireprototypes.HTTP_WIREPROTO_V2: { |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
846 'init': httpv2peer, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
847 'priority': 50, |
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 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
850 |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
851 def performhandshake(ui, url, opener, requestbuilder): |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
852 # 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
|
853 |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
854 caps = None |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
855 def capable(x): |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
856 raise error.ProgrammingError('should not be called') |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
857 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
858 args = {} |
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 # 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
|
861 # 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
|
862 # X-HgProto-* header advertising which serializing formats it supports. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
863 # 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
|
864 # now. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
865 advertisev2 = ui.configbool('experimental', 'httppeer.advertise-v2') |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
866 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
867 if advertisev2: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
868 args['headers'] = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
869 r'X-HgProto-1': r'cbor', |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
870 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
871 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
872 args['headers'].update( |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
873 encodevalueinheaders(' '.join(sorted(API_PEERS)), |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
874 'X-HgUpgrade', |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
875 # We don't know the header limit this early. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
876 # So make it small. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
877 1024)) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
878 |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
879 req, requrl, qs = makev1commandrequest(ui, requestbuilder, caps, |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
880 capable, url, 'capabilities', |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
881 args) |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
882 resp = sendrequest(ui, opener, req) |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
883 |
37832
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
884 # 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
|
885 # ?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
|
886 # 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
|
887 # 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
|
888 # the new URL. |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
889 # |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
890 # 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
|
891 # 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
|
892 # 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
|
893 # 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
|
894 # 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
|
895 # 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
|
896 try: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
897 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
|
898 compressible=False, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
899 allowcbor=advertisev2) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
900 except RedirectedRepoError as e: |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
901 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
|
902 capable, e.respurl, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
903 'capabilities', args) |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
904 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
|
905 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
|
906 compressible=False, |
6169d95dce3b
httppeer: detect redirect to URL without query string (issue5860)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37810
diff
changeset
|
907 allowcbor=advertisev2) |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
908 |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
909 try: |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
910 rawdata = resp.read() |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
911 finally: |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
912 resp.close() |
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
913 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
914 if not ct.startswith('application/mercurial-'): |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
915 raise error.ProgrammingError('unexpected content-type: %s' % ct) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
916 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
917 if advertisev2: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
918 if ct == 'application/mercurial-cbor': |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
919 try: |
39445
cdb56f295b03
httppeer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39437
diff
changeset
|
920 info = cborutil.decodeall(rawdata)[0] |
cdb56f295b03
httppeer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39437
diff
changeset
|
921 except cborutil.CBORDecodeError: |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
922 raise error.Abort(_('error decoding CBOR from remote server'), |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
923 hint=_('try again and consider contacting ' |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
924 'the server operator')) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
925 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
926 # We got a legacy response. That's fine. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
927 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
|
928 info = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
929 'v1capabilities': set(rawdata.split()) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
930 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
931 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
932 else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
933 raise error.RepoError( |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
934 _('unexpected response type from server: %s') % ct) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
935 else: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
936 info = { |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
937 'v1capabilities': set(rawdata.split()) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
938 } |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
939 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
940 return respurl, info |
37552
8b8a845c85fc
httppeer: perform capabilities request in makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37551
diff
changeset
|
941 |
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
942 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
|
943 """Construct an appropriate HTTP peer instance. |
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
944 |
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
945 ``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
|
946 connections, perform HTTP requests. |
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
947 |
37547
835ccc2a5ef1
httppeer: move requestbuilder defaults into makepeer() argument
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37546
diff
changeset
|
948 ``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
|
949 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
|
950 """ |
37006
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
951 u = util.url(path) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
952 if u.query or u.fragment: |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
953 raise error.Abort(_('unsupported URL component: "%s"') % |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
954 (u.query or u.fragment)) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
955 |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
956 # urllib cannot handle URLs with embedded user or passwd. |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
957 url, authinfo = u.authinfo() |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
958 ui.debug('using %s\n' % url) |
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
959 |
37553
6b08cf6b900f
httppeer: allow opener to be passed to makepeer()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37552
diff
changeset
|
960 opener = opener or urlmod.opener(ui, authinfo) |
37006
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
961 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
962 respurl, info = performhandshake(ui, url, opener, requestbuilder) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
963 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
964 # 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
|
965 # 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
|
966 # |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
967 # 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
|
968 # 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
|
969 # 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
|
970 # capabilities, we could filter out services not meeting the |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
971 # requirements. Possibly by consulting the interfaces defined by the |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
972 # peer type. |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
973 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
|
974 |
37558
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
975 preferredchoices = sorted(apipeerchoices, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
976 key=lambda x: API_PEERS[x]['priority'], |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
977 reverse=True) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
978 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
979 for service in preferredchoices: |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
980 apipath = '%s/%s' % (info['apibase'].rstrip('/'), service) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
981 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
982 return API_PEERS[service]['init'](ui, respurl, apipath, opener, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
983 requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
984 info['apis'][service]) |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
985 |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
986 # 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
|
987 return httppeer(ui, path, respurl, opener, requestbuilder, |
8a73132214a3
httppeer: support protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37556
diff
changeset
|
988 info['v1capabilities']) |
37006
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
989 |
39549
089fc0db0954
hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39484
diff
changeset
|
990 def instance(ui, path, create, intents=None, createopts=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
|
991 if create: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
992 raise error.Abort(_('cannot create new http repository')) |
7211 | 993 try: |
36959
43815d87c6aa
httppeer: alias url as urlmod
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36835
diff
changeset
|
994 if path.startswith('https:') and not urlmod.has_https: |
36220
874209855f5c
httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36219
diff
changeset
|
995 raise error.Abort(_('Python support for SSL and HTTPS ' |
874209855f5c
httppeer: remove httpspeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36219
diff
changeset
|
996 'is not installed')) |
35884
197d10e157ce
httppeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35698
diff
changeset
|
997 |
37006
8e89c2bec1f7
httppeer: refactor how httppeer is created (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36961
diff
changeset
|
998 inst = makepeer(ui, path) |
35884
197d10e157ce
httppeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35698
diff
changeset
|
999 |
7211 | 1000 return inst |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
1001 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
|
1002 try: |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
1003 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
|
1004 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
|
1005 return r |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
1006 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
|
1007 raise httpexception # use the original http RepoError instead |