6
6
from bzrlib.transport import Transport, register_transport, \
7
7
TransportNotPossible, NoSuchFile, NonRelativePath, \
9
import os, errno, time, asyncore
10
10
from cStringIO import StringIO
13
from bzrlib.errors import BzrError, BzrCheckError
14
from bzrlib.branch import Branch, BZR_BRANCH_FORMAT
15
from bzrlib.trace import mutter
17
from effbot.org.http_client import do_request
19
class HttpTransportError(TransportError):
22
class simple_wait_consumer(object):
23
"""This is a consumer object for effbot.org downloading.
25
Basically, it takes a management object, which it expects to
26
fill itself (eventually) if it waits long enough.
27
So it loops to wait for the download to finish, until it
30
def __init__(self, url, extra_headers=None):
31
self.buffer = StringIO()
36
do_request(self.url, self)
41
# Try and break cyclical loops
42
if self.ok and (self.status is None or self.status[1] == '200'):
13
from errors import BzrError, BzrCheckError
14
from branch import Branch, BZR_BRANCH_FORMAT
15
from trace import mutter
17
# velocitynet.com.au transparently proxies connections and thereby
18
# breaks keep-alive -- sucks!
21
ENABLE_URLGRABBER = True
26
import urlgrabber.keepalive
27
import urlgrabber.grabber
28
urlgrabber.keepalive.DEBUG = 0
29
def get_url(path, compressed=False):
34
mutter("grab url %s" % url)
35
url_f = urlgrabber.urlopen(url, keepalive=1, close_connection=0)
39
return gzip.GzipFile(fileobj=StringIO(url_f.read()))
40
except urllib2.URLError, e:
41
raise BzrError("remote fetch failed: %r: %s" % (url, e))
42
except urlgrabber.grabber.URLGrabError, e:
43
raise BzrError("remote fetch failed: %r: %s" % (url, e))
45
def get_url(url, compressed=False):
49
mutter("get_url %s" % url)
50
url_f = urllib2.urlopen(url)
52
return gzip.GzipFile(fileobj=StringIO(url_f.read()))
46
raise NoSuchFile('Download of %r failed: %r'
47
% (self.url, self.status))
54
self.buffer.write(data)
59
def http(self, ok, connection, *args, **kwargs):
60
mutter('simple-wait-consumer: %s, %s, %s, %s'
61
% (self.url, ok, connection.status, connection.header))
65
self.status = connection.status
67
56
def _find_remote_root(url):
68
57
"""Return the prefix URL that corresponds to the branch root."""
141
133
TODO: HttpTransport.has() should use a HEAD request,
142
134
not a full GET request.
144
c = simple_wait_consumer(self.abspath(relpath))
147
# We might also look at c.status, but it doesn't seem to always be set
148
# c.status is of the form ["HTTP/1.0", "200", "OK\r\n"] we could
149
# check both the 200 and the OK.
150
if c.ok and (c.status is None or c.status[1] == '200'):
137
f = get_url(self.abspath(relpath))
141
except urllib2.URLError:
144
if e.errno == errno.ENOENT:
146
raise HttpTransportError(orig_error=e)
154
def get(self, relpath):
148
def get(self, relpath, decode=False):
155
149
"""Get the file at the given relative path.
157
151
:param relpath: The relative path to the file
159
c = simple_wait_consumer(self.abspath(relpath))
162
### def get_multi(self, relpaths, pb=None):
163
### """Get a list of file-like objects, one for each entry in relpaths.
165
### :param relpaths: A list of relative paths.
166
### :param decode: If True, assume the file is utf-8 encoded and
167
### decode it into Unicode
168
### :param pb: An optional ProgressBar for indicating percent done.
169
### :return: A list or generator of file-like objects
172
### for relpath in relpaths:
173
### consumers.append(simple_wait_consumer(self.abspath(relpath)))
174
### total = self._get_total(consumers)
176
### for c in consumers:
177
### self._update_pb(pb, 'get', count, total)
154
return get_url(self.abspath(relpath))
156
raise NoSuchFile(orig_error=e)
157
except urllib2.URLError, e:
158
raise NoSuchFile(orig_error=e)
160
raise NoSuchFile(orig_error=e)
162
raise HttpTransportError(orig_error=e)
181
164
def put(self, relpath, f):
182
165
"""Copy the file-like or string object into the location.