~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

MergeĀ fromĀ martin

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from bzrlib.trace import mutter
23
23
import bzrlib.errors as errors
24
24
import errno
 
25
import sys
25
26
 
26
27
_protocol_handlers = {
27
28
}
63
64
        if hasattr(e, 'errno'):
64
65
            if e.errno in (errno.ENOENT, errno.ENOTDIR):
65
66
                raise errors.NoSuchFile(path, extra=e)
 
67
            # I would rather use errno.EFOO, but there doesn't seem to be
 
68
            # any matching for 267
 
69
            # This is the error when doing a listdir on a file:
 
70
            # WindowsError: [Errno 267] The directory name is invalid
 
71
            if sys.platform == 'win32' and e.errno in (errno.ESRCH, 267):
 
72
                raise errors.NoSuchFile(path, extra=e)
66
73
            if e.errno == errno.EEXIST:
67
74
                raise errors.FileExists(path, extra=e)
68
75
            if e.errno == errno.EACCES:
214
221
            yield self.get(relpath)
215
222
            count += 1
216
223
 
217
 
    def put(self, relpath, f):
 
224
    def put(self, relpath, f, mode=None):
218
225
        """Copy the file-like or string object into the location.
219
226
 
220
227
        :param relpath: Location to put the contents, relative to base.
221
228
        :param f:       File-like or string object.
 
229
        :param mode: The mode for the newly created file, 
 
230
                     None means just use the default
222
231
        """
223
232
        raise NotImplementedError
224
233
 
225
 
    def put_multi(self, files, pb=None):
 
234
    def put_multi(self, files, mode=None, pb=None):
226
235
        """Put a set of files or strings into the location.
227
236
 
228
237
        :param files: A list of tuples of relpath, file object [(path1, file1), (path2, file2),...]
229
238
        :param pb:  An optional ProgressBar for indicating percent done.
 
239
        :param mode: The mode for the newly created files
230
240
        :return: The number of files copied.
231
241
        """
232
 
        return self._iterate_over(files, self.put, pb, 'put', expand=True)
 
242
        def put(path, f):
 
243
            self.put(path, f, mode=mode)
 
244
        return self._iterate_over(files, put, pb, 'put', expand=True)
233
245
 
234
 
    def mkdir(self, relpath):
 
246
    def mkdir(self, relpath, mode=None):
235
247
        """Create a directory at the given path."""
236
248
        raise NotImplementedError
237
249
 
238
 
    def mkdir_multi(self, relpaths, pb=None):
 
250
    def mkdir_multi(self, relpaths, mode=None, pb=None):
239
251
        """Create a group of directories"""
240
 
        return self._iterate_over(relpaths, self.mkdir, pb, 'mkdir', expand=False)
 
252
        def mkdir(path):
 
253
            self.mkdir(path, mode=mode)
 
254
        return self._iterate_over(relpaths, mkdir, pb, 'mkdir', expand=False)
241
255
 
242
256
    def append(self, relpath, f):
243
257
        """Append the text in the file-like or string object to 
267
281
        # implementors don't have to implement everything.
268
282
        return self._iterate_over(relpaths, self.copy, pb, 'copy', expand=True)
269
283
 
270
 
    def copy_to(self, relpaths, other, pb=None):
 
284
    def copy_to(self, relpaths, other, mode=None, pb=None):
271
285
        """Copy a set of entries from self into another Transport.
272
286
 
273
287
        :param relpaths: A list/generator of entries to be copied.
 
288
        :param mode: This is the target mode for the newly created files
274
289
        TODO: This interface needs to be updated so that the target location
275
290
              can be different from the source location.
276
291
        """
277
292
        # The dummy implementation just does a simple get + put
278
293
        def copy_entry(path):
279
 
            other.put(path, self.get(path))
 
294
            other.put(path, self.get(path), mode=mode)
280
295
 
281
296
        return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
282
297
 
370
385
    global _protocol_handlers
371
386
    if base is None:
372
387
        base = u'.'
 
388
    else:
 
389
        base = unicode(base)
373
390
    for proto, klass in _protocol_handlers.iteritems():
374
391
        if proto is not None and base.startswith(proto):
375
392
            return klass(base)