Mercurial > hg
annotate mercurial/httppeer.py @ 31957:84f9eb9758c0
atexit: test failing handlers
author | Bryan O'Sullivan <bryano@fb.com> |
---|---|
date | Tue, 11 Apr 2017 14:54:12 -0700 |
parents | 48dea083f66d |
children | bf855efe5664 |
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 |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
12 import os |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
13 import socket |
30763
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
14 import struct |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
15 import tempfile |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
16 |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
17 from .i18n import _ |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
18 from .node import nullid |
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, |
25954
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
24 statichttprepo, |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
25 url, |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
26 util, |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
27 wireproto, |
7bbdb78d2842
httppeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
28 ) |
4678
a814a5b11fff
Work around urllib2 digest auth bug with Python < 2.5
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4633
diff
changeset
|
29 |
29455
0c741fd6158a
py3: conditionalize httplib import
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29241
diff
changeset
|
30 httplib = util.httplib |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
31 urlerr = util.urlerr |
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
32 urlreq = util.urlreq |
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
33 |
30465
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
34 # FUTURE: consider refactoring this API to use generators. This will |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
35 # require a compression engine API to emit generators. |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
36 def decompressresponse(response, engine): |
3661
e99ba8726bda
remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents:
3614
diff
changeset
|
37 try: |
30465
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
38 reader = engine.decompressorreader(response) |
7280
810ca383da9c
remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
7279
diff
changeset
|
39 except httplib.HTTPException: |
3661
e99ba8726bda
remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents:
3614
diff
changeset
|
40 raise IOError(None, _('connection ended unexpectedly')) |
30465
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
41 |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
42 # We need to wrap reader.read() so HTTPException on subsequent |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
43 # reads is also converted. |
30484
d1b97fc87f55
httppeer: document why super() isn't used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30475
diff
changeset
|
44 # Ideally we'd use super() here. However, if ``reader`` isn't a new-style |
d1b97fc87f55
httppeer: document why super() isn't used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30475
diff
changeset
|
45 # class, this can raise: |
d1b97fc87f55
httppeer: document why super() isn't used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30475
diff
changeset
|
46 # TypeError: super() argument 1 must be type, not classobj |
30465
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
47 origread = reader.read |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
48 class readerproxy(reader.__class__): |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
49 def read(self, *args, **kwargs): |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
50 try: |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
51 return origread(*args, **kwargs) |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
52 except httplib.HTTPException: |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
53 raise IOError(None, _('connection ended unexpectedly')) |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
54 |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
55 reader.__class__ = readerproxy |
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
56 return reader |
3661
e99ba8726bda
remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents:
3614
diff
changeset
|
57 |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
58 def encodevalueinheaders(value, header, limit): |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
59 """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
|
60 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
61 ``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
|
62 ``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
|
63 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
|
64 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
65 Returns an iterable of 2-tuples consisting of header names and values. |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
66 """ |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
67 fmt = header + '-%s' |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
68 valuelen = limit - len(fmt % '000') - len(': \r\n') |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
69 result = [] |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
70 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
71 n = 0 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
72 for i in xrange(0, len(value), valuelen): |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
73 n += 1 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
74 result.append((fmt % str(n), value[i:i + valuelen])) |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
75 |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
76 return result |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
77 |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
15246
diff
changeset
|
78 class httppeer(wireproto.wirepeer): |
60 | 79 def __init__(self, ui, path): |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
80 self.path = path |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
81 self.caps = None |
4132
0d94e4a3ddb4
Close keepalive connections to fix server traceback
Andrei Vermel <avermel@mail.ru>
parents:
4025
diff
changeset
|
82 self.handler = None |
15246
7b15dd9125b3
httprepo: make __del__ more stable in error situations
Mads Kiilerich <mads@kiilerich.com>
parents:
15159
diff
changeset
|
83 self.urlopener = None |
25500
00ecc894138d
httppeer: allow extensions to replace urllib2.Request
Kyle Lippincott <spectral@google.com>
parents:
25085
diff
changeset
|
84 self.requestbuilder = None |
14076
924c82157d46
url: move URL parsing functions into util to improve startup time
Brodie Rao <brodie@bitheap.org>
parents:
14060
diff
changeset
|
85 u = util.url(path) |
13819
d16894e29f91
httprepo/sshrepo: use url.url
Brodie Rao <brodie@bitheap.org>
parents:
13603
diff
changeset
|
86 if u.query or u.fragment: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
87 raise error.Abort(_('unsupported URL component: "%s"') % |
13819
d16894e29f91
httprepo/sshrepo: use url.url
Brodie Rao <brodie@bitheap.org>
parents:
13603
diff
changeset
|
88 (u.query or u.fragment)) |
2337
3f24bc5dee81
http: fix many problems with url parsing and auth. added proxy test.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2336
diff
changeset
|
89 |
3f24bc5dee81
http: fix many problems with url parsing and auth. added proxy test.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2336
diff
changeset
|
90 # urllib cannot handle URLs with embedded user or passwd |
13819
d16894e29f91
httprepo/sshrepo: use url.url
Brodie Rao <brodie@bitheap.org>
parents:
13603
diff
changeset
|
91 self._url, authinfo = u.authinfo() |
7270
2db33c1a5654
factor out the url handling from httprepo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
7269
diff
changeset
|
92 |
60 | 93 self.ui = ui |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
8563
diff
changeset
|
94 self.ui.debug('using %s\n' % self._url) |
2337
3f24bc5dee81
http: fix many problems with url parsing and auth. added proxy test.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2336
diff
changeset
|
95 |
7270
2db33c1a5654
factor out the url handling from httprepo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
7269
diff
changeset
|
96 self.urlopener = url.opener(ui, authinfo) |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
97 self.requestbuilder = urlreq.request |
4516
96d8a56d4ef9
Removed trailing whitespace and tabs from python files
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4369
diff
changeset
|
98 |
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
99 def __del__(self): |
30241
cac4ca036dff
httppeer: make __del__ access to self.urlopener more safe
Mads Kiilerich <madski@unity3d.com>
parents:
29455
diff
changeset
|
100 urlopener = getattr(self, 'urlopener', None) |
cac4ca036dff
httppeer: make __del__ access to self.urlopener more safe
Mads Kiilerich <madski@unity3d.com>
parents:
29455
diff
changeset
|
101 if urlopener: |
cac4ca036dff
httppeer: make __del__ access to self.urlopener more safe
Mads Kiilerich <madski@unity3d.com>
parents:
29455
diff
changeset
|
102 for h in urlopener.handlers: |
15246
7b15dd9125b3
httprepo: make __del__ more stable in error situations
Mads Kiilerich <mads@kiilerich.com>
parents:
15159
diff
changeset
|
103 h.close() |
7b15dd9125b3
httprepo: make __del__ more stable in error situations
Mads Kiilerich <mads@kiilerich.com>
parents:
15159
diff
changeset
|
104 getattr(h, "close_all", lambda : None)() |
7752
998fc8f62539
close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents:
7641
diff
changeset
|
105 |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
106 def url(self): |
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
107 return self.path |
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
108 |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
109 # look up capabilities only when needed |
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
110 |
13603
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
111 def _fetchcaps(self): |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
112 self.caps = set(self._call('capabilities').split()) |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
113 |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
15246
diff
changeset
|
114 def _capabilities(self): |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
115 if self.caps is None: |
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
116 try: |
13603
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
117 self._fetchcaps() |
7637 | 118 except error.RepoError: |
8150
bbc24c0753a0
util: use built-in set and frozenset
Martin Geisler <mg@lazybytes.net>
parents:
8055
diff
changeset
|
119 self.caps = set() |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
8563
diff
changeset
|
120 self.ui.debug('capabilities: %s\n' % |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
121 (' '.join(self.caps or ['none']))) |
2442
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
122 return self.caps |
c660691fb45d
http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2439
diff
changeset
|
123 |
1870
8a8ab47cccde
make push over http print good error message.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1736
diff
changeset
|
124 def lock(self): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
125 raise error.Abort(_('operation not supported over http')) |
1870
8a8ab47cccde
make push over http print good error message.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1736
diff
changeset
|
126 |
30464
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
127 def _callstream(self, cmd, _compressible=False, **args): |
13006
ea68947ad0ce
httprepo: remove is-comparison with string literal
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
12969
diff
changeset
|
128 if cmd == 'pushkey': |
12969
6bd9778ae749
pushkey: force HTTP POST on push and add tests (issue2489)
Matt Mackall <mpm@selenic.com>
parents:
12062
diff
changeset
|
129 args['data'] = '' |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
130 data = args.pop('data', None) |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
131 headers = args.pop('headers', {}) |
14245
13d44e4235f8
httprepo: send 100-continue on POSTs if using http2
Augie Fackler <durin42@gmail.com>
parents:
14244
diff
changeset
|
132 |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
8563
diff
changeset
|
133 self.ui.debug("sending %s command\n" % cmd) |
14093
ce99d887585f
httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents:
14076
diff
changeset
|
134 q = [('cmd', cmd)] |
ce99d887585f
httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents:
14076
diff
changeset
|
135 headersize = 0 |
30564
07bcd1bf6151
httppeer: assign Vary request header last
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30484
diff
changeset
|
136 varyheaders = [] |
28530
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
137 # Important: don't use self.capable() here or else you end up |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
138 # with infinite recursion when trying to look up capabilities |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
139 # for the first time. |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
140 postargsok = self.caps is not None and 'httppostargs' in self.caps |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
141 # TODO: support for httppostargs when data is a file-like |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
142 # object rather than a basestring |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
143 canmungedata = not data or isinstance(data, basestring) |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
144 if postargsok and canmungedata: |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
145 strargs = urlreq.urlencode(sorted(args.items())) |
28530
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
146 if strargs: |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
147 if not data: |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
148 data = strargs |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
149 elif isinstance(data, basestring): |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
150 data = strargs + data |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
151 headers['X-HgArgs-Post'] = len(strargs) |
fd2acc5046f6
http: support sending hgargs via POST body instead of in GET or headers
Augie Fackler <augie@google.com>
parents:
28486
diff
changeset
|
152 else: |
28485
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
153 if len(args) > 0: |
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
154 httpheader = self.capable('httpheader') |
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
155 if httpheader: |
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
156 headersize = int(httpheader.split(',', 1)[0]) |
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
157 if headersize > 0: |
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
158 # The headers can typically carry more data than the URL. |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
159 encargs = urlreq.urlencode(sorted(args.items())) |
30759
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
160 for header, value in encodevalueinheaders(encargs, 'X-HgArg', |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
161 headersize): |
3f5f0c98cd18
httppeer: extract code for HTTP header spanning
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30564
diff
changeset
|
162 headers[header] = value |
28486
50314dc3ae4e
httppeer: compute header names only once
Augie Fackler <augie@google.com>
parents:
28485
diff
changeset
|
163 varyheaders.append(header) |
28485
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
164 else: |
d3893900f6c8
httppeer: indent existing argument handling with if True
Augie Fackler <augie@google.com>
parents:
28484
diff
changeset
|
165 q += sorted(args.items()) |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
166 qs = '?%s' % urlreq.urlencode(q) |
3562
88b4755fa48f
httprepo: record the url after a request, makes pull + redirect works
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3445
diff
changeset
|
167 cu = "%s%s" % (self._url, qs) |
28484
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
168 size = 0 |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
169 if util.safehasattr(data, 'length'): |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
170 size = data.length |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
171 elif data is not None: |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
172 size = len(data) |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
173 if size and self.ui.configbool('ui', 'usehttp2', False): |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
174 headers['Expect'] = '100-Continue' |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
175 headers['X-HgHttp2'] = '1' |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
176 if data is not None and 'Content-Type' not in headers: |
da6f713ab480
httppeer: move size computation later in _callstream
Augie Fackler <augie@google.com>
parents:
28483
diff
changeset
|
177 headers['Content-Type'] = 'application/mercurial-0.1' |
30564
07bcd1bf6151
httppeer: assign Vary request header last
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30484
diff
changeset
|
178 |
30763
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
179 # Tell the server we accept application/mercurial-0.2 and multiple |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
180 # compression formats if the server is capable of emitting those |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
181 # payloads. |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
182 protoparams = [] |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
183 |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
184 mediatypes = set() |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
185 if self.caps is not None: |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
186 mt = self.capable('httpmediatype') |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
187 if mt: |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
188 protoparams.append('0.1') |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
189 mediatypes = set(mt.split(',')) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
190 |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
191 if '0.2tx' in mediatypes: |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
192 protoparams.append('0.2') |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
193 |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
194 if '0.2tx' in mediatypes and self.capable('compression'): |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
195 # We /could/ compare supported compression formats and prune |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
196 # non-mutually supported or error if nothing is mutually supported. |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
197 # For now, send the full list to the server and have it error. |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
198 comps = [e.wireprotosupport().name for e in |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
199 util.compengines.supportedwireengines(util.CLIENTROLE)] |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
200 protoparams.append('comp=%s' % ','.join(comps)) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
201 |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
202 if protoparams: |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
203 protoheaders = encodevalueinheaders(' '.join(protoparams), |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
204 'X-HgProto', |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
205 headersize or 1024) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
206 for header, value in protoheaders: |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
207 headers[header] = value |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
208 varyheaders.append(header) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
209 |
30564
07bcd1bf6151
httppeer: assign Vary request header last
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30484
diff
changeset
|
210 headers['Vary'] = ','.join(varyheaders) |
25500
00ecc894138d
httppeer: allow extensions to replace urllib2.Request
Kyle Lippincott <spectral@google.com>
parents:
25085
diff
changeset
|
211 req = self.requestbuilder(cu, data, headers) |
30564
07bcd1bf6151
httppeer: assign Vary request header last
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30484
diff
changeset
|
212 |
10491
d7e582cab6b6
http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10282
diff
changeset
|
213 if data is not None: |
d7e582cab6b6
http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10282
diff
changeset
|
214 self.ui.debug("sending %s bytes\n" % size) |
d7e582cab6b6
http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10282
diff
changeset
|
215 req.add_unredirected_header('Content-Length', '%d' % size) |
2294
ce67fa312f61
Catch urllib's HTTPException and give a meaningful error message to the user.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2281
diff
changeset
|
216 try: |
10491
d7e582cab6b6
http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10282
diff
changeset
|
217 resp = self.urlopener.open(req) |
28883
032c4c2f802a
pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents:
28666
diff
changeset
|
218 except urlerr.httperror as inst: |
2467
4e78dc71d946
http client: better work with authorization errors, broken sockets.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2465
diff
changeset
|
219 if inst.code == 401: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
220 raise error.Abort(_('authorization failed')) |
2467
4e78dc71d946
http client: better work with authorization errors, broken sockets.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2465
diff
changeset
|
221 raise |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
222 except httplib.HTTPException as inst: |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
8563
diff
changeset
|
223 self.ui.debug('http error while sending %s command\n' % cmd) |
8206
cce63ef1045b
ui: print_exc() -> traceback()
Matt Mackall <mpm@selenic.com>
parents:
8150
diff
changeset
|
224 self.ui.traceback() |
2336
f77edcffb837
http: print better error if exception happens.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2294
diff
changeset
|
225 raise IOError(None, inst) |
3562
88b4755fa48f
httprepo: record the url after a request, makes pull + redirect works
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3445
diff
changeset
|
226 # record the url we got redirected to |
3570
c141d07198b9
Inform the user about the new URL when being redirected via http.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3569
diff
changeset
|
227 resp_url = resp.geturl() |
c141d07198b9
Inform the user about the new URL when being redirected via http.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3569
diff
changeset
|
228 if resp_url.endswith(qs): |
c141d07198b9
Inform the user about the new URL when being redirected via http.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3569
diff
changeset
|
229 resp_url = resp_url[:-len(qs)] |
9881
54b518fc6671
httprepo: suppress the `real URL is...' message in safe, common cases.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
9878
diff
changeset
|
230 if self._url.rstrip('/') != resp_url.rstrip('/'): |
14504
c59968e8b579
httprepo: send URL redirection notices to stderr (issue2828)
Matt Mackall <mpm@selenic.com>
parents:
14503
diff
changeset
|
231 if not self.ui.quiet: |
c59968e8b579
httprepo: send URL redirection notices to stderr (issue2828)
Matt Mackall <mpm@selenic.com>
parents:
14503
diff
changeset
|
232 self.ui.warn(_('real URL is %s\n') % resp_url) |
10208
37c4ce51a12d
httprepo: always store the response url (issue1968)
Steve Borho <steve@borho.org>
parents:
9881
diff
changeset
|
233 self._url = resp_url |
2435
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
234 try: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
235 proto = resp.getheader('content-type') |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
236 except AttributeError: |
14503
4e958f2a193f
httprepo: proper handling of invalid responses without content-type (issue2019)
Mads Kiilerich <mads@kiilerich.com>
parents:
13115
diff
changeset
|
237 proto = resp.headers.get('content-type', '') |
752 | 238 |
14076
924c82157d46
url: move URL parsing functions into util to improve startup time
Brodie Rao <brodie@bitheap.org>
parents:
14060
diff
changeset
|
239 safeurl = util.hidepassword(self._url) |
15017
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14999
diff
changeset
|
240 if proto.startswith('application/hg-error'): |
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14999
diff
changeset
|
241 raise error.OutOfBandError(resp.read()) |
753 | 242 # accept old "text/plain" and "application/hg-changegroup" for now |
4633
ff7253a0d1da
Cleanup of whitespace, indentation and line continuation.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4516
diff
changeset
|
243 if not (proto.startswith('application/mercurial-') or |
18737
56f8522c3591
httppeer: improve protocol check
Matt Mackall <mpm@selenic.com>
parents:
17221
diff
changeset
|
244 (proto.startswith('text/plain') |
56f8522c3591
httppeer: improve protocol check
Matt Mackall <mpm@selenic.com>
parents:
17221
diff
changeset
|
245 and not resp.headers.get('content-length')) or |
4633
ff7253a0d1da
Cleanup of whitespace, indentation and line continuation.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4516
diff
changeset
|
246 proto.startswith('application/hg-changegroup')): |
14076
924c82157d46
url: move URL parsing functions into util to improve startup time
Brodie Rao <brodie@bitheap.org>
parents:
14060
diff
changeset
|
247 self.ui.debug("requested URL: '%s'\n" % util.hidepassword(cu)) |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10264
diff
changeset
|
248 raise error.RepoError( |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10264
diff
changeset
|
249 _("'%s' does not appear to be an hg repository:\n" |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10264
diff
changeset
|
250 "---%%<--- (%s)\n%s\n---%%<---\n") |
18738
b376e8f91c16
httppeer: avoid large dumps when we don't see an hgweb repo
Matt Mackall <mpm@selenic.com>
parents:
18737
diff
changeset
|
251 % (safeurl, proto or 'no content-type', resp.read(1024))) |
752 | 252 |
4012
d1e31d7f7d44
fix handling of multiple Content-type headers
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3703
diff
changeset
|
253 if proto.startswith('application/mercurial-'): |
d1e31d7f7d44
fix handling of multiple Content-type headers
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3703
diff
changeset
|
254 try: |
4356
aed9e6dceb85
Avoid float rounding errors when checking http protocol version.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4226
diff
changeset
|
255 version = proto.split('-', 1)[1] |
aed9e6dceb85
Avoid float rounding errors when checking http protocol version.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4226
diff
changeset
|
256 version_info = tuple([int(n) for n in version.split('.')]) |
4012
d1e31d7f7d44
fix handling of multiple Content-type headers
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3703
diff
changeset
|
257 except ValueError: |
7637 | 258 raise error.RepoError(_("'%s' sent a broken Content-Type " |
8053
976170068286
hide passwords in httprepo error messages
Steve Borho <steve@borho.org>
parents:
7752
diff
changeset
|
259 "header (%s)") % (safeurl, proto)) |
30763
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
260 |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
261 if version_info == (0, 1): |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
262 if _compressible: |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
263 return decompressresponse(resp, util.compengines['zlib']) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
264 return resp |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
265 elif version_info == (0, 2): |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
266 # application/mercurial-0.2 always identifies the compression |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
267 # engine in the payload header. |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
268 elen = struct.unpack('B', resp.read(1))[0] |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
269 ename = resp.read(elen) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
270 engine = util.compengines.forwiretype(ename) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
271 return decompressresponse(resp, engine) |
a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30759
diff
changeset
|
272 else: |
7637 | 273 raise error.RepoError(_("'%s' uses newer protocol %s") % |
8053
976170068286
hide passwords in httprepo error messages
Steve Borho <steve@borho.org>
parents:
7752
diff
changeset
|
274 (safeurl, version)) |
753 | 275 |
30464
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
276 if _compressible: |
30465
40a1871eea5e
httppeer: use compression engine API for decompressing responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30464
diff
changeset
|
277 return decompressresponse(resp, util.compengines['zlib']) |
30464
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
278 |
752 | 279 return resp |
60 | 280 |
11589
e8d22fe2ddab
protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents:
11588
diff
changeset
|
281 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
|
282 fp = self._callstream(cmd, **args) |
2435
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
283 try: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
284 return fp.read() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
285 finally: |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
286 # if using keepalive, allow connection to be reused |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
287 fp.close() |
ff2bac730b99
http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2337
diff
changeset
|
288 |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
289 def _callpush(self, cmd, cg, **args): |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
290 # 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
|
291 # http 1.1 chunked transfer. |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
292 |
3662
f4dc02d7fb71
unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents:
3661
diff
changeset
|
293 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
|
294 try: |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
295 types = types.split(',') |
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
296 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
|
297 # 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
|
298 # 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
|
299 # bundles. |
3703
e674cae8efee
fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
3662
diff
changeset
|
300 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
|
301 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
|
302 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
|
303 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
|
304 break |
3613
cbf352b9a3cd
Client support for hgweb unbundle with versions.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3609
diff
changeset
|
305 |
28666
ae53ecc47414
bundle: move writebundle() from changegroup.py to bundle2.py (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
28530
diff
changeset
|
306 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
|
307 fp = httpconnection.httpsendfile(self.ui, tempname, "rb") |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
308 headers = {'Content-Type': 'application/mercurial-0.1'} |
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
309 |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
310 try: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
311 r = self._call(cmd, data=fp, headers=headers, **args) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
312 vals = r.split('\n', 1) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
313 if len(vals) < 2: |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
314 raise error.ResponseError(_("unexpected response:"), r) |
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
315 return vals |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
316 except socket.error as err: |
25085
e05734cd7902
httppeer: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
23895
diff
changeset
|
317 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
|
318 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
|
319 raise error.Abort(err.args[1]) |
2465
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
320 finally: |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
321 fp.close() |
c91118f425d0
push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2447
diff
changeset
|
322 os.unlink(tempname) |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2435
diff
changeset
|
323 |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
324 def _calltwowaystream(self, cmd, fp, **args): |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
325 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
|
326 fp_ = None |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
327 filename = None |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
328 try: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
329 # dump bundle to disk |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
330 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg") |
30924
48dea083f66d
py3: convert the mode argument of os.fdopen to unicodes (1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30763
diff
changeset
|
331 fh = os.fdopen(fd, pycompat.sysstr("wb")) |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
332 d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
333 while d: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
334 fh.write(d) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
335 d = fp.read(4096) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
336 fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
337 # 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
|
338 fp_ = httpconnection.httpsendfile(self.ui, filename, "rb") |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
339 headers = {'Content-Type': '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
|
340 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
|
341 finally: |
23086
cde6904f1992
httppeer: close the temporary bundle file after two-way streaming it
Matt Harbison <matt_harbison@yahoo.com>
parents:
21188
diff
changeset
|
342 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
|
343 fp_.close() |
21074
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
344 if fh is not None: |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
345 fh.close() |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
346 os.unlink(filename) |
f8a0d82b0463
httppeer: support for _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
347 |
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
|
348 def _callcompressable(self, cmd, **args): |
30464
e16e234b9ca3
httppeer: do decompression inside _callstream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30241
diff
changeset
|
349 return self._callstream(cmd, _compressible=True, **args) |
11370 | 350 |
21188
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
351 def _abort(self, exception): |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
352 raise exception |
d36440d84328
httppeer: reintroduce _abort that accidentally was removed in 167047ba3cfa
Mads Kiilerich <madski@unity3d.com>
parents:
21074
diff
changeset
|
353 |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
15246
diff
changeset
|
354 class httpspeer(httppeer): |
2569
52ce0d6bc375
HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2557
diff
changeset
|
355 def __init__(self, ui, path): |
7279
1f0f84660dea
Fix https availability checking
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
7270
diff
changeset
|
356 if not url.has_https: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
357 raise error.Abort(_('Python support for SSL and HTTPS ' |
2569
52ce0d6bc375
HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2557
diff
changeset
|
358 'is not installed')) |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
15246
diff
changeset
|
359 httppeer.__init__(self, ui, path) |
2740
386f04d6ecb3
clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2673
diff
changeset
|
360 |
386f04d6ecb3
clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2673
diff
changeset
|
361 def instance(ui, path, create): |
386f04d6ecb3
clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2673
diff
changeset
|
362 if create: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25954
diff
changeset
|
363 raise error.Abort(_('cannot create new http repository')) |
7211 | 364 try: |
365 if path.startswith('https:'): | |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
15246
diff
changeset
|
366 inst = httpspeer(ui, path) |
7211 | 367 else: |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
15246
diff
changeset
|
368 inst = httppeer(ui, path) |
13603
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
369 try: |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
370 # Try to do useful work when checking compatibility. |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
371 # Usually saves a roundtrip since we want the caps anyway. |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
372 inst._fetchcaps() |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
373 except error.RepoError: |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
374 # No luck, try older compatibility check. |
395a84f78736
httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13555
diff
changeset
|
375 inst.between([(nullid, nullid)]) |
7211 | 376 return inst |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25500
diff
changeset
|
377 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
|
378 try: |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
379 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
|
380 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
|
381 return r |
cc9366a3751b
httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents:
14094
diff
changeset
|
382 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
|
383 raise httpexception # use the original http RepoError instead |