~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http.py

  • Committer: abentley
  • Date: 2005-10-14 03:50:50 UTC
  • mto: (1185.25.1)
  • mto: This revision was merged to the branch mainline in revision 1460.
  • Revision ID: abentley@lappy-20051014035050-d779472ccb599a51
semi-broke merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
from bzrlib.transport import Transport, register_transport
20
20
from bzrlib.errors import (TransportNotPossible, NoSuchFile, 
21
 
                           NonRelativePath, TransportError, ConnectionError)
 
21
                           NonRelativePath, TransportError)
22
22
import os, errno
23
23
from cStringIO import StringIO
24
24
import urllib2
28
28
from bzrlib.branch import Branch
29
29
from bzrlib.trace import mutter
30
30
 
 
31
# velocitynet.com.au transparently proxies connections and thereby
 
32
# breaks keep-alive -- sucks!
 
33
 
31
34
 
32
35
def get_url(url):
33
36
    import urllib2
34
 
    mutter("get_url %s", url)
 
37
    mutter("get_url %s" % url)
35
38
    url_f = urllib2.urlopen(url)
36
39
    return url_f
37
40
 
74
77
        """Return the full url to the given relative path.
75
78
        This can be supplied with a string or a list
76
79
        """
77
 
        assert isinstance(relpath, basestring)
78
80
        if isinstance(relpath, basestring):
79
 
            relpath_parts = relpath.split('/')
80
 
        else:
81
 
            # TODO: Don't call this with an array - no magic interfaces
82
 
            relpath_parts = relpath[:]
83
 
        if len(relpath_parts) > 1:
84
 
            if relpath_parts[0] == '':
85
 
                raise ValueError("path %r within branch %r seems to be absolute"
86
 
                                 % (relpath, self._path))
87
 
            if relpath_parts[-1] == '':
88
 
                raise ValueError("path %r within branch %r seems to be a directory"
89
 
                                 % (relpath, self._path))
 
81
            relpath = [relpath]
90
82
        basepath = self._path.split('/')
91
83
        if len(basepath) > 0 and basepath[-1] == '':
92
84
            basepath = basepath[:-1]
93
 
        for p in relpath_parts:
 
85
 
 
86
        for p in relpath:
94
87
            if p == '..':
95
 
                if len(basepath) == 0:
 
88
                if len(basepath) < 0:
96
89
                    # In most filesystems, a request for the parent
97
90
                    # of root, just returns root.
98
91
                    continue
99
 
                basepath.pop()
100
 
            elif p == '.' or p == '':
 
92
                if len(basepath) > 0:
 
93
                    basepath.pop()
 
94
            elif p == '.':
101
95
                continue # No-op
102
96
            else:
103
97
                basepath.append(p)
 
98
 
104
99
        # Possibly, we could use urlparse.urljoin() here, but
105
100
        # I'm concerned about when it chooses to strip the last
106
101
        # portion of the path, and when it doesn't.
108
103
        return urlparse.urlunparse((self._proto,
109
104
                self._host, path, '', '', ''))
110
105
 
 
106
    def relpath(self, abspath):
 
107
        if not abspath.startswith(self.base):
 
108
            raise NonRelativePath('path %r is not under base URL %r'
 
109
                           % (abspath, self.base))
 
110
        pl = len(self.base)
 
111
        return abspath[pl:].lstrip('/')
 
112
 
111
113
    def has(self, relpath):
112
114
        """Does the target location exist?
113
115
 
126
128
            f.read()
127
129
            f.close()
128
130
            return True
129
 
        except urllib2.URLError, e:
130
 
            if e.code == 404:
131
 
                return False
132
 
            raise
 
131
        except BzrError:
 
132
            return False
 
133
        except urllib2.URLError:
 
134
            return False
133
135
        except IOError, e:
134
136
            if e.errno == errno.ENOENT:
135
137
                return False
142
144
        """
143
145
        try:
144
146
            return get_url(self.abspath(relpath))
145
 
        except urllib2.HTTPError, e:
146
 
            if e.code == 404:
147
 
                raise NoSuchFile(msg = "Error retrieving %s: %s" 
148
 
                                 % (self.abspath(relpath), str(e)),
149
 
                                 orig_error=e)
150
 
            raise
151
 
        except (BzrError, IOError), e:
152
 
            raise ConnectionError(msg = "Error retrieving %s: %s" 
153
 
                             % (self.abspath(relpath), str(e)),
 
147
        except (BzrError, urllib2.URLError, IOError), e:
 
148
            raise NoSuchFile(msg = "Error retrieving %s" 
 
149
                             % self.abspath(relpath),
154
150
                             orig_error=e)
155
151
 
 
152
    def get_partial(self, relpath, start, length=None):
 
153
        """Get just part of a file.
 
154
 
 
155
        :param relpath: Path to the file, relative to base
 
156
        :param start: The starting position to read from
 
157
        :param length: The length to read. A length of None indicates
 
158
                       read to the end of the file.
 
159
        :return: A file-like object containing at least the specified bytes.
 
160
                 Some implementations may return objects which can be read
 
161
                 past this length, but this is not guaranteed.
 
162
        """
 
163
        # TODO: You can make specialized http requests for just
 
164
        # a portion of the file. Figure out how to do that.
 
165
        # For now, urllib2 returns files that cannot seek() so
 
166
        # we just read bytes off the beginning, until we
 
167
        # get to the point that we care about.
 
168
        f = self.get(relpath)
 
169
        # TODO: read in smaller chunks, in case things are
 
170
        # buffered internally.
 
171
        f.read(start)
 
172
        return f
 
173
 
156
174
    def put(self, relpath, f):
157
175
        """Copy the file-like or string object into the location.
158
176
 
228
246
        :return: A lock object, which should be passed to Transport.unlock()
229
247
        """
230
248
        raise TransportNotPossible('http does not support lock_write()')
 
249
 
 
250
register_transport('http://', HttpTransport)
 
251
register_transport('https://', HttpTransport)