##// END OF EJS Templates
httpconnection: allow `httpsendfile` subclasses to suppress the progressbar...
Matt Harbison -
r44780:0e8b28fb default
parent child Browse files
Show More
@@ -1,132 +1,135 b''
1 # httpconnection.py - urllib2 handler for new http support
1 # httpconnection.py - urllib2 handler for new http support
2 #
2 #
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 # Copyright 2011 Google, Inc.
6 # Copyright 2011 Google, Inc.
7 #
7 #
8 # This software may be used and distributed according to the terms of the
8 # This software may be used and distributed according to the terms of the
9 # GNU General Public License version 2 or any later version.
9 # GNU General Public License version 2 or any later version.
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12
12
13 import os
13 import os
14
14
15 from .i18n import _
15 from .i18n import _
16 from .pycompat import open
16 from .pycompat import open
17 from . import (
17 from . import (
18 pycompat,
18 pycompat,
19 util,
19 util,
20 )
20 )
21
21
22 urlerr = util.urlerr
22 urlerr = util.urlerr
23 urlreq = util.urlreq
23 urlreq = util.urlreq
24
24
25 # moved here from url.py to avoid a cycle
25 # moved here from url.py to avoid a cycle
26 class httpsendfile(object):
26 class httpsendfile(object):
27 """This is a wrapper around the objects returned by python's "open".
27 """This is a wrapper around the objects returned by python's "open".
28
28
29 Its purpose is to send file-like objects via HTTP.
29 Its purpose is to send file-like objects via HTTP.
30 It do however not define a __len__ attribute because the length
30 It do however not define a __len__ attribute because the length
31 might be more than Py_ssize_t can handle.
31 might be more than Py_ssize_t can handle.
32 """
32 """
33
33
34 def __init__(self, ui, *args, **kwargs):
34 def __init__(self, ui, *args, **kwargs):
35 self.ui = ui
35 self.ui = ui
36 self._data = open(*args, **kwargs)
36 self._data = open(*args, **kwargs)
37 self.seek = self._data.seek
37 self.seek = self._data.seek
38 self.close = self._data.close
38 self.close = self._data.close
39 self.write = self._data.write
39 self.write = self._data.write
40 self.length = os.fstat(self._data.fileno()).st_size
40 self.length = os.fstat(self._data.fileno()).st_size
41 self._pos = 0
41 self._pos = 0
42 self._progress = self._makeprogress()
43
44 def _makeprogress(self):
42 # We pass double the max for total because we currently have
45 # We pass double the max for total because we currently have
43 # to send the bundle twice in the case of a server that
46 # to send the bundle twice in the case of a server that
44 # requires authentication. Since we can't know until we try
47 # requires authentication. Since we can't know until we try
45 # once whether authentication will be required, just lie to
48 # once whether authentication will be required, just lie to
46 # the user and maybe the push succeeds suddenly at 50%.
49 # the user and maybe the push succeeds suddenly at 50%.
47 self._progress = ui.makeprogress(
50 return self.ui.makeprogress(
48 _(b'sending'), unit=_(b'kb'), total=(self.length // 1024 * 2)
51 _(b'sending'), unit=_(b'kb'), total=(self.length // 1024 * 2)
49 )
52 )
50
53
51 def read(self, *args, **kwargs):
54 def read(self, *args, **kwargs):
52 ret = self._data.read(*args, **kwargs)
55 ret = self._data.read(*args, **kwargs)
53 if not ret:
56 if not ret:
54 self._progress.complete()
57 self._progress.complete()
55 return ret
58 return ret
56 self._pos += len(ret)
59 self._pos += len(ret)
57 self._progress.update(self._pos // 1024)
60 self._progress.update(self._pos // 1024)
58 return ret
61 return ret
59
62
60 def __enter__(self):
63 def __enter__(self):
61 return self
64 return self
62
65
63 def __exit__(self, exc_type, exc_val, exc_tb):
66 def __exit__(self, exc_type, exc_val, exc_tb):
64 self.close()
67 self.close()
65
68
66
69
67 # moved here from url.py to avoid a cycle
70 # moved here from url.py to avoid a cycle
68 def readauthforuri(ui, uri, user):
71 def readauthforuri(ui, uri, user):
69 uri = pycompat.bytesurl(uri)
72 uri = pycompat.bytesurl(uri)
70 # Read configuration
73 # Read configuration
71 groups = {}
74 groups = {}
72 for key, val in ui.configitems(b'auth'):
75 for key, val in ui.configitems(b'auth'):
73 if key in (b'cookiefile',):
76 if key in (b'cookiefile',):
74 continue
77 continue
75
78
76 if b'.' not in key:
79 if b'.' not in key:
77 ui.warn(_(b"ignoring invalid [auth] key '%s'\n") % key)
80 ui.warn(_(b"ignoring invalid [auth] key '%s'\n") % key)
78 continue
81 continue
79 group, setting = key.rsplit(b'.', 1)
82 group, setting = key.rsplit(b'.', 1)
80 gdict = groups.setdefault(group, {})
83 gdict = groups.setdefault(group, {})
81 if setting in (b'username', b'cert', b'key'):
84 if setting in (b'username', b'cert', b'key'):
82 val = util.expandpath(val)
85 val = util.expandpath(val)
83 gdict[setting] = val
86 gdict[setting] = val
84
87
85 # Find the best match
88 # Find the best match
86 scheme, hostpath = uri.split(b'://', 1)
89 scheme, hostpath = uri.split(b'://', 1)
87 bestuser = None
90 bestuser = None
88 bestlen = 0
91 bestlen = 0
89 bestauth = None
92 bestauth = None
90 for group, auth in pycompat.iteritems(groups):
93 for group, auth in pycompat.iteritems(groups):
91 if user and user != auth.get(b'username', user):
94 if user and user != auth.get(b'username', user):
92 # If a username was set in the URI, the entry username
95 # If a username was set in the URI, the entry username
93 # must either match it or be unset
96 # must either match it or be unset
94 continue
97 continue
95 prefix = auth.get(b'prefix')
98 prefix = auth.get(b'prefix')
96 if not prefix:
99 if not prefix:
97 continue
100 continue
98
101
99 prefixurl = util.url(prefix)
102 prefixurl = util.url(prefix)
100 if prefixurl.user and prefixurl.user != user:
103 if prefixurl.user and prefixurl.user != user:
101 # If a username was set in the prefix, it must match the username in
104 # If a username was set in the prefix, it must match the username in
102 # the URI.
105 # the URI.
103 continue
106 continue
104
107
105 # The URI passed in has been stripped of credentials, so erase the user
108 # The URI passed in has been stripped of credentials, so erase the user
106 # here to allow simpler matching.
109 # here to allow simpler matching.
107 prefixurl.user = None
110 prefixurl.user = None
108 prefix = bytes(prefixurl)
111 prefix = bytes(prefixurl)
109
112
110 p = prefix.split(b'://', 1)
113 p = prefix.split(b'://', 1)
111 if len(p) > 1:
114 if len(p) > 1:
112 schemes, prefix = [p[0]], p[1]
115 schemes, prefix = [p[0]], p[1]
113 else:
116 else:
114 schemes = (auth.get(b'schemes') or b'https').split()
117 schemes = (auth.get(b'schemes') or b'https').split()
115 if (
118 if (
116 (prefix == b'*' or hostpath.startswith(prefix))
119 (prefix == b'*' or hostpath.startswith(prefix))
117 and (
120 and (
118 len(prefix) > bestlen
121 len(prefix) > bestlen
119 or (
122 or (
120 len(prefix) == bestlen
123 len(prefix) == bestlen
121 and not bestuser
124 and not bestuser
122 and b'username' in auth
125 and b'username' in auth
123 )
126 )
124 )
127 )
125 and scheme in schemes
128 and scheme in schemes
126 ):
129 ):
127 bestlen = len(prefix)
130 bestlen = len(prefix)
128 bestauth = group, auth
131 bestauth = group, auth
129 bestuser = auth.get(b'username')
132 bestuser = auth.get(b'username')
130 if user and not bestuser:
133 if user and not bestuser:
131 auth[b'username'] = user
134 auth[b'username'] = user
132 return bestauth
135 return bestauth
General Comments 0
You need to be logged in to leave comments. Login now