~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Jonathan Riddell
  • Date: 2011-09-16 15:37:58 UTC
  • mto: This revision was merged to the branch mainline in revision 6146.
  • Revision ID: jriddell@canonical.com-20110916153758-y936k3hysjc1tphy
update tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 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
42
42
 
43
43
from bzrlib import (
44
44
    cache_utf8,
 
45
    config,
45
46
    errors,
46
47
    trace,
47
48
    win32utils,
53
54
    deprecated_in,
54
55
    )
55
56
 
56
 
# sha and md5 modules are deprecated in python2.6 but hashlib is available as
57
 
# of 2.5
58
 
if sys.version_info < (2, 5):
59
 
    import md5 as _mod_md5
60
 
    md5 = _mod_md5.new
61
 
    import sha as _mod_sha
62
 
    sha = _mod_sha.new
63
 
else:
64
 
    from hashlib import (
65
 
        md5,
66
 
        sha1 as sha,
67
 
        )
 
57
from hashlib import (
 
58
    md5,
 
59
    sha1 as sha,
 
60
    )
68
61
 
69
62
 
70
63
import bzrlib
96
89
        user_encoding = get_user_encoding()
97
90
        return [a.decode(user_encoding) for a in sys.argv[1:]]
98
91
    except UnicodeDecodeError:
99
 
        raise errors.BzrError(("Parameter '%r' is unsupported by the current "
100
 
                                                            "encoding." % a))
 
92
        raise errors.BzrError("Parameter %r encoding is unsupported by %s "
 
93
            "application locale." % (a, user_encoding))
101
94
 
102
95
 
103
96
def make_readonly(filename):
269
262
            else:
270
263
                rename_func(tmp_name, new)
271
264
    if failure_exc is not None:
272
 
        raise failure_exc[0], failure_exc[1], failure_exc[2]
 
265
        try:
 
266
            raise failure_exc[0], failure_exc[1], failure_exc[2]
 
267
        finally:
 
268
            del failure_exc
273
269
 
274
270
 
275
271
# In Python 2.4.2 and older, os.path.abspath and os.path.realpath
392
388
# These were already lazily imported into local scope
393
389
# mkdtemp = tempfile.mkdtemp
394
390
# rmtree = shutil.rmtree
 
391
lstat = os.lstat
 
392
fstat = os.fstat
 
393
 
 
394
def wrap_stat(st):
 
395
    return st
 
396
 
395
397
 
396
398
MIN_ABS_PATHLENGTH = 1
397
399
 
407
409
    getcwd = _win32_getcwd
408
410
    mkdtemp = _win32_mkdtemp
409
411
    rename = _win32_rename
 
412
    try:
 
413
        from bzrlib import _walkdirs_win32
 
414
    except ImportError:
 
415
        pass
 
416
    else:
 
417
        lstat = _walkdirs_win32.lstat
 
418
        fstat = _walkdirs_win32.fstat
 
419
        wrap_stat = _walkdirs_win32.wrap_stat
410
420
 
411
421
    MIN_ABS_PATHLENGTH = 3
412
422
 
967
977
    # they tend to happen very early in startup when we can't check config
968
978
    # files etc, and also we want to report all failures but not spam the user
969
979
    # with 10 warnings.
970
 
    from bzrlib import trace
971
980
    exception_str = str(exception)
972
981
    if exception_str not in _extension_load_failures:
973
982
        trace.mutter("failed to load compiled extension: %s" % exception_str)
977
986
def report_extension_load_failures():
978
987
    if not _extension_load_failures:
979
988
        return
980
 
    from bzrlib.config import GlobalConfig
981
 
    if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
 
989
    if config.GlobalStack().get('ignore_missing_extensions'):
982
990
        return
983
991
    # the warnings framework should by default show this only once
984
992
    from bzrlib.trace import warning
1462
1470
    # a similar effect.
1463
1471
 
1464
1472
    # If BZR_COLUMNS is set, take it, user is always right
 
1473
    # Except if they specified 0 in which case, impose no limit here
1465
1474
    try:
1466
 
        return int(os.environ['BZR_COLUMNS'])
 
1475
        width = int(os.environ['BZR_COLUMNS'])
1467
1476
    except (KeyError, ValueError):
1468
 
        pass
 
1477
        width = None
 
1478
    if width is not None:
 
1479
        if width > 0:
 
1480
            return width
 
1481
        else:
 
1482
            return None
1469
1483
 
1470
1484
    isatty = getattr(sys.stdout, 'isatty', None)
1471
1485
    if isatty is None or not isatty():
1875
1889
        s = os.stat(src)
1876
1890
        chown(dst, s.st_uid, s.st_gid)
1877
1891
    except OSError, e:
1878
 
        trace.warning("Unable to copy ownership from '%s' to '%s': IOError: %s." % (src, dst, e))
 
