/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: Aaron Bentley
  • Date: 2006-09-09 18:52:57 UTC
  • mfrom: (1996 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1997.
  • Revision ID: aaron.bentley@utoronto.ca-20060909185257-ce0ee03ee5125ff1
Merge 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
211
220
 
212
221
        This handles things like ENOENT, ENOTDIR, EEXIST, and EACCESS
213
222
        """
214
 
        if hasattr(e, 'errno'):
 
223
        if getattr(e, 'errno', None) is not None:
215
224
            if e.errno in (errno.ENOENT, errno.ENOTDIR):
216
225
                raise errors.NoSuchFile(path, extra=e)
217
226
            # I would rather use errno.EFOO, but there doesn't seem to be
248
257
        object or string to another one.
249
258
        This just gives them something easy to call.
250
259
        """
251
 
        if isinstance(from_file, basestring):
252
 
            to_file.write(from_file)
253
 
        else:
254
 
            pumpfile(from_file, to_file)
 
260
        assert not isinstance(from_file, basestring), \
 
261
            '_pump should only be called on files not %s' % (type(from_file,))
 
262
        pumpfile(from_file, to_file)
255
263
 
256
264
    def _get_total(self, multi):
257
265
        """Try to figure out how many entries are in multi,
373
381
        """
374
382
        raise NotImplementedError(self.get)
375
383
 
 
384
    def get_bytes(self, relpath):
 
385
        """Get a raw string of the bytes for a file at the given location.
 
386
 
 
387
        :param relpath: The relative path to the file
 
388
        """
 
389
        return self.get(relpath).read()
 
390
 
376
391
    def readv(self, relpath, offsets):
377
392
        """Get parts of the file at the given relative path.
378
393
 
483
498
            yield self.get(relpath)
484
499
            count += 1
485
500
 
 
501
    @deprecated_method(zero_eleven)
486
502
    def put(self, relpath, f, mode=None):
487
 
        """Copy the file-like or string object into the location.
 
503
        """Copy the file-like object into the location.
488
504
 
489
505
        :param relpath: Location to put the contents, relative to base.
490
 
        :param f:       File-like or string object.
 
506
        :param f:       File-like object.
491
507
        :param mode: The mode for the newly created file, 
492
508
                     None means just use the default
493
509
        """
494
 
        raise NotImplementedError(self.put)
495
 
 
 
510
        if isinstance(f, str):
 
511
            return self.put_bytes(relpath, f, mode=mode)
 
512
        else:
 
513
            return self.put_file(relpath, f, mode=mode)
 
514
 
 
515
    def put_bytes(self, relpath, bytes, mode=None):
 
516
        """Atomically put the supplied bytes into the given location.
 
517
 
 
518
        :param relpath: The location to put the contents, relative to the
 
519
            transport base.
 
520
        :param bytes: A bytestring of data.
 
521
        :param mode: Create the file with the given mode.
 
522
        :return: None
 
523
        """
 
524
        assert isinstance(bytes, str), \
 
525
            'bytes must be a plain string, not %s' % type(bytes)
 
526
        return self.put_file(relpath, StringIO(bytes), mode=mode)
 
527
 
 
528
    def put_bytes_non_atomic(self, relpath, bytes, mode=None,
 
529
                             create_parent_dir=False,
 
530
                             dir_mode=None):
 
531
        """Copy the string into the target location.
 
532
 
 
533
        This function is not strictly safe to use. See 
 
534
        Transport.put_bytes_non_atomic for more information.
 
535
 
 
536
        :param relpath: The remote location to put the contents.
 
537
        :param bytes:   A string object containing the raw bytes to write into
 
538
                        the target file.
 
539
        :param mode:    Possible access permissions for new file.
 
540
                        None means do not set remote permissions.
 
541
        :param create_parent_dir: If we cannot create the target file because
 
542
                        the parent directory does not exist, go ahead and
 
543
                        create it, and then try again.
 
544
        :param dir_mode: Possible access permissions for new directories.
 
545
        """
 
546
        assert isinstance(bytes, str), \
 
547
            'bytes must be a plain string, not %s' % type(bytes)
 
548
        self.put_file_non_atomic(relpath, StringIO(bytes), mode=mode,
 
549
                                 create_parent_dir=create_parent_dir,
 
550
                                 dir_mode=dir_mode)
 
551
 
 
552
    def put_file(self, relpath, f, mode=None):
 
553
        """Copy the file-like object into the location.
 
554
 
 
555
        :param relpath: Location to put the contents, relative to base.
 
556
        :param f:       File-like object.
 
557
        :param mode: The mode for the newly created file,
 
558
                     None means just use the default.
 
559
        """
 
560
        # We would like to mark this as NotImplemented, but most likely
 
561
        # transports have defined it in terms of the old api.
 
562
        symbol_versioning.warn('Transport %s should implement put_file,'
 
563
                               ' rather than implementing put() as of'
 
564
                               ' version 0.11.'
 
565
                               % (self.__class__.__name__,),
 
566
                               DeprecationWarning)
 
567
        return self.put(relpath, f, mode=mode)
 
568
        #raise NotImplementedError(self.put_file)
 
569
 
 
570
    def put_file_non_atomic(self, relpath, f, mode=None,
 
571
                            create_parent_dir=False,
 
572
                            dir_mode=None):
 
573
        """Copy the file-like object into the target location.
 
574
 
 
575
        This function is not strictly safe to use. It is only meant to
 
576
        be used when you already know that the target does not exist.
 
577
        It is not safe, because it will open and truncate the remote
 
578
        file. So there may be a time when the file has invalid contents.
 
579
 
 
580
        :param relpath: The remote location to put the contents.
 
581
        :param f:       File-like object.
 
582
        :param mode:    Possible access permissions for new file.
 
583
                        None means do not set remote permissions.
 
584
        :param create_parent_dir: If we cannot create the target file because
 
585
                        the parent directory does not exist, go ahead and
 
586
                        create it, and then try again.
 
587
        :param dir_mode: Possible access permissions for new directories.
 
588
        """
 
589
        # Default implementation just does an atomic put.
 
590
        try:
 
591
            return self.put_file(relpath, f, mode=mode)
 
592
        except errors.NoSuchFile:
 
593
            if not create_parent_dir:
 
594
                raise
 
595
            parent_dir = osutils.dirname(relpath)
 
596
            if parent_dir:
 
597
                self.mkdir(parent_dir, mode=dir_mode)
 
598
                return self.put_file(relpath, f, mode=mode)
 
599
 
 
600
    @deprecated_method(zero_eleven)
496
601
    def put_multi(self, files, mode=None, pb=None):
497
602
        """Put a set of files into the location.
498
603
 
501
606
        :param mode: The mode for the newly created files
502
607
        :return: The number of files copied.
503
608
        """
504
 
        def put(path, f):
505
 
            self.put(path, f, mode=mode)
506
 
        return len(self._iterate_over(files, put, pb, 'put', expand=True))
 
609
        def _put(path, f):
 
610
            if isinstance(f, str):
 
611
                self.put_bytes(path, f, mode=mode)
 
612
            else:
 
613
                self.put_file(path, f, mode=mode)
 
614
        return len(self._iterate_over(files, _put, pb, 'put', expand=True))
507
615
 
508
616
    def mkdir(self, relpath, mode=None):
509
617
        """Create a directory at the given path."""
515
623
            self.mkdir(path, mode=mode)
516
624
        return len(self._iterate_over(relpaths, mkdir, pb, 'mkdir', expand=False))
517
625
 
 
626
    @deprecated_method(zero_eleven)
518
627
    def append(self, relpath, f, mode=None):
519
 
        """Append the text in the file-like or string object to 
520
 
        the supplied location.
521
 
 
522
 
        returns the length of f before the content was written to it.
523
 
        
524
 
        If the file does not exist, it is created with the supplied mode.
525
 
        """
526
 
        raise NotImplementedError(self.append)
 
628
        """Append the text in the file-like object to the supplied location.
 
629
 
 
630
        returns the length of relpath before the content was written to it.
 
631
        
 
632
        If the file does not exist, it is created with the supplied mode.
 
633
        """
 
634
        return self.append_file(relpath, f, mode=mode)
 
635
 
 
636
    def append_file(self, relpath, f, mode=None):
 
637
        """Append the text in the file-like object to the supplied location.
 
638
 
 
639
        returns the length of relpath before the content was written to it.
 
640
        
 
641
        If the file does not exist, it is created with the supplied mode.
 
642
        """
 
643
        symbol_versioning.warn('Transport %s should implement append_file,'
 
644
                               ' rather than implementing append() as of'
 
645
                               ' version 0.11.'
 
646
                               % (self.__class__.__name__,),
 
647
                               DeprecationWarning)
 
648
        return self.append(relpath, f, mode=mode)
 
649
 
 
650
    def append_bytes(self, relpath, bytes, mode=None):
 
651
        """Append the text in the string object to the supplied location.
 
652
 
 
653
        returns the length of relpath before the content was written to it.
 
654
        
 
655
        If the file does not exist, it is created with the supplied mode.
 
656
        """
 
657
        assert isinstance(bytes, str), \
 
658
            'bytes must be a plain string, not %s' % type(bytes)
 
659
        return self.append_file(relpath, StringIO(bytes), mode=mode)
527
660
 
528
661
    def append_multi(self, files, pb=None):
529
662
        """Append the text in each file-like or string object to
532
665
        :param files: A set of (path, f) entries
533
666
        :param pb:  An optional ProgressBar for indicating percent done.
534
667
        """
535
 
        return self._iterate_over(files, self.append, pb, 'append', expand=True)
 
668
        return self._iterate_over(files, self.append_file, pb, 'append', expand=True)
536
669
 
537
670
    def copy(self, rel_from, rel_to):
538
671
        """Copy the item at rel_from to the location at rel_to.
540
673
        Override this for efficiency if a specific transport can do it 
541
674
        faster than this default implementation.
542
675
        """
543
 
        self.put(rel_to, self.get(rel_from))
 
676
        self.put_file(rel_to, self.get(rel_from))
544
677
 
545
678
    def copy_multi(self, relpaths, pb=None):
546
679
        """Copy a bunch of entries.
561
694
        """
562
695
        # The dummy implementation just does a simple get + put
563
696
        def copy_entry(path):
564
 
            other.put(path, self.get(path), mode=mode)
 
697
            other.put_file(path, self.get(path), mode=mode)
565
698
 
566
699
        return len(self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False))
567
700
 
882
1015
 
883
1016
    def get_transport_test_permutations(self, module):
884
1017
        """Get the permutations module wants to have tested."""
885
 
        if not hasattr(module, 'get_test_permutations'):
 
1018
        if getattr(module, 'get_test_permutations', None) is None:
886
1019
            warning("transport module %s doesn't provide get_test_permutations()"
887
1020
                    % module.__name__)
888
1021
            return []