19
19
from bzrlib.transport import Transport, register_transport
20
20
from bzrlib.errors import (TransportNotPossible, NoSuchFile,
21
NonRelativePath, TransportError, ConnectionError)
21
TransportError, ConnectionError)
23
23
from cStringIO import StringIO
24
import urllib, urllib2
27
27
from bzrlib.errors import BzrError, BzrCheckError
29
29
from bzrlib.trace import mutter
32
def extract_auth(url, password_manager):
34
Extract auth parameters from am HTTP/HTTPS url and add them to the given
35
password manager. Return the url, minus those auth parameters (which
38
assert url.startswith('http://') or url.startswith('https://')
39
scheme, host = url.split('//', 1)
41
host, path = host.split('/', 1)
47
auth, host = host.split('@', 1)
49
username, password = auth.split(':', 1)
51
username, password = auth, None
53
host, port = host.split(':', 1)
55
# FIXME: if password isn't given, should we ask for it?
56
if password is not None:
57
username = urllib.unquote(username)
58
password = urllib.unquote(password)
59
password_manager.add_password(None, host, username, password)
60
url = scheme + '//' + host + port + path
34
65
mutter("get_url %s" % url)
35
url_f = urllib2.urlopen(url)
66
manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
67
url = extract_auth(url, manager)
68
auth_handler = urllib2.HTTPBasicAuthHandler(manager)
69
opener = urllib2.build_opener(auth_handler)
70
url_f = opener.open(url)
38
class HttpTransportError(TransportError):
41
73
class HttpTransport(Transport):
42
74
"""This is the transport agent for http:// access.
119
151
cleaner if we just do an http HEAD request, and parse
123
f = get_url(self.abspath(relpath))
156
path = self.abspath(relpath)
124
158
# Without the read and then close()
125
159
# we tend to have busy sockets.
129
163
except urllib2.URLError, e:
164
mutter('url error code: %s for has url: %r', e.code, path)
130
165
if e.code == 404:
133
168
except IOError, e:
169
mutter('io error: %s %s for has url: %r',
170
e.errno, errno.errorcode.get(e.errno), path)
134
171
if e.errno == errno.ENOENT:
136
raise HttpTransportError(orig_error=e)
173
raise TransportError(orig_error=e)
138
175
def get(self, relpath, decode=False):
139
176
"""Get the file at the given relative path.
141
178
:param relpath: The relative path to the file
144
return get_url(self.abspath(relpath))
182
path = self.abspath(relpath)
145
184
except urllib2.HTTPError, e:
185
mutter('url error code: %s for has url: %r', e.code, path)
146
186
if e.code == 404:
147
raise NoSuchFile(msg = "Error retrieving %s: %s"
148
% (self.abspath(relpath), str(e)),
187
raise NoSuchFile(path, extra=e)
151
189
except (BzrError, IOError), e:
190
if hasattr(e, 'errno'):
191
mutter('io error: %s %s for has url: %r',
192
e.errno, errno.errorcode.get(e.errno), path)
193
if e.errno == errno.ENOENT:
194
raise NoSuchFile(path, extra=e)
152
195
raise ConnectionError(msg = "Error retrieving %s: %s"
153
196
% (self.abspath(relpath), str(e)),
156
def put(self, relpath, f):
199
def put(self, relpath, f, mode=None):
157
200
"""Copy the file-like or string object into the location.
159
202
:param relpath: Location to put the contents, relative to base.
162
205
raise TransportNotPossible('http PUT not supported')
164
def mkdir(self, relpath):
207
def mkdir(self, relpath, mode=None):
165
208
"""Create a directory at the given path."""
166
209
raise TransportNotPossible('http does not support mkdir()')
175
218
"""Copy the item at rel_from to the location at rel_to"""
176
219
raise TransportNotPossible('http does not support copy()')
178
def copy_to(self, relpaths, other, pb=None):
221
def copy_to(self, relpaths, other, mode=None, pb=None):
179
222
"""Copy a set of entries from self into another Transport.
181
224
:param relpaths: A list/generator of entries to be copied.
189
232
if isinstance(other, HttpTransport):
190
233
raise TransportNotPossible('http cannot be the target of copy_to()')
192
return super(HttpTransport, self).copy_to(relpaths, other, pb=pb)
235
return super(HttpTransport, self).copy_to(relpaths, other, mode=mode, pb=pb)
194
237
def move(self, rel_from, rel_to):
195
238
"""Move the item at rel_from to the location at rel_to"""