1892
        trace.warning(
 
1893
            'Unable to copy ownership from "%s" to "%s". '
 
1894
            'You may want to set it manually.', src, dst)
 
1895
        trace.log_exception_quietly()
1879
1896
 
1880
1897
 
1881
1898
def path_prefix_key(path):
1993
2010
# data at once.
1994
2011
MAX_SOCKET_CHUNK = 64 * 1024
1995
2012
 
 
2013
_end_of_stream_errors = [errno.ECONNRESET]
 
2014
for _eno in ['WSAECONNRESET', 'WSAECONNABORTED']:
 
2015
    _eno = getattr(errno, _eno, None)
 
2016
    if _eno is not None:
 
2017
        _end_of_stream_errors.append(_eno)
 
2018
del _eno
 
2019
 
 
2020
 
1996
2021
def read_bytes_from_socket(sock, report_activity=None,
1997
2022
        max_read_size=MAX_SOCKET_CHUNK):
1998
2023
    """Read up to max_read_size of bytes from sock and notify of progress.
2006
2031
            bytes = sock.recv(max_read_size)
2007
2032
        except socket.error, e:
2008
2033
            eno = e.args[0]
2009
 
            if eno == getattr(errno, "WSAECONNRESET", errno.ECONNRESET):
 
2034
            if eno in _end_of_stream_errors:
2010
2035
                # The connection was closed by the other side.  Callers expect
2011
2036
                # an empty string to signal end-of-stream.
2012
2037
                return ""
2153
2178
    return file_kind_from_stat_mode(mode)
2154
2179
file_kind_from_stat_mode = file_kind_from_stat_mode_thunk
2155
2180
 
2156
 
 
2157
 
def file_kind(f, _lstat=os.lstat):
 
2181
def file_stat(f, _lstat=os.lstat):
2158
2182
    try:
2159
 
        return file_kind_from_stat_mode(_lstat(f).st_mode)
 
2183
        # XXX cache?
 
2184
        return _lstat(f)
2160
2185
    except OSError, e:
2161
2186
        if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
2162
2187
            raise errors.NoSuchFile(f)
2163
2188
        raise
2164
2189
 
 
2190
def file_kind(f, _lstat=os.lstat):
 
2191
    stat_value = file_stat(f, _lstat)
 
2192
    return file_kind_from_stat_mode(stat_value.st_mode)
2165
2193
 
2166
2194
def until_no_eintr(f, *a, **kw):
2167
2195
    """Run f(*a, **kw), retrying if an EINTR error occurs.
2227
2255
            termios.tcsetattr(fd, termios.TCSADRAIN, settings)
2228
2256
        return ch
2229
2257
 
2230
 
 
2231
 
if sys.platform == 'linux2':
 
2258
if sys.platform.startswith('linux'):
2232
2259
    def _local_concurrency():
2233
 
        concurrency = None
2234
 
        prefix = 'processor'
2235
 
        for line in file('/proc/cpuinfo', 'rb'):
2236
 
            if line.startswith(prefix):
2237
 
                concurrency = int(line[line.find(':')+1:]) + 1
2238
 
        return concurrency
 
2260
        try:
 
2261
            return os.sysconf('SC_NPROCESSORS_ONLN')
 
2262
        except (ValueError, OSError, AttributeError):
 
2263
            return None
2239
2264
elif sys.platform == 'darwin':
2240
2265
    def _local_concurrency():
2241
2266
        return subprocess.Popen(['sysctl', '-n', 'hw.availcpu'],
2242
2267
                                stdout=subprocess.PIPE).communicate()[0]
2243
 
elif sys.platform[0:7] == 'freebsd':
 
2268
elif "bsd" in sys.platform:
2244
2269
    def _local_concurrency():
2245
2270
        return subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
2246
2271
                                stdout=subprocess.PIPE).communicate()[0]
2274
2299
    concurrency = os.environ.get('BZR_CONCURRENCY', None)
2275
2300
    if concurrency is None:
2276
2301
        try:
2277
 
            concurrency = _local_concurrency()
2278
 
        except (OSError, IOError):
2279
 
            pass
 
2302
            import multiprocessing
 
2303
        except ImportError:
 
2304
            # multiprocessing is only available on Python >= 2.6
 
2305
            try:
 
2306
                concurrency = _local_concurrency()
 
2307
            except (OSError, IOError):
 
2308
                pass
 
2309
        else:
 
2310
            concurrency = multiprocessing.cpu_count()
2280
2311
    try:
2281
2312
        concurrency = int(concurrency)
2282
2313
    except (TypeError, ValueError):
2353
2384
    except UnicodeDecodeError:
2354
2385
        raise errors.BzrError("Can't decode username as %s." % \
2355
2386
                user_encoding)
 
2387
    except ImportError, e:
 
2388
        if sys.platform != 'win32':
 
2389
            raise
 
