httpconnection.py
107 lines
| 3.5 KiB
| text/x-python
|
PythonLexer
/ mercurial / httpconnection.py
|
r14244 | # httpconnection.py - urllib2 handler for new http support | ||
# | ||||
# 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> | ||||
# Copyright 2011 Google, Inc. | ||||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | ||||
|
r27521 | |||
from __future__ import absolute_import | ||||
import os | ||||
|
r14244 | |||
|
r27521 | from .i18n import _ | ||
from . import ( | ||||
util, | ||||
) | ||||
|
r14244 | |||
|
r28883 | urlerr = util.urlerr | ||
urlreq = util.urlreq | ||||
|
r14244 | # moved here from url.py to avoid a cycle | ||
class httpsendfile(object): | ||||
"""This is a wrapper around the objects returned by python's "open". | ||||
|
r15152 | Its purpose is to send file-like objects via HTTP. | ||
It do however not define a __len__ attribute because the length | ||||
might be more than Py_ssize_t can handle. | ||||
|
r14244 | """ | ||
def __init__(self, ui, *args, **kwargs): | ||||
self.ui = ui | ||||
self._data = open(*args, **kwargs) | ||||
self.seek = self._data.seek | ||||
self.close = self._data.close | ||||
self.write = self._data.write | ||||
|
r15152 | self.length = os.fstat(self._data.fileno()).st_size | ||
|
r14244 | self._pos = 0 | ||
|
r15791 | self._total = self.length // 1024 * 2 | ||
|
r14244 | |||
def read(self, *args, **kwargs): | ||||
|
r31488 | ret = self._data.read(*args, **kwargs) | ||
if not ret: | ||||
|
r14244 | self.ui.progress(_('sending'), None) | ||
|
r31488 | return ret | ||
|
r14244 | self._pos += len(ret) | ||
# We pass double the max for total because we currently have | ||||
# to send the bundle twice in the case of a server that | ||||
# requires authentication. Since we can't know until we try | ||||
# once whether authentication will be required, just lie to | ||||
# the user and maybe the push succeeds suddenly at 50%. | ||||
|
r15791 | self.ui.progress(_('sending'), self._pos // 1024, | ||
|
r14244 | unit=_('kb'), total=self._total) | ||
return ret | ||||
|
r30142 | def __enter__(self): | ||
return self | ||||
def __exit__(self, exc_type, exc_val, exc_tb): | ||||
self.close() | ||||
|
r14244 | # moved here from url.py to avoid a cycle | ||
|
r15025 | def readauthforuri(ui, uri, user): | ||
|
r14244 | # Read configuration | ||
|
r31300 | groups = {} | ||
|
r14244 | for key, val in ui.configitems('auth'): | ||
|
r31935 | if key in ('cookiefile',): | ||
continue | ||||
|
r14244 | if '.' not in key: | ||
ui.warn(_("ignoring invalid [auth] key '%s'\n") % key) | ||||
continue | ||||
group, setting = key.rsplit('.', 1) | ||||
|
r31300 | gdict = groups.setdefault(group, {}) | ||
|
r14244 | if setting in ('username', 'cert', 'key'): | ||
val = util.expandpath(val) | ||||
gdict[setting] = val | ||||
# Find the best match | ||||
|
r25206 | scheme, hostpath = uri.split('://', 1) | ||
|
r15005 | bestuser = None | ||
|
r14244 | bestlen = 0 | ||
bestauth = None | ||||
|
r31300 | for group, auth in groups.iteritems(): | ||
|
r15005 | if user and user != auth.get('username', user): | ||
# If a username was set in the URI, the entry username | ||||
# must either match it or be unset | ||||
continue | ||||
|
r14244 | prefix = auth.get('prefix') | ||
if not prefix: | ||||
continue | ||||
p = prefix.split('://', 1) | ||||
if len(p) > 1: | ||||
schemes, prefix = [p[0]], p[1] | ||||
else: | ||||
schemes = (auth.get('schemes') or 'https').split() | ||||
if (prefix == '*' or hostpath.startswith(prefix)) and \ | ||||
|
r15005 | (len(prefix) > bestlen or (len(prefix) == bestlen and \ | ||
not bestuser and 'username' in auth)) \ | ||||
and scheme in schemes: | ||||
|
r14244 | bestlen = len(prefix) | ||
bestauth = group, auth | ||||
|
r15005 | bestuser = auth.get('username') | ||
if user and not bestuser: | ||||
auth['username'] = user | ||||
|
r14244 | return bestauth | ||