~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/local.py

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import sys
24
24
from stat import ST_MODE, S_ISDIR, ST_SIZE
25
25
import tempfile
26
 
import urllib
27
26
 
 
27
from bzrlib.osutils import (abspath, realpath, normpath, pathjoin, rename, 
 
28
                            check_legal_path, rmtree)
 
29
from bzrlib.symbol_versioning import warn
28
30
from bzrlib.trace import mutter
29
31
from bzrlib.transport import Transport, Server
30
 
from bzrlib.osutils import (abspath, realpath, normpath, pathjoin, rename, 
31
 
                            check_legal_path, rmtree)
 
32
import bzrlib.urlutils as urlutils
32
33
 
33
34
 
34
35
class LocalTransport(Transport):
36
37
 
37
38
    def __init__(self, base):
38
39
        """Set the base path where files will be stored."""
39
 
        if base.startswith('file://'):
40
 
            base = base[len('file://'):]
41
 
        # realpath is incompatible with symlinks. When we traverse
42
 
        # up we might be able to normpath stuff. RBC 20051003
43
 
        base = normpath(abspath(base))
 
40
        if not base.startswith('file://'):
 
41
            warn("Instantiating LocalTransport with a filesystem path"
 
42
                " is deprecated as of bzr 0.8."
 
43
                " Please use bzrlib.transport.get_transport()"
 
44
                " or pass in a file:// url.",
 
45
                 DeprecationWarning,
 
46
                 stacklevel=2
 
47
                 )
 
48
            base = urlutils.local_path_to_url(base)
44
49
        if base[-1] != '/':
45
50
            base = base + '/'
46
51
        super(LocalTransport, self).__init__(base)
 
52
        self._local_base = urlutils.local_path_from_url(base)
47
53
 
48
54
    def should_cache(self):
49
55
        return False
61
67
    def abspath(self, relpath):
62
68
        """Return the full url to the given relative URL."""
63
69
        assert isinstance(relpath, basestring), (type(relpath), relpath)
64
 
        result = normpath(pathjoin(self.base, urllib.unquote(relpath)))
65
 
        #if result[-1] != '/':
66
 
        #    result += '/'
67
 
        return result
 
70
        # jam 20060426 Using normpath on the real path, because that ensures
 
71
        #       proper handling of stuff like
 
72
        path = normpath(pathjoin(self._local_base, urlutils.unescape(relpath)))
 
73
        return urlutils.local_path_to_url(path)
 
74
 
 
75
    def local_abspath(self, relpath):
 
76
        """Transform the given relative path URL into the actual path on disk
 
77
 
 
78
        This function only exists for the LocalTransport, since it is
 
79
        the only one that has direct local access.
 
80
        This is mostly for stuff like WorkingTree which needs to know
 
81
        the local working directory.
 
82
        """
 
83
        absurl = self.abspath(relpath)
 
84
        # mutter(u'relpath %s => base: %s, absurl %s', relpath, self.base, absurl)
 
85
        return urlutils.local_path_from_url(absurl)
68
86
 
69
87
    def relpath(self, abspath):
70
88
        """Return the local path portion from a given absolute path.
71
89
        """
72
 
        from bzrlib.osutils import relpath, strip_trailing_slash
73
90
        if abspath is None:
74
91
            abspath = u'.'
75
92
 
76
 
        return relpath(strip_trailing_slash(self.base), 
77
 
                       strip_trailing_slash(abspath))
 
93
        return urlutils.file_relpath(
 
94
            urlutils.strip_trailing_slash(self.base), 
 
95
            urlutils.strip_trailing_slash(abspath))
78
96
 
79
97
    def has(self, relpath):
80
 
        return os.access(self.abspath(relpath), os.F_OK)
 
98
        return os.access(self.local_abspath(relpath), os.F_OK)
81
99
 
82
100
    def get(self, relpath):
83
101
        """Get the file at the given relative path.
85
103
        :param relpath: The relative path to the file
86
104
        """
87
105
        try:
88
 
            path = self.abspath(relpath)
 
106
            path = self.local_abspath(relpath)
 
107
            # mutter('LocalTransport.get(%r) => %r', relpath, path)
89
108
            return open(path, 'rb')
90
109
        except (IOError, OSError),e:
91
110
            self._translate_error(e, path)
100
119
 
101
120
        path = relpath
102
121
        try:
103
 
            path = self.abspath(relpath)
 
122
            path = self.local_abspath(relpath)
104
123
            check_legal_path(path)
105
124
            fp = AtomicFile(path, 'wb', new_mode=mode)
106
125
        except (IOError, OSError),e:
127
146
        """Create a directory at the given path."""
128
147
        path = relpath
129
148
        try:
130
 
            path = self.abspath(relpath)
 
149
            path = self.local_abspath(relpath)
131
150
            os.mkdir(path)
132
151
            if mode is not None:
133
152
                os.chmod(path, mode)