2390
        if str(e) != 'No module named pwd':
 
2391
            raise
 
2392
        # https://bugs.launchpad.net/bzr/+bug/660174
 
2393
        # getpass.getuser() is unable to return username on Windows
 
2394
        # if there is no USERNAME environment variable set.
 
2395
        # That could be true if bzr is running as a service,
 
2396
        # e.g. running `bzr serve` as a service on Windows.
 
2397
        # We should not fail with traceback in this case.
 
2398
        username = u'UNKNOWN'
2356
2399
    return username
 
2400
 
 
2401
 
 
2402
def available_backup_name(base, exists):
 
2403
    """Find a non-existing backup file name.
 
2404
 
 
2405
    This will *not* create anything, this only return a 'free' entry.  This
 
2406
    should be used for checking names in a directory below a locked
 
2407
    tree/branch/repo to avoid race conditions. This is LBYL (Look Before You
 
2408
    Leap) and generally discouraged.
 
2409
 
 
2410
    :param base: The base name.
 
2411
 
 
2412
    :param exists: A callable returning True if the path parameter exists.
 
2413
    """
 
2414
    counter = 1
 
2415
    name = "%s.~%d~" % (base, counter)
 
2416
    while exists(name):
 
2417
        counter += 1
 
2418
        name = "%s.~%d~" % (base, counter)
 
2419
    return name
 
2420
 
 
2421
 
 
2422
def set_fd_cloexec(fd):
 
2423
    """Set a Unix file descriptor's FD_CLOEXEC flag.  Do nothing if platform
 
2424
    support for this is not available.
 
2425
    """
 
2426
    try:
 
2427
        import fcntl
 
2428
        old = fcntl.fcntl(fd, fcntl.F_GETFD)
 
2429
        fcntl.fcntl(fd, fcntl.F_SETFD, old | fcntl.FD_CLOEXEC)
 
2430
    except (ImportError, AttributeError):
 
2431
        # Either the fcntl module or specific constants are not present
 
2432
        pass
 
2433
 
 
2434
 
 
2435
def find_executable_on_path(name):
 
2436
    """Finds an executable on the PATH.
 
2437
    
 
2438
    On Windows, this will try to append each extension in the PATHEXT
 
2439
    environment variable to the name, if it cannot be found with the name
 
2440
    as given.
 
2441
    
 
2442
    :param name: The base name of the executable.
 
2443
    :return: The path to the executable found or None.
 
2444
    """
 
2445
    path = os.environ.get('PATH')
 
2446
    if path is None:
 
2447
        return None
 
2448
    path = path.split(os.pathsep)
 
2449
    if sys.platform == 'win32':
 
2450
        exts = os.environ.get('PATHEXT', '').split(os.pathsep)
 
2451
        exts = [ext.lower() for ext in exts]
 
2452
        base, ext = os.path.splitext(name)
 
2453
        if ext != '':
 
2454
            if ext.lower() not in exts:
 
2455
                return None
 
2456
            name = base
 
2457
            exts = [ext]
 
2458
    else:
 
2459
        exts = ['']
 
2460
    for ext in exts:
 
2461
        for d in path:
 
2462
            f = os.path.join(d, name) + ext
 
2463
            if os.access(f, os.X_OK):
 
2464
                return f
 
2465
    return None
 
2466
 
 
2467
 
 
2468
def _posix_is_local_pid_dead(pid):
 
2469
    """True if pid doesn't correspond to live process on this machine"""
 
2470
    try:
 
2471
        # Special meaning of unix kill: just check if it's there.
 
2472
        os.kill(pid, 0)
 
2473
    except OSError, e:
 
2474
        if e.errno == errno.ESRCH:
 
2475
            # On this machine, and really not found: as sure as we can be
 
2476
            # that it's dead.
 
2477
            return True
 
2478
        elif e.errno == errno.EPERM:
 
2479
            # exists, though not ours
 
2480
            return False
 
2481
        else:
 
2482
            mutter("os.kill(%d, 0) failed: %s" % (pid, e))
 
2483
            # Don't really know.
 
2484
            return False
 
2485
    else:
 
2486
        # Exists and our process: not dead.
 
2487
        return False
 
2488
 
 
2489
if sys.platform == "win32":
 
2490
    is_local_pid_dead = win32utils.is_local_pid_dead
 
2491
else:
 
2492
    is_local_pid_dead = _posix_is_local_pid_dead
 
2493
 
 
2494
 
 
2495
def fdatasync(fileno):
 
2496
    """Flush file contents to disk if possible.
 
2497
    
 
2498
    :param fileno: Integer OS file handle.
 
2499
    :raises TransportNotPossible: If flushing to disk is not possible.
 
2500
    """
 
2501
    fn = getattr(os, 'fdatasync', getattr(os, 'fsync', None))
 
2502
    if fn is not None:
 
2503
        fn(fileno)