/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

Merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
import errno
30
30
from collections import deque
31
31
from copy import deepcopy
 
32
from cStringIO import StringIO
32
33
import re
33
34
from stat import S_ISDIR
34
35
import sys
38
39
import warnings
39
40
 
40
41
import bzrlib
41
 
import bzrlib.errors as errors
 
42
from bzrlib import (
 
43
    errors,
 
44
    osutils,
 
45
    symbol_versioning,
 
46
    urlutils,
 
47
    )
42
48
from bzrlib.errors import DependencyNotPresent
43
 
import bzrlib.osutils as osutils
44
49
from bzrlib.osutils import pumpfile
45
 
from bzrlib.symbol_versioning import (deprecated_passed, deprecated_method, deprecated_function, 
 
50
from bzrlib.symbol_versioning import (
 
51
        deprecated_passed,
 
52
        deprecated_method,
 
53
        deprecated_function,
46
54
        DEPRECATED_PARAMETER,
47
 
        zero_eight)
 
55
        zero_eight,
 
56
        zero_eleven,
 
57
        )
48
58
from bzrlib.trace import mutter, warning
49
 
import bzrlib.urlutils as urlutils
50
59
 
51
60
# {prefix: [transport_classes]}
52
61
# Transports are inserted onto the list LIFO and tried in order; as a result
213
222
 
214
223
        This handles things like ENOENT, ENOTDIR, EEXIST, and EACCESS
215
224
        """
216
 
        if hasattr(e, 'errno'):
 
225
        if getattr(e, 'errno', None) is not None:
217
226
            if e.errno in (errno.ENOENT, errno.ENOTDIR):
218
227
                raise errors.NoSuchFile(path, extra=e)
219
228
            # I would rather use errno.EFOO, but there doesn't seem to be
250
259
        object or string to another one.
251
260
        This just gives them something easy to call.
252
261
        """
253
 
        if isinstance(from_file, basestring):
254
 
            to_file.write(from_file)
255
 
        else:
256
 
            pumpfile(from_file, to_file)
 
262
        assert not isinstance(from_file, basestring), \
 
263
            '_pump should only be called on files not %s' % (type(from_file,))
 
264
        pumpfile(from_file, to_file)
257
265
 
258
266
    def _get_total(self, multi):
259
267
        """Try to figure out how many entries are in multi,
377
385
        """
378
386
        raise NotImplementedError(self.get)
379
387
 
 
388
    def get_bytes(self, relpath):
 
389
        """Get a raw string of the bytes for a file at the given location.
 
390
 
 
391
        :param relpath: The relative path to the file
 
392
        """
 
393
        return self.get(relpath).read()
 
394
 
380
395
    def readv(self, relpath, offsets):
381
396
        """Get parts of the file at the given relative path.
382
397
 
487
502
            yield self.get(relpath)
488
503
            count += 1
489
504
 
 
505
    @deprecated_method(zero_eleven)
490
506
    def put(self, relpath, f, mode=None):
491
 
        """Copy the file-like or string object into the location.
 
507
        """Copy the file-like object into the location.
492
508
 
493
509
        :param relpath: Location to put the contents, relative to base.
494
 
        :param f:       File-like or string object.
 
510
        :param f:       File-like object.
495
511
        :param mode: The mode for the newly created file, 
496
512
                     None means just use the default
497
513
        """
498
 
        raise NotImplementedError(self.put)
499
 
 
 
514
        if isinstance(f, str):
 
515
            return self.put_bytes(relpath, f, mode=mode)
 
516
        else:
 
517
            return self.put_file(relpath, f, mode=mode)
 
518
 
 
519
    def put_bytes(self, relpath, bytes, mode=None):
 
520
        """Atomically put the supplied bytes into the given location.
 
521
 
 
522
        :param relpath: The location to put the contents, relative to the
 
523
            transport base.
 
524
        :param bytes: A bytestring of data.
 
525
        :param mode: Create the file with the given mode.
 
526
        :return: None
 
527
        """
 
528
        assert isinstance(bytes, str), \
 
529
            'bytes must be a plain string, not %s' % type(bytes)
 
530
        return self.put_file(relpath, StringIO(bytes), mode=mode)
 
