##// END OF EJS Templates
parsers: inline fields of dirstate values in C version...
parsers: inline fields of dirstate values in C version Previously, while unpacking the dirstate we'd create 3-4 new CPython objects for most dirstate values: - the state is a single character string, which is pooled by CPython - the mode is a new object if it isn't 0 due to being in the lookup set - the size is a new object if it is greater than 255 - the mtime is a new object if it isn't -1 due to being in the lookup set - the tuple to contain them all In some cases such as regular hg status, we actually look at all the objects. In other cases like hg add, hg status for a subdirectory, or hg status with the third-party hgwatchman enabled, we look at almost none of the objects. This patch eliminates most object creation in these cases by defining a custom C struct that is exposed to Python with an interface similar to a tuple. Only when tuple elements are actually requested are the respective objects created. The gains, where they're expected, are significant. The following tests are run against a working copy with over 270,000 files. parse_dirstate becomes significantly faster: $ hg perfdirstate before: wall 0.186437 comb 0.180000 user 0.160000 sys 0.020000 (best of 35) after: wall 0.093158 comb 0.100000 user 0.090000 sys 0.010000 (best of 95) and as a result, several commands benefit: $ time hg status # with hgwatchman enabled before: 0.42s user 0.14s system 99% cpu 0.563 total after: 0.34s user 0.12s system 99% cpu 0.471 total $ time hg add new-file before: 0.85s user 0.18s system 99% cpu 1.033 total after: 0.76s user 0.17s system 99% cpu 0.931 total There is a slight regression in regular status performance, but this is fixed in an upcoming patch.

File last commit:

r21543:21b3513d stable
r21809:e250b830 default
Show More
url.py
509 lines | 18.3 KiB | text/x-python | PythonLexer
Benoit Boissinot
factor out the url handling from httprepo...
r7270 # url.py - HTTP handling for mercurial
#
# Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
# Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Benoit Boissinot
factor out the url handling from httprepo...
r7270
Stéphane Klein
http: reuse authentication info after the first failed request (issue3567)...
r20964 import urllib, urllib2, httplib, os, socket, cStringIO, base64
Benoit Boissinot
factor out the url handling from httprepo...
r7270 from i18n import _
Augie Fackler
sslutil: extracted ssl methods from httpsconnection in url.py...
r14204 import keepalive, util, sslutil
Augie Fackler
url: use new http support if requested by the user...
r14244 import httpconnection as httpconnectionmod
Steve Borho
url: move [auth] parsing out into a utility function...
r13371
Benoit Boissinot
factor out the url handling from httprepo...
r7270 class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm):
def __init__(self, ui):
urllib2.HTTPPasswordMgrWithDefaultRealm.__init__(self)
self.ui = ui
def find_user_password(self, realm, authuri):
authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
self, realm, authuri)
user, passwd = authinfo
if user and passwd:
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 self._writedebug(user, passwd)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 return (user, passwd)
Patrick Mezard
hgweb: do not ignore [auth] if url has a username (issue2822)...
r15005 if not user or not passwd:
Patrick Mezard
http: pass user to readauthforuri() (fix 4a43e23b8c55)...
r15025 res = httpconnectionmod.readauthforuri(self.ui, authuri, user)
Steve Borho
url: return the matched authentication group name from readauthforuri()...
r13372 if res:
group, auth = res
Henrik Stuart
url: support client certificate files over HTTPS (issue643)...
r8847 user, passwd = auth.get('username'), auth.get('password')
Steve Borho
url: return the matched authentication group name from readauthforuri()...
r13372 self.ui.debug("using auth.%s.* for authentication\n" % group)
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 if not user or not passwd:
Lucas Moscovicz
url: added authuri when login information is requested (issue3209)...
r20291 u = util.url(authuri)
u.query = None
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 if not self.ui.interactive():
Lucas Moscovicz
url: added authuri when login information is requested (issue3209)...
r20291 raise util.Abort(_('http authorization required for %s') %
util.hidepassword(str(u)))
Benoit Boissinot
factor out the url handling from httprepo...
r7270
Lucas Moscovicz
url: added authuri when login information is requested (issue3209)...
r20291 self.ui.write(_("http authorization required for %s\n") %
util.hidepassword(str(u)))
timeless
url: show realm/user when asking for username/password
r12862 self.ui.write(_("realm: %s\n") % realm)
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 if user:
timeless
url: show realm/user when asking for username/password
r12862 self.ui.write(_("user: %s\n") % user)
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 else:
user = self.ui.prompt(_("user:"), default=None)
Benoit Boissinot
factor out the url handling from httprepo...
r7270
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 if not passwd:
passwd = self.ui.getpass()
Benoit Boissinot
factor out the url handling from httprepo...
r7270
self.add_password(realm, authuri, user, passwd)
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 self._writedebug(user, passwd)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 return (user, passwd)
Sune Foldager
allow http authentication information to be specified in the configuration
r8333 def _writedebug(self, user, passwd):
msg = _('http auth: user %s, password %s\n')
self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
Patrick Mezard
http: pass user to readauthforuri() (fix 4a43e23b8c55)...
r15025 def find_stored_password(self, authuri):
return urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
self, None, authuri)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 class proxyhandler(urllib2.ProxyHandler):
def __init__(self, ui):
proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
# XXX proxyauthinfo = None
if proxyurl:
# proxy can be proper url or host[:port]
if not (proxyurl.startswith('http:') or
proxyurl.startswith('https:')):
proxyurl = 'http://' + proxyurl + '/'
Brodie Rao
url: move URL parsing functions into util to improve startup time...
r14076 proxy = util.url(proxyurl)
Brodie Rao
url: use url.url in proxyhandler
r13820 if not proxy.user:
proxy.user = ui.config("http_proxy", "user")
proxy.passwd = ui.config("http_proxy", "passwd")
Benoit Boissinot
factor out the url handling from httprepo...
r7270
# see if we should use a proxy for this url
Matt Mackall
many, many trivial check-code fixups
r10282 no_list = ["localhost", "127.0.0.1"]
Benoit Boissinot
factor out the url handling from httprepo...
r7270 no_list.extend([p.lower() for
p in ui.configlist("http_proxy", "no")])
no_list.extend([p.strip().lower() for
p in os.getenv("no_proxy", '').split(',')
if p.strip()])
# "http_proxy.always" config is for running tests on localhost
if ui.configbool("http_proxy", "always"):
self.no_list = []
else:
self.no_list = no_list
Brodie Rao
url: use url.url in proxyhandler
r13820 proxyurl = str(proxy)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 proxies = {'http': proxyurl, 'https': proxyurl}
Martin Geisler
do not attempt to translate ui.debug output
r9467 ui.debug('proxying through http://%s:%s\n' %
Brodie Rao
url: use url.url in proxyhandler
r13820 (proxy.host, proxy.port))
Benoit Boissinot
factor out the url handling from httprepo...
r7270 else:
proxies = {}
# urllib2 takes proxy values from the environment and those
Renato Cunha
url: Remove the proxy env variables only when needed (issue2451)...
r15077 # will take precedence if found. So, if there's a config entry
# defining a proxy, drop the environment ones
if ui.config("http_proxy", "host"):
for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
try:
if env in os.environ:
del os.environ[env]
except OSError:
pass
Benoit Boissinot
factor out the url handling from httprepo...
r7270
urllib2.ProxyHandler.__init__(self, proxies)
self.ui = ui
def proxy_open(self, req, proxy, type_):
host = req.get_host().split(':')[0]
Matt Mackall
proxy: allow wildcards in the no proxy list (issue1821)
r19535 for e in self.no_list:
if host == e:
return None
if e.startswith('*.') and host.endswith(e[2:]):
return None
if e.startswith('.') and host.endswith(e[1:]):
return None
Benoit Boissinot
factor out the url handling from httprepo...
r7270
# work around a bug in Python < 2.4.2
# (it leaves a "\n" at the end of Proxy-authorization headers)
baseclass = req.__class__
class _request(baseclass):
def add_header(self, key, val):
if key.lower() == 'proxy-authorization':
val = val.strip()
return baseclass.add_header(self, key, val)
req.__class__ = _request
return urllib2.ProxyHandler.proxy_open(self, req, proxy, type_)
Mads Kiilerich
url: refactor _gen_sendfile
r13420 def _gen_sendfile(orgsend):
Benoit Boissinot
factor out the url handling from httprepo...
r7270 def _sendfile(self, data):
# send a file
Augie Fackler
url: use new http support if requested by the user...
r14244 if isinstance(data, httpconnectionmod.httpsendfile):
Benoit Boissinot
factor out the url handling from httprepo...
r7270 # if auth required, some data sent twice, so rewind here
data.seek(0)
for chunk in util.filechunkiter(data):
Mads Kiilerich
url: refactor _gen_sendfile
r13420 orgsend(self, chunk)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 else:
Mads Kiilerich
url: refactor _gen_sendfile
r13420 orgsend(self, data)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 return _sendfile
Augie Fackler
url: replace uses of hasattr with safehasattr or getattr
r14964 has_https = util.safehasattr(urllib2, 'HTTPSHandler')
Henrik Stuart
url: use CONNECT for HTTPS connections through HTTP proxy (issue967)...
r8590 if has_https:
try:
Henrik Stuart
url: SSL server certificate verification using web.cacerts file (issue1174)
r10409 _create_connection = socket.create_connection
Matt Mackall
ssl: fix compatibility with pre-2.6 Python
r10411 except AttributeError:
Benoit Boissinot
url: fix python < 2.6 with ssl installed...
r10482 _GLOBAL_DEFAULT_TIMEOUT = object()
Henrik Stuart
url: SSL server certificate verification using web.cacerts file (issue1174)
r10409 def _create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
source_address=None):
# lifted from Python 2.6
msg = "getaddrinfo returns an empty list"
host, port = address
for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
sock.connect(sa)
return sock
except socket.error, msg:
if sock is not None:
sock.close()
Augie Fackler
url: clean up use of two-argument raise...
r18176 raise socket.error(msg)
Henrik Stuart
url: SSL server certificate verification using web.cacerts file (issue1174)
r10409
Benoit Boissinot
factor out the url handling from httprepo...
r7270 class httpconnection(keepalive.HTTPConnection):
# must be able to send big bundle as stream.
Mads Kiilerich
url: refactor _gen_sendfile
r13420 send = _gen_sendfile(keepalive.HTTPConnection.send)
Benoit Boissinot
factor out the url handling from httprepo...
r7270
Henrik Stuart
url: use CONNECT for HTTPS connections through HTTP proxy (issue967)...
r8590 def connect(self):
Benoit Boissinot
url: proxy handling, simplify and correctly deal with IPv6...
r10415 if has_https and self.realhostport: # use CONNECT proxy
Henrik Stuart
url: use CONNECT for HTTPS connections through HTTP proxy (issue967)...
r8590 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.host, self.port))
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 if _generic_proxytunnel(self):
Mads Kiilerich
fix trivial spelling errors
r17424 # we do not support client X.509 certificates
Augie Fackler
sslutil: extracted ssl methods from httpsconnection in url.py...
r14204 self.sock = sslutil.ssl_wrap_socket(self.sock, None, None)
Henrik Stuart
url: use CONNECT for HTTPS connections through HTTP proxy (issue967)...
r8590 else:
keepalive.HTTPConnection.connect(self)
def getresponse(self):
proxyres = getattr(self, 'proxyres', None)
if proxyres:
if proxyres.will_close:
self.close()
self.proxyres = None
return proxyres
return keepalive.HTTPConnection.getresponse(self)
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 # general transaction handler to support different ways to handle
# HTTPS proxying before and after Python 2.6.3.
def _generic_start_transaction(handler, h, req):
Augie Fackler
url: replace uses of hasattr with safehasattr or getattr
r14964 tunnel_host = getattr(req, '_tunnel_host', None)
if tunnel_host:
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 if tunnel_host[:7] not in ['http://', 'https:/']:
tunnel_host = 'https://' + tunnel_host
new_tunnel = True
else:
tunnel_host = req.get_selector()
new_tunnel = False
if new_tunnel or tunnel_host == req.get_full_url(): # has proxy
Brodie Rao
url: move URL parsing functions into util to improve startup time...
r14076 u = util.url(tunnel_host)
Brodie Rao
url: use url.url in proxyhandler
r13820 if new_tunnel or u.scheme == 'https': # only use CONNECT for HTTPS
h.realhostport = ':'.join([u.host, (u.port or '443')])
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 h.headers = req.headers.copy()
h.headers.update(handler.parent.addheaders)
return
Benoit Boissinot
url: proxy handling, simplify and correctly deal with IPv6...
r10415 h.realhostport = None
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 h.headers = None
def _generic_proxytunnel(self):
proxyheaders = dict(
[(x, self.headers[x]) for x in self.headers
if x.lower().startswith('proxy-')])
Benoit Boissinot
url: proxy handling, simplify and correctly deal with IPv6...
r10415 self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport)
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 for header in proxyheaders.iteritems():
self.send('%s: %s\r\n' % header)
self.send('\r\n')
# majority of the following code is duplicated from
# httplib.HTTPConnection as there are no adequate places to
# override functions to provide the needed functionality
res = self.response_class(self.sock,
strict=self.strict,
method=self._method)
while True:
version, status, reason = res._read_status()
if status != httplib.CONTINUE:
break
while True:
skip = res.fp.readline().strip()
if not skip:
break
res.status = status
res.reason = reason.strip()
if res.status == 200:
while True:
line = res.fp.readline()
if line == '\r\n':
break
return True
if version == 'HTTP/1.0':
res.version = 10
elif version.startswith('HTTP/1.'):
res.version = 11
elif version == 'HTTP/0.9':
res.version = 9
else:
raise httplib.UnknownProtocol(version)
if res.version == 9:
res.length = None
res.chunked = 0
res.will_close = 1
res.msg = httplib.HTTPMessage(cStringIO.StringIO())
return False
res.msg = httplib.HTTPMessage(res.fp)
res.msg.fp = None
# are we using the chunked-style of transfer encoding?
trenc = res.msg.getheader('transfer-encoding')
if trenc and trenc.lower() == "chunked":
res.chunked = 1
res.chunk_left = None
else:
res.chunked = 0
# will the connection close at the end of the response?
res.will_close = res._check_close()
# do we have a Content-Length?
Mads Kiilerich
avoid using abbreviations that look like spelling errors
r17428 # NOTE: RFC 2616, section 4.4, #3 says we ignore this if
# transfer-encoding is "chunked"
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 length = res.msg.getheader('content-length')
if length and not res.chunked:
try:
res.length = int(length)
except ValueError:
res.length = None
else:
if res.length < 0: # ignore nonsensical negative lengths
res.length = None
else:
res.length = None
# does the body have a fixed length? (of zero)
if (status == httplib.NO_CONTENT or status == httplib.NOT_MODIFIED or
100 <= status < 200 or # 1xx codes
res._method == 'HEAD'):
res.length = 0
# if the connection remains open, and we aren't using chunked, and
# a content-length was not provided, then assume that the connection
# WILL close.
if (not res.will_close and
not res.chunked and
res.length is None):
res.will_close = 1
self.proxyres = res
return False
Benoit Boissinot
factor out the url handling from httprepo...
r7270 class httphandler(keepalive.HTTPHandler):
def http_open(self, req):
return self.do_open(httpconnection, req)
Henrik Stuart
url: use CONNECT for HTTPS connections through HTTP proxy (issue967)...
r8590 def _start_transaction(self, h, req):
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 _generic_start_transaction(self, h, req)
Henrik Stuart
url: use CONNECT for HTTPS connections through HTTP proxy (issue967)...
r8590 return keepalive.HTTPHandler._start_transaction(self, h, req)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 if has_https:
Mads Kiilerich
url: merge BetterHTTPS with httpsconnection to get some proxy https validation
r13424 class httpsconnection(httplib.HTTPSConnection):
response_class = keepalive.HTTPResponse
# must be able to send big bundle as stream.
send = _gen_sendfile(keepalive.safesend)
getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection)
Augie Fackler
keepalive: handle broken pipes gracefully during large POSTs
r9726
Henrik Stuart
url: SSL server certificate verification using web.cacerts file (issue1174)
r10409 def connect(self):
Mads Kiilerich
url: always create BetterHTTPS connections the same way
r13422 self.sock = _create_connection((self.host, self.port))
Mads Kiilerich
url: refactor BetterHTTPS.connect
r13421 host = self.host
Mads Kiilerich
url: merge BetterHTTPS with httpsconnection to get some proxy https validation
r13424 if self.realhostport: # use CONNECT proxy
Alexander Solovyov
remove unused imports and variables
r14064 _generic_proxytunnel(self)
Mads Kiilerich
url: merge BetterHTTPS with httpsconnection to get some proxy https validation
r13424 host = self.realhostport.rsplit(':', 1)[0]
Augie Fackler
sslutil: extracted ssl methods from httpsconnection in url.py...
r14204 self.sock = sslutil.ssl_wrap_socket(
self.sock, self.key_file, self.cert_file,
**sslutil.sslkwargs(self.ui, host))
sslutil.validator(self.ui, host)(self.sock)
Henrik Stuart
url: SSL server certificate verification using web.cacerts file (issue1174)
r10409
Benoit Boissinot
factor out the url handling from httprepo...
r7270 class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
Henrik Stuart
url: support client certificate files over HTTPS (issue643)...
r8847 def __init__(self, ui):
keepalive.KeepAliveHandler.__init__(self)
urllib2.HTTPSHandler.__init__(self)
self.ui = ui
self.pwmgr = passwordmgr(self.ui)
Henrik Stuart
url: generalise HTTPS proxy handling to accomodate Python changes...
r9852 def _start_transaction(self, h, req):
_generic_start_transaction(self, h, req)
return keepalive.KeepAliveHandler._start_transaction(self, h, req)
Benoit Boissinot
factor out the url handling from httprepo...
r7270 def https_open(self, req):
Patrick Mezard
http: pass user to readauthforuri() (fix 4a43e23b8c55)...
r15025 # req.get_full_url() does not contain credentials and we may
# need them to match the certificates.
url = req.get_full_url()
user, password = self.pwmgr.find_stored_password(url)
res = httpconnectionmod.readauthforuri(self.ui, url, user)
Steve Borho
url: return the matched authentication group name from readauthforuri()...
r13372 if res:
group, auth = res
self.auth = auth
self.ui.debug("using auth.%s.* for authentication\n" % group)
else:
self.auth = None
Henrik Stuart
url: support client certificate files over HTTPS (issue643)...
r8847 return self.do_open(self._makeconnection, req)
Benoit Boissinot
url: httplib.HTTPSConnection already handles IPv6 and port parsing fine
r10408 def _makeconnection(self, host, port=None, *args, **kwargs):
Henrik Stuart
url: support client certificate files over HTTPS (issue643)...
r8847 keyfile = None
certfile = None
Benoit Boissinot
url: *args argument is a tuple, not a list (found by pylint)...
r10511 if len(args) >= 1: # key_file
keyfile = args[0]
if len(args) >= 2: # cert_file
certfile = args[1]
args = args[2:]
Henrik Stuart
url: support client certificate files over HTTPS (issue643)...
r8847
# if the user has specified different key/cert files in
# hgrc, we prefer these
if self.auth and 'key' in self.auth and 'cert' in self.auth:
keyfile = self.auth['key']
certfile = self.auth['cert']
Brodie Rao
cleanup: eradicate long lines
r16683 conn = httpsconnection(host, port, keyfile, certfile, *args,
**kwargs)
Henrik Stuart
url: SSL server certificate verification using web.cacerts file (issue1174)
r10409 conn.ui = self.ui
return conn
Benoit Boissinot
factor out the url handling from httprepo...
r7270
class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler):
Mads Kiilerich
http digest auth: reset redirect counter on new requests (issue2255)...
r11457 def __init__(self, *args, **kwargs):
urllib2.HTTPDigestAuthHandler.__init__(self, *args, **kwargs)
self.retried_req = None
def reset_retry_count(self):
# Python 2.6.5 will call this on 401 or 407 errors and thus loop
# forever. We disable reset_retry_count completely and reset in
# http_error_auth_reqed instead.
pass
Benoit Boissinot
factor out the url handling from httprepo...
r7270 def http_error_auth_reqed(self, auth_header, host, req, headers):
Mads Kiilerich
http digest auth: reset redirect counter on new requests (issue2255)...
r11457 # Reset the retry counter once for each request.
if req is not self.retried_req:
self.retried_req = req
self.retried = 0
# In python < 2.5 AbstractDigestAuthHandler raises a ValueError if
# it doesn't know about the auth type requested. This can happen if
# somebody is using BasicAuth and types a bad password.
Benoit Boissinot
factor out the url handling from httprepo...
r7270 try:
return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed(
self, auth_header, host, req, headers)
except ValueError, inst:
arg = inst.args[0]
if arg.startswith("AbstractDigestAuthHandler doesn't know "):
return
raise
Wagner Bruna
http basic auth: reset redirect counter on new requests (issue2255)...
r11844 class httpbasicauthhandler(urllib2.HTTPBasicAuthHandler):
def __init__(self, *args, **kwargs):
Stéphane Klein
http: reuse authentication info after the first failed request (issue3567)...
r20964 self.auth = None
Wagner Bruna
http basic auth: reset redirect counter on new requests (issue2255)...
r11844 urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
self.retried_req = None
Stéphane Klein
http: reuse authentication info after the first failed request (issue3567)...
r20964 def http_request(self, request):
if self.auth:
request.add_unredirected_header(self.auth_header, self.auth)
return request
def https_request(self, request):
if self.auth:
request.add_unredirected_header(self.auth_header, self.auth)
return request
Wagner Bruna
http basic auth: reset redirect counter on new requests (issue2255)...
r11844 def reset_retry_count(self):
# Python 2.6.5 will call this on 401 or 407 errors and thus loop
# forever. We disable reset_retry_count completely and reset in
# http_error_auth_reqed instead.
pass
def http_error_auth_reqed(self, auth_header, host, req, headers):
# Reset the retry counter once for each request.
if req is not self.retried_req:
self.retried_req = req
self.retried = 0
return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(
self, auth_header, host, req, headers)
Stéphane Klein
http: reuse authentication info after the first failed request (issue3567)...
r20964 def retry_http_basic_auth(self, host, req, realm):
user, pw = self.passwd.find_user_password(realm, req.get_full_url())
if pw is not None:
raw = "%s:%s" % (user, pw)
auth = 'Basic %s' % base64.b64encode(raw).strip()
if req.headers.get(self.auth_header, None) == auth:
return None
self.auth = auth
req.add_unredirected_header(self.auth_header, auth)
return self.parent.open(req)
else:
return None
Henrik Stuart
url: add support for custom handlers in extensions
r9347 handlerfuncs = []
Benoit Boissinot
factor out the url handling from httprepo...
r7270 def opener(ui, authinfo=None):
'''
construct an opener suitable for urllib2
authinfo will be added to the password manager
'''
Augie Fackler
url: use new http support if requested by the user...
r14244 if ui.configbool('ui', 'usehttp2', False):
handlers = [httpconnectionmod.http2handler(ui, passwordmgr(ui))]
else:
handlers = [httphandler()]
if has_https:
handlers.append(httpshandler(ui))
Benoit Boissinot
factor out the url handling from httprepo...
r7270
handlers.append(proxyhandler(ui))
passmgr = passwordmgr(ui)
if authinfo is not None:
passmgr.add_password(*authinfo)
user, passwd = authinfo[2:4]
Martin Geisler
do not attempt to translate ui.debug output
r9467 ui.debug('http auth: user %s, password %s\n' %
Benoit Boissinot
factor out the url handling from httprepo...
r7270 (user, passwd and '*' * len(passwd) or 'not set'))
Wagner Bruna
http basic auth: reset redirect counter on new requests (issue2255)...
r11844 handlers.extend((httpbasicauthhandler(passmgr),
Benoit Boissinot
factor out the url handling from httprepo...
r7270 httpdigestauthhandler(passmgr)))
Henrik Stuart
url: add support for custom handlers in extensions
r9347 handlers.extend([h(ui, passmgr) for h in handlerfuncs])
Benoit Boissinot
factor out the url handling from httprepo...
r7270 opener = urllib2.build_opener(*handlers)
# 1.0 here is the _protocol_ version
opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
return opener
Brodie Rao
url: use url.url in url.open()
r13818 def open(ui, url_, data=None):
Brodie Rao
url: move URL parsing functions into util to improve startup time...
r14076 u = util.url(url_)
Brodie Rao
url: use url.url in url.open()
r13818 if u.scheme:
u.scheme = u.scheme.lower()
url_, authinfo = u.authinfo()
else:
path = util.normpath(os.path.abspath(url_))
url_ = 'file://' + urllib.pathname2url(path)
Patrick Mezard
url: fix file:// URL handling
r7284 authinfo = None
Brodie Rao
url: use url.url in url.open()
r13818 return opener(ui, authinfo).open(url_, data)