/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/osutils.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
import os
18
18
import re
19
19
import stat
20
 
from stat import (S_ISREG, S_ISDIR, S_ISLNK, ST_MODE, ST_SIZE,
21
 
                  S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
 
20
from stat import S_ISREG, S_ISDIR, S_ISLNK, ST_MODE, ST_SIZE
22
21
import sys
23
22
import time
24
23
import codecs
25
 
import warnings
26
24
 
27
25
from bzrlib.lazy_import import lazy_import
28
26
lazy_import(globals(), """
39
37
from shutil import (
40
38
    rmtree,
41
39
    )
42
 
import signal
43
40
import socket
44
41
import subprocess
45
42
import tempfile
363
360
    return _win32_fixdrive(tempfile.mkdtemp(*args, **kwargs).replace('\\', '/'))
364
361
 
365
362
 
 
363
def _add_rename_error_details(e, old, new):
 
364
    new_e = OSError(e.errno, "failed to rename %s to %s: %s"
 
365
        % (old, new, e.strerror))
 
366
    new_e.filename = old
 
367
    new_e.to_filename = new
 
368
    return new_e
 
369
 
 
370
 
366
371
def _win32_rename(old, new):
367
372
    """We expect to be able to atomically replace 'new' with old.
368
373
 
370
375
    and then deleted.
371
376
    """
372
377
    try:
373
 
        fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
 
378
        fancy_rename(old, new, rename_func=_wrapped_rename, unlink_func=os.unlink)
374
379
    except OSError, e:
375
380
        if e.errno in (errno.EPERM, errno.EACCES, errno.EBUSY, errno.EINVAL):
376
381
            # If we try to rename a non-existant file onto cwd, we get
381
386
        raise
382
387
 
383
388
 
 
389
def _wrapped_rename(old, new):
 
390
    """Rename a file or directory"""
 
391
    try:
 
392
        os.rename(old, new)
 
393
    except (IOError, OSError), e:
 
394
        # this is eventually called by all rename-like functions, so should 
 
395
        # catch all of them
 
396
        raise _add_rename_error_details(e, old, new)
 
397
 
 
398
 
384
399
def _mac_getcwd():
385
400
    return unicodedata.normalize('NFC', os.getcwdu())
386
401
 
391
406
realpath = _posix_realpath
392
407
pathjoin = os.path.join
393
408
normpath = os.path.normpath
 
409
rename = _wrapped_rename # overridden below on win32
394
410
getcwd = os.getcwdu
395
 
rename = os.rename
396
411
dirname = os.path.dirname
397
412
basename = os.path.basename
398
413
split = os.path.split
1132
1147
 
1133
1148
 
1134
1149
def relpath(base, path):
1135
 
    """Return path relative to base, or raise exception.
 
1150
    """Return path relative to base, or raise PathNotChild exception.
1136
1151
 
1137
1152
    The path may be either an absolute path or a path relative to the
1138
1153
    current working directory.
1140
1155
    os.path.commonprefix (python2.4) has a bad bug that it works just
1141
1156
    on string prefixes, assuming that '/u' is a prefix of '/u2'.  This
1142
1157
    avoids that problem.
 
1158
 
 
1159
    NOTE: `base` should not have a trailing slash otherwise you'll get
 
1160
    PathNotChild exceptions regardless of `path`.
1143
1161
    """
1144
1162
 
1145
1163
    if len(base) < MIN_ABS_PATHLENGTH:
1365
1383
        False)`).  May be ignored if the feature is not available on this
1366
1384
        platform or Python version.
1367
1385
    """
1368
 
    old_handler = signal.signal(signum, handler)
 
1386
    try:
 
1387
        import signal
 
1388
        siginterrupt = signal.siginterrupt
 
1389
    except ImportError:
 
1390
        # This python implementation doesn't provide signal support, hence no
 
1391
        # handler exists
 
1392
        return None
 
1393
    except AttributeError:
 
1394
        # siginterrupt doesn't exist on this platform, or for this version
 
1395
        # of Python.
 
1396
        siginterrupt = lambda signum, flag: None
1369
1397
    if restart_syscall:
1370
 
        try:
1371
 
            siginterrupt = signal.siginterrupt
1372
 
        except AttributeError: # siginterrupt doesn't exist on this platform, or for this version of
1373
 
            # Python.
1374
 
            pass
1375
 
        else:
 
1398
        def sig_handler(*args):
 
1399
            # Python resets the siginterrupt flag when a signal is
 
1400
            # received.  <http://bugs.python.org/issue8354>
 
1401
            # As a workaround for some cases, set it back the way we want it.
1376
1402
            siginterrupt(signum, False)
 
1403
            # Now run the handler function passed to set_signal_handler.
 
1404
            handler(*args)
 
1405
    else:
 
1406
        sig_handler = handler
 
1407
    old_handler = signal.signal(signum, sig_handler)
 
1408
    if restart_syscall:
 
1409
        siginterrupt(signum, False)
1377
1410
    return old_handler
1378
1411
 
1379
1412
 
1473
1506
 
1474
1507
 
1475
1508
_registered_sigwinch = False
1476
 
 
1477
1509
def watch_sigwinch():
1478
 
    """Register for SIGWINCH, once and only once."""
 
1510
    """Register for SIGWINCH, once and only once.
 
1511
 
 
1512
    Do nothing if the signal module is not available.
 
1513
    """
1479
1514
    global _registered_sigwinch
1480
1515
    if not _registered_sigwinch:
1481
 
        if sys.platform == 'win32':
1482
 
            # Martin (gz) mentioned WINDOW_BUFFER_SIZE_RECORD from
1483
 
            # ReadConsoleInput but I've no idea how to plug that in
1484
 
            # the current design -- vila 20091216
 
1516
        try:
 
1517
            import signal
 
1518
            if getattr(signal, "SIGWINCH", None) is not None:
 
1519
                set_signal_handler(signal.SIGWINCH, _terminal_size_changed)
 
1520
        except ImportError:
 
1521
            # python doesn't provide signal support, nothing we can do about it
1485
1522
            pass
1486
 
        else:
1487
 
            set_signal_handler(signal.SIGWINCH, _terminal_size_changed)
1488
1523
        _registered_sigwinch = True
1489
1524
 
1490
1525
 
1811
1846
            real_handlers[kind](abspath, relpath)
1812
1847
 
1813
1848
 
1814
 
def copy_ownership(dst, src=None):
 
1849
def copy_ownership_from_path(dst, src=None):
1815
1850
    """Copy usr/grp ownership from src file/dir to dst file/dir.
1816
1851
 
1817
1852
    If src is None, the containing directory is used as source. If chown
1833
1868
        trace.warning("Unable to copy ownership from '%s' to '%s': IOError: %s." % (src, dst, e))
1834
1869
 
1835
1870
 
1836
 
def mkdir_with_ownership(path, ownership_src=None):
1837
 
    """Create the directory 'path' with specified ownership.
1838
 
 
1839
 
    If ownership_src is given, copies (chown) usr/grp ownership
1840
 
    from 'ownership_src' to 'path'. If ownership_src is None, use the
1841
 
    containing dir ownership.
1842
 
    """
1843
 
    os.mkdir(path)
1844
 
    copy_ownership(path, ownership_src)
1845
 
 
1846
 
 
1847
 
def open_with_ownership(filename, mode='r', bufsize=-1, ownership_src=None):
1848
 
    """Open the file 'filename' with the specified ownership.
1849
 
 
1850
 
    If ownership_src is specified, copy usr/grp ownership from ownership_src
1851
 
    to filename. If ownership_src is None, copy ownership from containing
1852
 
    directory.
1853
 
    Returns the opened file object.
1854
 
    """
1855
 
    f = open(filename, mode, bufsize)
1856
 
    copy_ownership(filename, ownership_src)
1857
 
    return f
1858
 
 
1859
 
 
1860
1871
def path_prefix_key(path):
1861
1872
    """Generate a prefix-order path key for path.
1862
1873