~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http.py

Exclude more files from dumb-rsync upload

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)
 
21
                           NonRelativePath, TransportError, ConnectionError)
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
 
 
34
31
 
35
32
def get_url(url):
36
33
    import urllib2
77
74
        """Return the full url to the given relative path.
78
75
        This can be supplied with a string or a list
79
76
        """
 
77
        assert isinstance(relpath, basestring)
80
78
        if isinstance(relpath, basestring):
81
 
            relpath = [relpath]
 
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))
82
90
        basepath = self._path.split('/')
83
91
        if len(basepath) > 0 and basepath[-1] == '':
84
92
            basepath = basepath[:-1]
85
 
 
86
 
        for p in relpath:
 
93
        for p in relpath_parts:
87
94
            if p == '..':
88
 
                if len(basepath) < 0:
 
95
                if len(basepath) == 0:
89
96
                    # In most filesystems, a request for the parent
90
97
                    # of root, just returns root.
91
98
                    continue
92
99
                basepath.pop()
93
 
            elif p == '.':
 
100
            elif p == '.' or p == '':
94
101
                continue # No-op
95
102
            else:
96
103
                basepath.append(p)
97
 
 
98
104
        # Possibly, we could use urlparse.urljoin() here, but
99
105
        # I'm concerned about when it chooses to strip the last
100
106
        # portion of the path, and when it doesn't.
102
108
        return urlparse.urlunparse((self._proto,
103
109
                self._host, path, '', '', ''))
104
110
 
105
 
    def relpath(self, abspath):
106
 
        if not abspath.startswith(self.base):
107
 
            raise NonRelativePath('path %r is not under base URL %r'
108
 
                           % (abspath, self.base))
109
 
        pl = len(self.base)
110
 
        return abspath[pl:].lstrip('/')
111
 
 
112
111
    def has(self, relpath):
113
112
        """Does the target location exist?
114
113
 
127
126
            f.read()
128
127
            f.close()
129
128
            return True
130
 
        except BzrError:
131
 
            return False
132
 
        except urllib2.URLError:
133
 
            return False
 
129
        except urllib2.URLError, e:
 
130
            if e.code == 404:
 
131
                return False
 
132
            raise
134
133
        except IOError, e:
135
134
            if e.errno == errno.ENOENT:
136
135
                return False
143
142
        """
144
143
        try:
145
144
            return get_url(self.abspath(relpath))
146
 
        except (BzrError, urllib2.URLError, IOError), e:
147
 
            raise NoSuchFile(orig_error=e)
148
 
        except Exception,e:
149
 
            raise HttpTransportError(orig_error=e)
150
 
 
151
 
    def get_partial(self, relpath, start, length=None):
152
 
        """Get just part of a file.
153
 
 
154
 
        :param relpath: Path to the file, relative to base
155
 
        :param start: The starting position to read from
156
 
        :param length: The length to read. A length of None indicates
157
 
                       read to the end of the file.
158
 
        :return: A file-like object containing at least the specified bytes.
159
 
                 Some implementations may return objects which can be read
160
 
                 past this length, but this is not guaranteed.
161
 
        """
162
 
        # TODO: You can make specialized http requests for just
163
 
        # a portion of the file. Figure out how to do that.
164
 
        # For now, urllib2 returns files that cannot seek() so
165
 
        # we just read bytes off the beginning, until we
166
 
        # get to the point that we care about.
167
 
        f = self.get(relpath)
168
 
        # TODO: read in smaller chunks, in case things are
169
 
        # buffered internally.
170
 
        f.read(start)
171
 
        return f
 
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)),
 
154
                             orig_error=e)
172
155
 
173
156
    def put(self, relpath, f):
174
157
        """Copy the file-like or string object into the location.
216
199
        """Delete the item at relpath"""
217
200
        raise TransportNotPossible('http does not support delete()')
218
201
 
219
 
    def list_dir(self, relpath):
220
 
        """Return a list of all files at the given location.
221
 
        WARNING: many transports do not support this, so trying avoid using
222
 
        it if at all possible.
223
 
        """
224
 
        raise TransportNotPossible('http does not support list_dir()')
 
202
    def listable(self):
 
203
        """See Transport.listable."""
 
204
        return False
225
205
 
226
206
    def stat(self, relpath):
227
207
        """Return the stat information for a file.
248
228
        :return: A lock object, which should be passed to Transport.unlock()
249
229
        """
250
230
        raise TransportNotPossible('http does not support lock_write()')
251
 
 
252
 
register_transport('http://', HttpTransport)
253
 
register_transport('https://', HttpTransport)