531
 
 
532
    def put_bytes_non_atomic(self, relpath, bytes, mode=None,
 
533
                             create_parent_dir=False,
 
534
                             dir_mode=None):
 
535
        """Copy the string into the target location.
 
536
 
 
537
        This function is not strictly safe to use. See 
 
538
        Transport.put_bytes_non_atomic for more information.
 
539
 
 
540
        :param relpath: The remote location to put the contents.
 
541
        :param bytes:   A string object containing the raw bytes to write into
 
542
                        the target file.
 
543
        :param mode:    Possible access permissions for new file.
 
544
                        None means do not set remote permissions.
 
545
        :param create_parent_dir: If we cannot create the target file because
 
546
                        the parent directory does not exist, go ahead and
 
547
                        create it, and then try again.
 
548
        :param dir_mode: Possible access permissions for new directories.
 
549
        """
 
550
        assert isinstance(bytes, str), \
 
551
            'bytes must be a plain string, not %s' % type(bytes)
 
552
        self.put_file_non_atomic(relpath, StringIO(bytes), mode=mode,
 
553
                                 create_parent_dir=create_parent_dir,
 
554
                                 dir_mode=dir_mode)
 
555
 
 
556
    def put_file(self, relpath, f, mode=None):
 
557
        """Copy the file-like object into the location.
 
558
 
 
559
        :param relpath: Location to put the contents, relative to base.
 
560
        :param f:       File-like object.
 
561
        :param mode: The mode for the newly created file,
 
562
                     None means just use the default.
 
563
        """
 
564
        # We would like to mark this as NotImplemented, but most likely
 
565
        # transports have defined it in terms of the old api.
 
566
        symbol_versioning.warn('Transport %s should implement put_file,'
 
567
                               ' rather than implementing put() as of'
 
568
                               ' version 0.11.'
 
569
                               % (self.__class__.__name__,),
 
570
                               DeprecationWarning)
 
571
        return self.put(relpath, f, mode=mode)
 
572
        #raise NotImplementedError(self.put_file)
 
573
 
 
574
    def put_file_non_atomic(self, relpath, f, mode=None,
 
575
                            create_parent_dir=False,
 
576
                            dir_mode=None):
 
577
        """Copy the file-like object into the target location.
 
578
 
 
579
        This function is not strictly safe to use. It is only meant to
 
580
        be used when you already know that the target does not exist.
 
581
        It is not safe, because it will open and truncate the remote
 
582
        file. So there may be a time when the file has invalid contents.
 
583
 
 
584
        :param relpath: The remote location to put the contents.
 
585
        :param f:       File-like object.
 
586
        :param mode:    Possible access permissions for new file.
 
587
                        None means do not set remote permissions.
 
588
        :param create_parent_dir: If we cannot create the target file because
 
589
                        the parent directory does not exist, go ahead and
 
590
                        create it, and then try again.
 
591
        :param dir_mode: Possible access permissions for new directories.
 
592
        """
 
593
        # Default implementation just does an atomic put.
 
594
        try:
 
595
            return self.put_file(relpath, f, mode=mode)
 
596
        except errors.NoSuchFile:
 
597
            if not create_parent_dir:
 
598
                raise
 
599
            parent_dir = osutils.dirname(relpath)
 
600
            if parent_dir:
 
601
                self.mkdir(parent_dir, mode=dir_mode)
 
602
                return self.put_file(relpath, f, mode=mode)
 
603
 
 
604
    @deprecated_method(zero_eleven)
500
605
    def put_multi(self, files, mode=None, pb=None):
501
606
        """Put a set of files into the location.
502
607
 
505
610
        :param mode: The mode for the newly created files
506
611
        :return: The number of files copied.
507
612
        """
508
 
        def put(path, f):
509
 
            self.put(path, f, mode=mode)
510
 
        return len(self._iterate_over(files, put, pb, 'put', expand=True))
 
613
        def _put(path, f):
 
614
            if isinstance(f, str):
 
615
                self.put_bytes(path, f, mode=mode)
 
616
            else:
 
617
                self.put_file(path, f, mode=mode)
 
618
        return len(self._iterate_over(files, _put, pb, 'put', expand=True))
511
619
 