139
158
        location.
140
159
        """
141
160
        try:
142
 
            fp = open(self.abspath(relpath), 'ab')
 
161
            fp = open(self.local_abspath(relpath), 'ab')
143
162
            if mode is not None:
144
 
                os.chmod(self.abspath(relpath), mode)
 
163
                os.chmod(self.local_abspath(relpath), mode)
145
164
        except (IOError, OSError),e:
146
165
            self._translate_error(e, relpath)
147
166
        # win32 workaround (tell on an unwritten file returns 0)
152
171
 
153
172
    def copy(self, rel_from, rel_to):
154
173
        """Copy the item at rel_from to the location at rel_to"""
155
 
        path_from = self.abspath(rel_from)
156
 
        path_to = self.abspath(rel_to)
 
174
        path_from = self.local_abspath(rel_from)
 
175
        path_to = self.local_abspath(rel_to)
157
176
        try:
158
177
            shutil.copy(path_from, path_to)
159
178
        except (IOError, OSError),e:
161
180
            self._translate_error(e, path_from)
162
181
 
163
182
    def rename(self, rel_from, rel_to):
164
 
        path_from = self.abspath(rel_from)
 
183
        path_from = self.local_abspath(rel_from)
165
184
        try:
166
185
            # *don't* call bzrlib.osutils.rename, because we want to 
167
186
            # detect errors on rename
168
 
            os.rename(path_from, self.abspath(rel_to))
 
187
            os.rename(path_from, self.local_abspath(rel_to))
169
188
        except (IOError, OSError),e:
170
189
            # TODO: What about path_to?
171
190
            self._translate_error(e, path_from)
172
191
 
173
192
    def move(self, rel_from, rel_to):
174
193
        """Move the item at rel_from to the location at rel_to"""
175
 
        path_from = self.abspath(rel_from)
176
 
        path_to = self.abspath(rel_to)
 
194
        path_from = self.local_abspath(rel_from)
 
195
        path_to = self.local_abspath(rel_to)
177
196
 
178
197
        try:
179
198
            # this version will delete the destination if necessary
186
205
        """Delete the item at relpath"""
187
206
        path = relpath
188
207
        try:
189
 
            path = self.abspath(relpath)
 
208
            path = self.local_abspath(relpath)
190
209
            os.remove(path)
191
210
        except (IOError, OSError),e:
192
211
            # TODO: What about path_to?
206
225
            for path in relpaths:
207
226
                self._update_pb(pb, 'copy-to', count, total)
208
227
                try:
209
 
                    mypath = self.abspath(path)
210
 
                    otherpath = other.abspath(path)
 
228
                    mypath = self.local_abspath(path)
 
229
                    otherpath = other.local_abspath(path)
211
230
                    shutil.copy(mypath, otherpath)
212
231
                    if mode is not None:
213
232
                        os.chmod(otherpath, mode)
227
246
        WARNING: many transports do not support this, so trying avoid using
228
247
        it if at all possible.
229
248
        """
230
 
        path = self.abspath(relpath)
 
249
        path = self.local_abspath(relpath)
231
250
        try:
232
 
            return [urllib.quote(entry) for entry in os.listdir(path)]
 
251
            return [urlutils.escape(entry) for entry in os.listdir(path)]
233
252
        except (IOError, OSError), e:
234
253
            self._translate_error(e, path)
235
254
 
238
257
        """
239
258
        path = relpath
240
259
        try:
241
 
            path = self.abspath(relpath)
 
260
            path = self.local_abspath(relpath)
242
261
            return os.stat(path)
243
262
        except (IOError, OSError),e:
244
263
            self._translate_error(e, path)
250
269
        from bzrlib.lock import ReadLock
251
270
        path = relpath
252
271
        try:
253
 
            path = self.abspath(relpath)
 
272
            path = self.local_abspath(relpath)
254
273
            return ReadLock(path)
255
274
        except (IOError, OSError), e:
256
275
            self._translate_error(e, path)
262
281
        :return: A lock object, which should be passed to Transport.unlock()
263
282
        """
264
283
        from bzrlib.lock import WriteLock
265
 
        return WriteLock(self.abspath(relpath))
 
284
        return WriteLock(self.local_abspath(relpath))
266
285
 
267
286
    def rmdir(self, relpath):
268
287
        """See Transport.rmdir."""
269
288
        path = relpath
270
289
        try:
271
 
            path = self.abspath(relpath)
 
290
            path = self.local_abspath(relpath)
272
291
            os.rmdir(path)
273
292
        except (IOError, OSError),e:
274
293
            self._translate_error(e, path)
319
338
 
320
339
    def get_url(self):
321
340
        """See Transport.Server.get_url."""
322
 
        # FIXME: \ to / on windows
323
 
        return "file://%s" % os.path.abspath("")
 
341
        return urlutils.local_path_to_url('')
324
342
 
325
343
 
326
344
def get_test_permutations():