~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/local.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-14 12:15:44 UTC
  • mto: This revision was merged to the branch mainline in revision 6365.
  • Revision ID: jelmer@samba.org-20111214121544-v07cbvmi30re6q7w
s/NoVfsCalls/ContainsNoVfsCalls/.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
20
20
"""
21
21
 
22
22
import os
23
 
from stat import ST_MODE, S_ISDIR, ST_SIZE, S_IMODE
 
23
from stat import ST_MODE, S_ISDIR, S_IMODE
24
24
import sys
25
25
 
26
26
from bzrlib.lazy_import import lazy_import
33
33
    osutils,
34
34
    urlutils,
35
35
    symbol_versioning,
36
 
    transport,
37
36
    )
38
 
from bzrlib.trace import mutter
39
37
from bzrlib.transport import LateReadError
40
38
""")
41
39
 
42
40
from bzrlib import transport
43
41
 
44
42
 
45
 
_append_flags = os.O_CREAT | os.O_APPEND | os.O_WRONLY | osutils.O_BINARY
46
 
_put_non_atomic_flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | osutils.O_BINARY
 
43
_append_flags = os.O_CREAT | os.O_APPEND | os.O_WRONLY | osutils.O_BINARY | osutils.O_NOINHERIT
 
44
_put_non_atomic_flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | osutils.O_BINARY | osutils.O_NOINHERIT
47
45
 
48
46
 
49
47
class LocalTransport(transport.Transport):
74
72
 
75
73
        super(LocalTransport, self).__init__(base)
76
74
        self._local_base = urlutils.local_path_from_url(base)
 
75
        if self._local_base[-1] != '/':
 
76
            self._local_base = self._local_base + '/'
77
77
 
78
78
    def clone(self, offset=None):
79
79
        """Return a new LocalTransport with root at self.base + offset
99
99
         - relative_reference is url escaped.
100
100
        """
101
101
        if relative_reference in ('.', ''):
102
 
            return self._local_base
 
102
            # _local_base normally has a trailing slash; strip it so that stat
 
103
            # on a transport pointing to a symlink reads the link not the
 
104
            # referent but be careful of / and c:\
 
105
            return osutils.split(self._local_base)[0]
103
106
        return self._local_base + urlutils.unescape(relative_reference)
104
107
 
105
108
    def abspath(self, relpath):
143
146
        if abspath is None:
144
147
            abspath = u'.'
145
148
 
146
 
        return urlutils.file_relpath(
147
 
            urlutils.strip_trailing_slash(self.base),
148
 
            urlutils.strip_trailing_slash(abspath))
 
149
        return urlutils.file_relpath(self.base, abspath)
149
150
 
150
151
    def has(self, relpath):
151
152
        return os.access(self._abspath(relpath), os.F_OK)
160
161
            transport._file_streams[canonical_url].flush()
161
162
        try:
162
163
            path = self._abspath(relpath)
163
 
            return open(path, 'rb')
 
164
            return osutils.open_file(path, 'rb')
164
165
        except (IOError, OSError),e:
165
166
            if e.errno == errno.EISDIR:
166
167
                return LateReadError(relpath)
254
255
            if mode is not None and mode != S_IMODE(st.st_mode):
255
256
                # Because of umask, we may still need to chmod the file.
256
257
                # But in the general case, we won't have to
257
 
                os.chmod(abspath, mode)
 
258
                osutils.chmod_if_possible(abspath, mode)
258
259
            writer(fd)
259
260
        finally:
260
261
            os.close(fd)
313
314
            local_mode = mode
314
315
        try:
315
316
            os.mkdir(abspath, local_mode)
316
 
            if mode is not None:
317
 
                # It is probably faster to just do the chmod, rather than
318
 
                # doing a stat, and then trying to compare
319
 
                os.chmod(abspath, mode)
320
317
        except (IOError, OSError),e:
321
318
            self._translate_error(e, abspath)
 
319
        if mode is not None:
 
320
            try:
 
321
                osutils.chmod_if_possible(abspath, mode)
 
322
            except (IOError, OSError), e:
 
323
                self._translate_error(e, abspath)
322
324
 
323
325
    def mkdir(self, relpath, mode=None):
324
326
        """Create a directory at the given path."""