512
620
    def mkdir(self, relpath, mode=None):
513
621
        """Create a directory at the given path."""
519
627
            self.mkdir(path, mode=mode)
520
628
        return len(self._iterate_over(relpaths, mkdir, pb, 'mkdir', expand=False))
521
629
 
 
630
    @deprecated_method(zero_eleven)
522
631
    def append(self, relpath, f, mode=None):
523
 
        """Append bytes to a file.
524
 
 
525
 
        The file is created if it does not already exist.
526
 
 
527
 
        :param f: a file-like object or string of the bytes to append.
528
 
        :param mode: Unix mode for newly created files.  This is not used for
529
 
            existing files.
530
 
 
531
 
        :returns: the length of f before the content was written to it.
532
 
        """
533
 
        raise NotImplementedError(self.append)
 
632
        """Append the text in the file-like object to the supplied location.
 
633
 
 
634
        returns the length of relpath before the content was written to it.
 
635
        
 
636
        If the file does not exist, it is created with the supplied mode.
 
637
        """
 
638
        return self.append_file(relpath, f, mode=mode)
 
639
 
 
640
    def append_file(self, relpath, f, mode=None):
 
641
        """Append bytes from a file-like object to a file at relpath.
 
642
 
 
643
        The file is created if it does not already exist.
 
644
 
 
645
        :param f: a file-like object of the bytes to append.
 
646
        :param mode: Unix mode for newly created files.  This is not used for
 
647
            existing files.
 
648
 
 
649
        :returns: the length of relpath before the content was written to it.
 
650
        """
 
651
        symbol_versioning.warn('Transport %s should implement append_file,'
 
652
                               ' rather than implementing append() as of'
 
653
                               ' version 0.11.'
 
654
                               % (self.__class__.__name__,),
 
655
                               DeprecationWarning)
 
656
        return self.append(relpath, f, mode=mode)
 
657
 
 
658
    def append_bytes(self, relpath, bytes, mode=None):
 
659
        """Append bytes to a file at relpath.
 
660
 
 
661
        The file is created if it does not already exist.
 
662
 
 
663
        :type f: str
 
664
        :param f: a string of the bytes to append.
 
665
        :param mode: Unix mode for newly created files.  This is not used for
 
666
            existing files.
 
667
 
 
668
        :returns: the length of relpath before the content was written to it.
 
669
        """
 
670
        assert isinstance(bytes, str), \
 
671
            'bytes must be a plain string, not %s' % type(bytes)
 
672
        return self.append_file(relpath, StringIO(bytes), mode=mode)
534
673
 
535
674
    def append_multi(self, files, pb=None):
536
675
        """Append the text in each file-like or string object to
539
678
        :param files: A set of (path, f) entries
540
679
        :param pb:  An optional ProgressBar for indicating percent done.
541
680
        """
542
 
        return self._iterate_over(files, self.append, pb, 'append', expand=True)
 
681
        return self._iterate_over(files, self.append_file, pb, 'append', expand=True)
543
682
 
544
683
    def copy(self, rel_from, rel_to):
545
684
        """Copy the item at rel_from to the location at rel_to.
547
686
        Override this for efficiency if a specific transport can do it 
548
687
        faster than this default implementation.
549
688
        """
550
 
        self.put(rel_to, self.get(rel_from))
 
689
        self.put_file(rel_to, self.get(rel_from))
551
690
 
552
691
    def copy_multi(self, relpaths, pb=None):
553
692
        """Copy a bunch of entries.
568
707
        """
569
708
        # The dummy implementation just does a simple get + put
570
709
        def copy_entry(path):
571
 
            other.put(path, self.get(path), mode=mode)
 
710
            other.put_file(path, self.get(path), mode=mode)
572
711
 
573
712
        return len(self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False))
574
713
 
889
1028
 
890
1029
    def get_transport_test_permutations(self, module):
891
1030
        """Get the permutations module wants to have tested."""
892
 
        if not hasattr(module, 'get_test_permutations'):
 
1031
        if getattr(module, 'get_test_permutations', None) is None:
893
1032
            warning("transport module %s doesn't provide get_test_permutations()"
894
1033
                    % module.__name__)
895
1034
            return []