~bzr-pqm/bzr/bzr.dev

907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1
#!/usr/bin/env python
2
"""\
3
An implementation of the Transport object for local
4
filesystem access.
5
"""
6
7
from bzrlib.transport import Transport, protocol_handlers
8
import os
9
10
class LocalTransport(Transport):
11
    """This is the transport agent for local filesystem access."""
12
13
    def __init__(self, base):
14
        """Set the base path where files will be stored."""
15
        from os.path import realpath
16
        super(LocalTransport, self).__init__(realpath(base))
17
907.1.22 by John Arbash Meinel
Fixed some encoding issues, added is_remote function for Transport objects.
18
    def is_remote(self):
19
        return False
20
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
21
    def clone(self, offset=None):
22
        """Return a new LocalTransport with root at self.base + offset
23
        Because the local filesystem does not require a connection, 
24
        we can just return a new object.
25
        """
26
        if offset is None:
27
            return LocalTransport(self.base)
28
        else:
29
            return LocalTransport(self.abspath(offset))
30
907.1.8 by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport
31
    def abspath(self, relpath):
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
32
        """Return the full url to the given relative path.
907.1.8 by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport
33
        This can be supplied with a string or a list
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
34
        """
907.1.8 by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport
35
        if isinstance(relpath, basestring):
36
            relpath = [relpath]
37
        return os.path.join(self.base, *relpath)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
38
907.1.24 by John Arbash Meinel
Remote functionality work.
39
    def relpath(self, abspath):
40
        """Return the local path portion from a given absolute path.
41
        """
42
        from branch import _relpath
43
        return _relpath(self.base, abspath)
44
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
45
    def has(self, relpath):
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
46
        return os.access(self.abspath(relpath), os.F_OK)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
47
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
48
    def get(self, relpath, decode=False):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
49
        """Get the file at the given relative path.
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
50
51
        :param relpath: The relative path to the file
52
        :param decode:  If True, assume the file is utf-8 encoded and
53
                        decode it into Unicode
54
        """
55
        if decode:
56
            import codecs
907.1.22 by John Arbash Meinel
Fixed some encoding issues, added is_remote function for Transport objects.
57
            return codecs.open(self.abspath(relpath), 'rb',
58
                    encoding='utf-8', buffering=60000)
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
59
        else:
60
            return open(self.abspath(relpath), 'rb')
61
62
    def put(self, relpath, f, encode=False):
63
        """Copy the file-like or string object into the location.
64
65
        :param relpath: Location to put the contents, relative to base.
66
        :param f:       File-like or string object.
67
        :param encode:  If True, translate the contents into utf-8 encoded text.
68
        """
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
69
        from bzrlib.atomicfile import AtomicFile
70
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
71
        if encode:
72
            fp = AtomicFile(self.abspath(relpath), 'wb', encoding='utf-8')
73
        else:
74
            fp = AtomicFile(self.abspath(relpath), 'wb')
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
75
        try:
76
            self._pump(f, fp)
77
            fp.commit()
78
        finally:
79
            fp.close()
80
81
    def mkdir(self, relpath):
82
        """Create a directory at the given path."""
83
        os.mkdir(self.abspath(relpath))
84
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
85
    def append(self, relpath, f):
86
        """Append the text in the file-like object into the final
87
        location.
88
        """
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
89
        fp = open(self.abspath(relpath), 'a+b')
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
90
        self._pump(f, fp)
91
92
    def copy(self, rel_from, rel_to):
93
        """Copy the item at rel_from to the location at rel_to"""
94
        import shutil
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
95
        path_from = self.abspath(rel_from)
96
        path_to = self.abspath(rel_to)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
97
        shutil.copy(path_from, path_to)
98
99
    def move(self, rel_from, rel_to):
100
        """Move the item at rel_from to the location at rel_to"""
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
101
        path_from = self.abspath(rel_from)
102
        path_to = self.abspath(rel_to)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
103
104
        os.rename(path_from, path_to)
105
106
    def delete(self, relpath):
107
        """Delete the item at relpath"""
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
108
        os.remove(self.abspath(relpath))
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
109
110
    def async_get(self, relpath):
111
        """Make a request for an file at the given location, but
112
        don't worry about actually getting it yet.
113
114
        :rtype: AsyncFile
115
        """
116
        raise NotImplementedError
117
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
118
    def list_dir(self, relpath):
119
        """Return a list of all files at the given location.
120
        WARNING: many transports do not support this, so trying avoid using
121
        it if at all possible.
122
        """
123
        return os.listdir(self.abspath(relpath))
124
125
    def stat(self, relpath):
126
        """Return the stat information for a file.
127
        """
128
        return os.stat(self.abspath(relpath))
129
907.1.24 by John Arbash Meinel
Remote functionality work.
130
    def lock_read(self, relpath):
131
        """Lock the given file for shared (read) access.
132
        :return: A lock object, which should be passed to Transport.unlock()
133
        """
134
        from bzrlib.lock import ReadLock
135
        return ReadLock(self.abspath(relpath))
136
137
    def lock_write(self, relpath):
138
        """Lock the given file for exclusive (write) access.
139
        WARNING: many transports do not support this, so trying avoid using it
140
141
        :return: A lock object, which should be passed to Transport.unlock()
142
        """
143
        from bzrlib.lock import WriteLock
144
        return WriteLock(self.abspath(relpath))
145
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
146
# If nothing else matches, try the LocalTransport
147
protocol_handlers[None] = LocalTransport
148