326
328
 
327
329
    def open_write_stream(self, relpath, mode=None):
328
330
        """See Transport.open_write_stream."""
329
 
        # initialise the file
330
 
        self.put_bytes_non_atomic(relpath, "", mode=mode)
331
331
        abspath = self._abspath(relpath)
332
 
        handle = open(abspath, 'wb')
 
332
        try:
 
333
            handle = osutils.open_file(abspath, 'wb')
 
334
        except (IOError, OSError),e:
 
335
            self._translate_error(e, abspath)
 
336
        handle.truncate()
333
337
        if mode is not None:
334
338
            self._check_mode_and_size(abspath, handle.fileno(), mode)
335
339
        transport._file_streams[self.abspath(relpath)] = handle
354
358
        if mode is not None and mode != S_IMODE(st.st_mode):
355
359
            # Because of umask, we may still need to chmod the file.
356
360
            # But in the general case, we won't have to
357
 
            os.chmod(file_abspath, mode)
 
361
            osutils.chmod_if_possible(file_abspath, mode)
358
362
        return st.st_size
359
363
 
360
364
    def append_file(self, relpath, f, mode=None):
399
403
 
400
404
    def rename(self, rel_from, rel_to):
401
405
        path_from = self._abspath(rel_from)
 
406
        path_to = self._abspath(rel_to)
402
407
        try:
403
408
            # *don't* call bzrlib.osutils.rename, because we want to
404
 
            # detect errors on rename
405
 
            os.rename(path_from, self._abspath(rel_to))
 
409
            # detect conflicting names on rename, and osutils.rename tries to
 
410
            # mask cross-platform differences there
 
411
            os.rename(path_from, path_to)
406
412
        except (IOError, OSError),e:
407
413
            # TODO: What about path_to?
408
414
            self._translate_error(e, path_from)
451
457
                    otherpath = other._abspath(path)
452
458
                    shutil.copy(mypath, otherpath)
453
459
                    if mode is not None:
454
 
                        os.chmod(otherpath, mode)
 
460
                        osutils.chmod_if_possible(otherpath, mode)
455
461
                except (IOError, OSError),e:
456
462
                    self._translate_error(e, path)
457
463
                count += 1
481
487
        path = relpath
482
488
        try:
483
489
            path = self._abspath(relpath)
484
 
            return os.stat(path)
 
490
            return os.lstat(path)
485
491
        except (IOError, OSError),e:
486
492
            self._translate_error(e, path)
487
493
 
515
521
        except (IOError, OSError),e:
516
522
            self._translate_error(e, path)
517
523
 
 
524
    if osutils.host_os_dereferences_symlinks():
 
525
        def readlink(self, relpath):
 
526
            """See Transport.readlink."""
 
527
            return osutils.readlink(self._abspath(relpath))
 
528
 
 
529
    if osutils.hardlinks_good():
 
530
        def hardlink(self, source, link_name):
 
531
            """See Transport.link."""
 
532
            try:
 
533
                os.link(self._abspath(source), self._abspath(link_name))
 
534
            except (IOError, OSError), e:
 
535
                self._translate_error(e, source)
 
536
 
 
537
    if osutils.has_symlinks():
 
538
        def symlink(self, source, link_name):
 
539
            """See Transport.symlink."""
 
540
            abs_link_dirpath = urlutils.dirname(self.abspath(link_name))
 
541
            source_rel = urlutils.file_relpath(
 
542
                abs_link_dirpath, self.abspath(source))
 
543
 
 
544
            try:
 
545
                os.symlink(source_rel, self._abspath(link_name))
 
546
            except (IOError, OSError), e:
 
547
                self._translate_error(e, source_rel)
 
548
 
518
549
    def _can_roundtrip_unix_modebits(self):
519
550
        if sys.platform == 'win32':
520
551
            # anyone else?
533
564
        self._local_base = urlutils._win32_local_path_from_url(base)
534
565
 
535
566
    def abspath(self, relpath):
536
 
        path = osutils.normpath(osutils.pathjoin(
 
567
        path = osutils._win32_normpath(osutils.pathjoin(
537
568
                    self._local_base, urlutils.unescape(relpath)))
538
569
        return urlutils._win32_local_path_to_url(path)
539
570