~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

[merge] jam-integration 1527, including branch-formats, help text, misc bug fixes.

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
import urllib
26
27
from unittest import TestSuite
334
335
 
335
336
        return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
336
337
 
 
338
    def copy_tree(self, from_relpath, to_relpath):
 
339
        """Copy a subtree from one relpath to another.
 
340
 
 
341
        If a faster implementation is available, specific transports should 
 
342
        implement it.
 
343
        """
 
344
        source = self.clone(from_relpath)
 
345
        self.mkdir(to_relpath)
 
346
        target = self.clone(to_relpath)
 
347
        files = []
 
348
        directories = ['.']
 
349
        while directories:
 
350
            dir = directories.pop()
 
351
            if dir != '.':
 
352
                target.mkdir(dir)
 
353
            for path in source.list_dir(dir):
 
354
                path = dir + '/' + path
 
355
                stat = source.stat(path)
 
356
                if S_ISDIR(stat.st_mode):
 
357
                    directories.append(path)
 
358
                else:
 
359
                    files.append(path)
 
360
        source.copy_to(files, target)
337
361
 
338
362
    def move(self, rel_from, rel_to):
339
363
        """Move the item at rel_from to the location at rel_to.
341
365
        If a transport can directly implement this it is suggested that
342
366
        it do so for efficiency.
343
367
        """
344
 
        self.copy(rel_from, rel_to)
345
 
        self.delete(rel_from)
 
368
        if S_ISDIR(self.stat(rel_from).st_mode):
 
369
            self.copy_tree(rel_from, rel_to)
 
370
            self.delete_tree(rel_from)
 
371
        else:
 
372
            self.copy(rel_from, rel_to)
 
373
            self.delete(rel_from)
346
374
 
347
375
    def move_multi(self, relpaths, pb=None):
348
376
        """Move a bunch of entries.
372
400
        """
373
401
        return self._iterate_over(relpaths, self.delete, pb, 'delete', expand=False)
374
402
 
 
403
    def delete_tree(self, relpath):
 
404
        """Delete an entire tree. This may require a listable transport."""
 
405
        subtree = self.clone(relpath)
 
406
        files = []
 
407
        directories = ['.']
 
408
        pending_rmdirs = []
 
409
        while directories:
 
410
            dir = directories.pop()
 
411
            if dir != '.':
 
412
                pending_rmdirs.append(dir)
 
413
            for path in subtree.list_dir(dir):
 
414
                path = dir + '/' + path
 
415
                stat = subtree.stat(path)
 
416
                if S_ISDIR(stat.st_mode):
 
417
                    directories.append(path)
 
418
                else:
 
419
                    files.append(path)
 
420
        subtree.delete_multi(files)
 
421
        pending_rmdirs.reverse()
 
422
        for dir in pending_rmdirs:
 
423
            subtree.rmdir(dir)
 
424
        self.rmdir(relpath)
 
425
 
375
426
    def stat(self, relpath):
376
427
        """Return the stat information for a file.
377
428
        WARNING: This may not be implementable for all protocols, so use
384
435
        """
385
436
        raise NotImplementedError
386
437
 
 
438
    def rmdir(self, relpath):
 
439
        """Remove a directory at the given path."""
 
440
        raise NotImplementedError
 
441
 
387
442
    def stat_multi(self, relpaths, pb=None):
388
443
        """Stat multiple files and return the information.
389
444
        """
544
599
        """Return a list of the klass, server_factory pairs to test."""
545
600
        result = []
546
601
        for module in _get_transport_modules():
547
 
            result.extend(self.get_transport_test_permutations(reduce(getattr, 
548
 
                (module).split('.')[1:],
549
 
                 __import__(module))))
 
602
            try:
 
603
                result.extend(self.get_transport_test_permutations(reduce(getattr, 
 
604
                    (module).split('.')[1:],
 
605
                     __import__(module))))
 
606
            except errors.DependencyNotPresent, e:
 
607
                # Continue even if a dependency prevents us 
 
608
                # from running this test
 
609
                pass
550
610
        return result
551
611
        
552
612
 
559
619
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
560
620
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
561
621
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
 
622
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')