/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

  • Committer: John Arbash Meinel
  • Date: 2006-09-15 00:44:57 UTC
  • mfrom: (2009 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2050.
  • Revision ID: john@arbash-meinel.com-20060915004457-902cec0526a39337
[merge] bzr.dev 2009

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
189
198
    implementations can do pipelining.
190
199
    In general implementations should support having a generator or a list
191
200
    as an argument (ie always iterate, never index)
 
201
 
 
202
    :ivar base: Base URL for the transport; should always end in a slash.
192
203
    """
193
204
 
194
205
    # implementations can override this if it is more efficient
211
222
 
212
223
        This handles things like ENOENT, ENOTDIR, EEXIST, and EACCESS
213
224
        """
214
 
        if hasattr(e, 'errno'):
 
225
        if getattr(e, 'errno', None) is not None:
215
226
            if e.errno in (errno.ENOENT, errno.ENOTDIR):
216
227
                raise errors.NoSuchFile(path, extra=e)
217
228
            # I would rather use errno.EFOO, but there doesn't seem to be
248
259
        object or string to another one.
249
260
        This just gives them something easy to call.
250
261
        """
251
 
        if isinstance(from_file, basestring):
252
 
            to_file.write(from_file)
253
 
        else:
254
 
            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)
255
265
 
256
266
    def _get_total(self, multi):
257
267
        """Try to figure out how many entries are in multi,
334
344
        Note that some transports MAY allow querying on directories, but this
335
345
        is not part of the protocol.  In other words, the results of 
336
346
        t.has("a_directory_name") are undefined.
 
347
 
 
348
        :rtype: bool
337
349
        """
338
350
        raise NotImplementedError(self.has)
339
351
 
373
385
        """
374
386
        raise NotImplementedError(self.get)
375
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
 
376
395
    def readv(self, relpath, offsets):
377
396
        """Get parts of the file at the given relative path.
378
397
 
483
502
            yield self.get(relpath)
484
503
            count += 1
485
504
 
 
505
    @deprecated_method(zero_eleven)
486
506
    def put(self, relpath, f, mode=None):
487
 
        """Copy the file-like or string object into the location.
 
507
        """Copy the file-like object into the location.
488
508
 
489
509
        :param relpath: Location to put the contents, relative to base.
490
 
        :param f:       File-like or string object.
 
510
        :param f:       File-like object.
491
511
        :param mode: The mode for the newly created file, 
492
512
                     None means just use the default
493
513
        """
494
 
        raise NotImplementedError(self.put)
495
 
 
 
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)
496
605
    def put_multi(self, files, mode=None, pb=None):
497
606
        """Put a set of files into the location.
498
607
 
501
610
        :param mode: The mode for the newly created files
502
611
        :return: The number of files copied.
503
612
        """
504
 
        def put(path, f):
505
 
            self.put(path, f, mode=mode)
506
 
        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))
507
619
 
508
620
    def mkdir(self, relpath, mode=None):
509
621
        """Create a directory at the given path."""
515
627
            self.mkdir(path, mode=mode)
516
628
        return len(self._iterate_over(relpaths, mkdir, pb, 'mkdir', expand=False))
517
629
 
 
630
    @deprecated_method(zero_eleven)
518
631
    def append(self, relpath, f, mode=None):
519
 
        """Append the text in the file-like or string object to 
520
 
        the supplied location.
 
632
        """Append the text in the file-like object to the supplied location.
521
633
 
522
 
        returns the length of f before the content was written to it.
 
634
        returns the length of relpath before the content was written to it.
523
635
        
524
636
        If the file does not exist, it is created with the supplied mode.
525
637
        """
526
 
        raise NotImplementedError(self.append)
 
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)
527
673
 
528
674
    def append_multi(self, files, pb=None):
529
675
        """Append the text in each file-like or string object to
532
678
        :param files: A set of (path, f) entries
533
679
        :param pb:  An optional ProgressBar for indicating percent done.
534
680
        """
535
 
        return self._iterate_over(files, self.append, pb, 'append', expand=True)
 
681
        return self._iterate_over(files, self.append_file, pb, 'append', expand=True)
536
682
 
537
683
    def copy(self, rel_from, rel_to):
538
684
        """Copy the item at rel_from to the location at rel_to.
540
686
        Override this for efficiency if a specific transport can do it 
541
687
        faster than this default implementation.
542
688
        """
543
 
        self.put(rel_to, self.get(rel_from))
 
689
        self.put_file(rel_to, self.get(rel_from))
544
690
 
545
691
    def copy_multi(self, relpaths, pb=None):
546
692
        """Copy a bunch of entries.
561
707
        """
562
708
        # The dummy implementation just does a simple get + put
563
709
        def copy_entry(path):
564
 
            other.put(path, self.get(path), mode=mode)
 
710
            other.put_file(path, self.get(path), mode=mode)
565
711
 
566
712
        return len(self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False))
567
713
 
882
1028
 
883
1029
    def get_transport_test_permutations(self, module):
884
1030
        """Get the permutations module wants to have tested."""
885
 
        if not hasattr(module, 'get_test_permutations'):
 
1031
        if getattr(module, 'get_test_permutations', None) is None:
886
1032
            warning("transport module %s doesn't provide get_test_permutations()"
887
1033
                    % module.__name__)
888
1034
            return []