~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Jelmer Vernooij
  • Date: 2011-04-09 19:25:42 UTC
  • mto: (5777.5.1 inventoryworkingtree)
  • mto: This revision was merged to the branch mainline in revision 5781.
  • Revision ID: jelmer@samba.org-20110409192542-8bbedp36s7nj928e
Split InventoryTree out of Tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
 
43
43
from bzrlib import (
44
44
    cache_utf8,
45
 
    config,
46
45
    errors,
47
46
    trace,
48
47
    win32utils,
49
48
    )
50
 
from bzrlib.i18n import gettext
51
49
""")
52
50
 
53
51
from bzrlib.symbol_versioning import (
55
53
    deprecated_in,
56
54
    )
57
55
 
58
 
from hashlib import (
59
 
    md5,
60
 
    sha1 as sha,
61
 
    )
 
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
        )
62
68
 
63
69
 
64
70
import bzrlib
90
96
        user_encoding = get_user_encoding()
91
97
        return [a.decode(user_encoding) for a in sys.argv[1:]]
92
98
    except UnicodeDecodeError:
93
 
        raise errors.BzrError(gettext("Parameter {0!r} encoding is unsupported by {1} "
94
 
            "application locale.").format(a, user_encoding))
 
99
        raise errors.BzrError(("Parameter '%r' is unsupported by the current "
 
100
                                                            "encoding." % a))
95
101
 
96
102
 
97
103
def make_readonly(filename):
191
197
            if e.errno == errno.ENOENT:
192
198
                return False;
193
199
            else:
194
 
                raise errors.BzrError(gettext("lstat/stat of ({0!r}): {1!r}").format(f, e))
 
200
                raise errors.BzrError("lstat/stat of (%r): %r" % (f, e))
195
201
 
196
202
 
197
203
def fancy_rename(old, new, rename_func, unlink_func):
263
269
            else:
264
270
                rename_func(tmp_name, new)
265
271
    if failure_exc is not None:
266
 
        try:
267
 
            raise failure_exc[0], failure_exc[1], failure_exc[2]
268
 
        finally:
269
 
            del failure_exc
 
272
        raise failure_exc[0], failure_exc[1], failure_exc[2]
270
273
 
271
274
 
272
275
# In Python 2.4.2 and older, os.path.abspath and os.path.realpath
279
282
    # copy posixpath.abspath, but use os.getcwdu instead
280
283
    if not posixpath.isabs(path):
281
284
        path = posixpath.join(getcwd(), path)
282
 
    return _posix_normpath(path)
 
285
    return posixpath.normpath(path)
283
286
 
284
287
 
285
288
def _posix_realpath(path):
286
289
    return posixpath.realpath(path.encode(_fs_enc)).decode(_fs_enc)
287
290
 
288
291
 
289
 
def _posix_normpath(path):
290
 
    path = posixpath.normpath(path)
291
 
    # Bug 861008: posixpath.normpath() returns a path normalized according to
292
 
    # the POSIX standard, which stipulates (for compatibility reasons) that two
293
 
    # leading slashes must not be simplified to one, and only if there are 3 or
294
 
    # more should they be simplified as one. So we treat the leading 2 slashes
295
 
    # as a special case here by simply removing the first slash, as we consider
296
 
    # that breaking POSIX compatibility for this obscure feature is acceptable.
297
 
    # This is not a paranoid precaution, as we notably get paths like this when
298
 
    # the repo is hosted at the root of the filesystem, i.e. in "/".    
299
 
    if path.startswith('//'):
300
 
        path = path[1:]
301
 
    return path
302
 
 
303
 
 
304
292
def _win32_fixdrive(path):
305
293
    """Force drive letters to be consistent.
306
294
 
394
382
abspath = _posix_abspath
395
383
realpath = _posix_realpath
396
384
pathjoin = os.path.join
397
 
normpath = _posix_normpath
 
385
normpath = os.path.normpath
398
386
getcwd = os.getcwdu
399
387
rename = os.rename
400
388
dirname = os.path.dirname
941
929
    rps = []
942
930
    for f in ps:
943
931
        if f == '..':
944
 
            raise errors.BzrError(gettext("sorry, %r not allowed in path") % f)
 
932
            raise errors.BzrError("sorry, %r not allowed in path" % f)
945
933
        elif (f == '.') or (f == ''):
946
934
            pass
947
935
        else:
952
940
def joinpath(p):
953
941
    for f in p:
954
942
        if (f == '..') or (f is None) or (f == ''):
955
 
            raise errors.BzrError(gettext("sorry, %r not allowed in path") % f)
 
943
            raise errors.BzrError("sorry, %r not allowed in path" % f)
956
944
    return pathjoin(*p)
957
945
 
958
946
 
