~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
import errno
23
23
from copy import deepcopy
 
24
from stat import *
24
25
import sys
25
26
from unittest import TestSuite
26
27
 
333
334
 
334
335
        return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
335
336
 
 
337
    def copy_tree(self, from_relpath, to_relpath):
 
338
        """Copy a subtree from one relpath to another.
 
339
 
 
340
        If a faster implementation is available, specific transports should 
 
341
        implement it.
 
342
        """
 
343
        source = self.clone(from_relpath)
 
344
        self.mkdir(to_relpath)
 
345
        target = self.clone(to_relpath)
 
346
        files = []
 
347
        directories = ['.']
 
348
        while directories:
 
349
            dir = directories.pop()
 
350
            if dir != '.':
 
351
                target.mkdir(dir)
 
352
            for path in source.list_dir(dir):
 
353
                path = dir + '/' + path
 
354
                stat = source.stat(path)
 
355
                if S_ISDIR(stat.st_mode):
 
356
                    directories.append(path)
 
357
                else:
 
358
                    files.append(path)
 
359
        source.copy_to(files, target)
336
360
 
337
361
    def move(self, rel_from, rel_to):
338
362
        """Move the item at rel_from to the location at rel_to.
340
364
        If a transport can directly implement this it is suggested that
341
365
        it do so for efficiency.
342
366
        """
343
 
        self.copy(rel_from, rel_to)
344
 
        self.delete(rel_from)
 
367
        if S_ISDIR(self.stat(rel_from).st_mode):
 
368
            self.copy_tree(rel_from, rel_to)
 
369
            self.delete_tree(rel_from)
 
370
        else:
 
371
            self.copy(rel_from, rel_to)
 
372
            self.delete(rel_from)
345
373
 
346
374
    def move_multi(self, relpaths, pb=None):
347
375
        """Move a bunch of entries.
371
399
        """
372
400
        return self._iterate_over(relpaths, self.delete, pb, 'delete', expand=False)
373
401
 
 
402
    def delete_tree(self, relpath):
 
403
        """Delete an entire tree. This may require a listable transport."""
 
404
        subtree = self.clone(relpath)
 
405
        files = []
 
406
        directories = ['.']
 
407
        pending_rmdirs = []
 
408
        while directories:
 
409
            dir = directories.pop()
 
410
            if dir != '.':
 
411
                pending_rmdirs.append(dir)
 
412
            for path in subtree.list_dir(dir):
 
413
                path = dir + '/' + path
 
414
                stat = subtree.stat(path)
 
415
                if S_ISDIR(stat.st_mode):
 
416
                    directories.append(path)
 
417
                else:
 
418
                    files.append(path)
 
419
        subtree.delete_multi(files)
 
420
        pending_rmdirs.reverse()
 
421
        for dir in pending_rmdirs:
 
422
            subtree.rmdir(dir)
 
423
        self.rmdir(relpath)
 
424
 
374
425
    def stat(self, relpath):
375
426
        """Return the stat information for a file.
376
427
        WARNING: This may not be implementable for all protocols, so use
383
434
        """
384
435
        raise NotImplementedError
385
436
 
 
437
    def rmdir(self, relpath):
 
438
        """Remove a directory at the given path."""
 
439
        raise NotImplementedError
 
440
 
386
441
    def stat_multi(self, relpaths, pb=None):
387
442
        """Stat multiple files and return the information.
388
443
        """
554
609
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
555
610
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
556
611
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
 
612
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')