1002
990
def report_extension_load_failures():
1003
991
    if not _extension_load_failures:
1004
992
        return
1005
 
    if config.GlobalStack().get('ignore_missing_extensions'):
 
993
    from bzrlib.config import GlobalConfig
 
994
    if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
1006
995
        return
1007
996
    # the warnings framework should by default show this only once
1008
997
    from bzrlib.trace import warning
1170
1159
 
1171
1160
    if len(base) < MIN_ABS_PATHLENGTH:
1172
1161
        # must have space for e.g. a drive letter
1173
 
        raise ValueError(gettext('%r is too short to calculate a relative path')
 
1162
        raise ValueError('%r is too short to calculate a relative path'
1174
1163
            % (base,))
1175
1164
 
1176
1165
    rp = abspath(path)
2194
2183
    return file_kind_from_stat_mode(mode)
2195
2184
file_kind_from_stat_mode = file_kind_from_stat_mode_thunk
2196
2185
 
2197
 
def file_stat(f, _lstat=os.lstat):
 
2186
 
 
2187
def file_kind(f, _lstat=os.lstat):
2198
2188
    try:
2199
 
        # XXX cache?
2200
 
        return _lstat(f)
 
2189
        return file_kind_from_stat_mode(_lstat(f).st_mode)
2201
2190
    except OSError, e:
2202
2191
        if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
2203
2192
            raise errors.NoSuchFile(f)
2204
2193
        raise
2205
2194
 
2206
 
def file_kind(f, _lstat=os.lstat):
2207
 
    stat_value = file_stat(f, _lstat)
2208
 
    return file_kind_from_stat_mode(stat_value.st_mode)
2209
2195
 
2210
2196
def until_no_eintr(f, *a, **kw):
2211
2197
    """Run f(*a, **kw), retrying if an EINTR error occurs.
2271
2257
            termios.tcsetattr(fd, termios.TCSADRAIN, settings)
2272
2258
        return ch
2273
2259
 
2274
 
if sys.platform.startswith('linux'):
 
2260
if sys.platform == 'linux2':
2275
2261
    def _local_concurrency():
2276
2262
        try:
2277
2263
            return os.sysconf('SC_NPROCESSORS_ONLN')
2400
2386
    except UnicodeDecodeError:
2401
2387
        raise errors.BzrError("Can't decode username as %s." % \
2402
2388
                user_encoding)
2403
 
    except ImportError, e:
2404
 
        if sys.platform != 'win32':
2405
 
            raise
2406
 
        if str(e) != 'No module named pwd':
2407
 
            raise
2408
 
        # https://bugs.launchpad.net/bzr/+bug/660174
2409
 
        # getpass.getuser() is unable to return username on Windows
2410
 
        # if there is no USERNAME environment variable set.
2411
 
        # That could be true if bzr is running as a service,
2412
 
        # e.g. running `bzr serve` as a service on Windows.
2413
 
        # We should not fail with traceback in this case.
2414
 
        username = u'UNKNOWN'
2415
2389
    return username
2416
2390
 
2417
2391
 
2479
2453
            if os.access(f, os.X_OK):
2480
2454
                return f
2481
2455
    return None
2482
 
 
2483
 
 
2484
 
def _posix_is_local_pid_dead(pid):
2485
 
    """True if pid doesn't correspond to live process on this machine"""
2486
 
    try:
2487
 
        # Special meaning of unix kill: just check if it's there.
2488
 
        os.kill(pid, 0)
2489
 
    except OSError, e:
2490
 
        if e.errno == errno.ESRCH:
2491
 
            # On this machine, and really not found: as sure as we can be
2492
 
            # that it's dead.
2493
 
            return True
2494
 
        elif e.errno == errno.EPERM:
2495
 
            # exists, though not ours
2496
 
            return False
2497
 
        else:
2498
 
            mutter("os.kill(%d, 0) failed: %s" % (pid, e))
2499
 
            # Don't really know.
2500
 
            return False
2501
 
    else:
2502
 
        # Exists and our process: not dead.
2503
 
        return False
2504
 
 
2505
 
if sys.platform == "win32":
2506
 
    is_local_pid_dead = win32utils.is_local_pid_dead
2507
 
else:
2508
 
    is_local_pid_dead = _posix_is_local_pid_dead
2509
 
 
2510
 
 
2511
 
def fdatasync(fileno):
2512
 
    """Flush file contents to disk if possible.
2513
 
    
2514
 
    :param fileno: Integer OS file handle.
2515
 
    :raises TransportNotPossible: If flushing to disk is not possible.
2516
 
    """
2517
 
    fn = getattr(os, 'fdatasync', getattr(os, 'fsync', None))
2518
 
    if fn is not None:
2519
 
        fn(fileno)