/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: John Arbash Meinel
  • Date: 2009-12-10 17:16:19 UTC
  • mfrom: (4884 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4889.
  • Revision ID: john@arbash-meinel.com-20091210171619-ehdcxjbl8afhq9g1
Bring in bzr.dev 4884

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
                  S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
22
22
import sys
23
23
import time
 
24
import warnings
24
25
 
25
26
from bzrlib.lazy_import import lazy_import
26
27
lazy_import(globals(), """
223
224
    else:
224
225
        file_existed = True
225
226
 
 
227
    failure_exc = None
226
228
    success = False
227
229
    try:
228
230
        try:
234
236
            # source and target may be aliases of each other (e.g. on a
235
237
            # case-insensitive filesystem), so we may have accidentally renamed
236
238
            # source by when we tried to rename target
237
 
            if not (file_existed and e.errno in (None, errno.ENOENT)):
238
 
                raise
 
239
            failure_exc = sys.exc_info()
 
240
            if (file_existed and e.errno in (None, errno.ENOENT)
 
241
                and old.lower() == new.lower()):
 
242
                # source and target are the same file on a case-insensitive
 
243
                # filesystem, so we don't generate an exception
 
244
                failure_exc = None
239
245
    finally:
240
246
        if file_existed:
241
247
            # If the file used to exist, rename it back into place
244
250
                unlink_func(tmp_name)
245
251
            else:
246
252
                rename_func(tmp_name, new)
 
253
    if failure_exc is not None:
 
254
        raise failure_exc[0], failure_exc[1], failure_exc[2]
247
255
 
248
256
 
249
257
# In Python 2.4.2 and older, os.path.abspath and os.path.realpath
687
695
    return offset.days * 86400 + offset.seconds
688
696
 
689
697
weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
 
698
_default_format_by_weekday_num = [wd + " %Y-%m-%d %H:%M:%S" for wd in weekdays]
 
699
 
690
700
 
691
701
def format_date(t, offset=0, timezone='original', date_fmt=None,
692
702
                show_offset=True):
706
716
    date_str = time.strftime(date_fmt, tt)
707
717
    return date_str + offset_str
708
718
 
 
719
 
 
720
# Cache of formatted offset strings
 
721
_offset_cache = {}
 
722
 
 
723
 
 
724
def format_date_with_offset_in_original_timezone(t, offset=0,
 
725
    _cache=_offset_cache):
 
726
    """Return a formatted date string in the original timezone.
 
727
 
 
728
    This routine may be faster then format_date.
 
729
 
 
730
    :param t: Seconds since the epoch.
 
731
    :param offset: Timezone offset in seconds east of utc.
 
732
    """
 
733
    if offset is None:
 
734
        offset = 0
 
735
    tt = time.gmtime(t + offset)
 
736
    date_fmt = _default_format_by_weekday_num[tt[6]]
 
737
    date_str = time.strftime(date_fmt, tt)
 
738
    offset_str = _cache.get(offset, None)
 
739
    if offset_str is None:
 
740
        offset_str = ' %+03d%02d' % (offset / 3600, (offset / 60) % 60)
 
741
        _cache[offset] = offset_str
 
742
    return date_str + offset_str
 
743
 
 
744
 
709
745
def format_local_date(t, offset=0, timezone='original', date_fmt=None,
710
746
                      show_offset=True):
711
747
    """Return an unicode date string formatted according to the current locale.
725
761
        date_str = date_str.decode(get_user_encoding(), 'replace')
726
762
    return date_str + offset_str
727
763
 
 
764
 
728
765
def _format_date(t, offset, timezone, date_fmt, show_offset):
729
766
    if timezone == 'utc':
730
767
        tt = time.gmtime(t)
881
918
    return parents
882
919
 
883
920
 
 
921
_extension_load_failures = []
 
922
 
 
923
 
 
924
def failed_to_load_extension(exception):
 
925
    """Handle failing to load a binary extension.
 
926
 
 
927
    This should be called from the ImportError block guarding the attempt to
 
928
    import the native extension.  If this function returns, the pure-Python
 
929
    implementation should be loaded instead::
 
930
 
 
931
    >>> try:
 
932
    >>>     import bzrlib._fictional_extension_pyx
 
933
    >>> except ImportError, e:
 
934
    >>>     bzrlib.osutils.failed_to_load_extension(e)
 
935
    >>>     import bzrlib._fictional_extension_py
 
936
    """
 
937
    # NB: This docstring is just an example, not a doctest, because doctest
 
938
    # currently can't cope with the use of lazy imports in this namespace --
 
939
    # mbp 20090729
 
940
    
 
941
    # This currently doesn't report the failure at the time it occurs, because
 
942
    # they tend to happen very early in startup when we can't check config
 
943
    # files etc, and also we want to report all failures but not spam the user
 
944
    # with 10 warnings.
 
945
    from bzrlib import trace
 
946
    exception_str = str(exception)
 
947
    if exception_str not in _extension_load_failures:
 
948
        trace.mutter("failed to load compiled extension: %s" % exception_str)
 
949
        _extension_load_failures.append(exception_str)
 
950
 
 
951
 
 
952
def report_extension_load_failures():
 
953
    if not _extension_load_failures:
 
954
        return
 
955
    from bzrlib.config import GlobalConfig
 
956
    if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
 
957
        return
 
958
    # the warnings framework should by default show this only once
 
959
    from bzrlib.trace import warning
 
960
    warning(
 
961
        "bzr: warning: some compiled extensions could not be loaded; "
 
962
        "see <https://answers.launchpad.net/bzr/+faq/703>")
 
963
    # we no longer show the specific missing extensions here, because it makes
 
964
    # the message too long and scary - see
 
965
    # https://bugs.launchpad.net/bzr/+bug/430529
 
966
 
 
967
 
884
968
try:
885
969
    from bzrlib._chunks_to_lines_pyx import chunks_to_lines
886
 
except ImportError:
 
970
except ImportError, e:
 
971
    failed_to_load_extension(e)
887
972
    from bzrlib._chunks_to_lines_py import chunks_to_lines
888
973
 
889
974
 
1245
1330
    normalized_filename = _inaccessible_normalized_filename
1246
1331
 
1247
1332
 
 
1333
default_terminal_width = 80
 
1334
"""The default terminal width for ttys.
 
1335
 
 
1336
This is defined so that higher levels can share a common fallback value when
 
1337
terminal_width() returns None.
 
1338
"""
 
1339
 
 
1340
 
1248
1341
def terminal_width():
1249
 
    """Return estimated terminal width."""
1250
 
    if sys.platform == 'win32':
1251
 
        return win32utils.get_console_size()[0]
1252
 
    width = 0
 
1342
    """Return terminal width.
 
1343
 
 
1344
    None is returned if the width can't established precisely.
 
1345
 
 
1346
    The rules are:
 
1347
    - if BZR_COLUMNS is set, returns its value
 
1348
    - if there is no controlling terminal, returns None
 
1349
    - if COLUMNS is set, returns its value,
 
1350
 
 
1351
    From there, we need to query the OS to get the size of the controlling
 
1352
    terminal.
 
1353
 
 
1354
    Unices:
 
1355
    - get termios.TIOCGWINSZ
 
1356
    - if an error occurs or a negative value is obtained, returns None
 
1357
 
 
1358
    Windows:
 
1359
    
 
1360
    - win32utils.get_console_size() decides,
 
1361
    - returns None on error (provided default value)
 
1362
    """
 
1363
 
 
1364
    # If BZR_COLUMNS is set, take it, user is always right
 
1365
    try:
 
1366
        return int(os.environ['BZR_COLUMNS'])
 
1367
    except (KeyError, ValueError):
 
1368
        pass
 
1369
 
 
1370
    isatty = getattr(sys.stdout, 'isatty', None)
 
1371
    if  isatty is None or not isatty():
 
1372
        # Don't guess, setting BZR_COLUMNS is the recommended way to override.
 
1373
        return None
 
1374
 
 
1375
    # If COLUMNS is set, take it, the terminal knows better (even inside a
 
1376
    # given terminal, the application can decide to set COLUMNS to a lower
 
1377
    # value (splitted screen) or a bigger value (scroll bars))
 
1378
    try:
 
1379
        return int(os.environ['COLUMNS'])
 
1380
    except (KeyError, ValueError):
 
1381
        pass
 
1382
 
 
1383
    width, height = _terminal_size(None, None)
 
1384
    if width <= 0:
 
1385
        # Consider invalid values as meaning no width
 
1386
        return None
 
1387
 
 
1388
    return width
 
1389
 
 
1390
 
 
1391
def _win32_terminal_size(width, height):
 
1392
    width, height = win32utils.get_console_size(defaultx=width, defaulty=height)
 
1393
    return width, height
 
1394
 
 
1395
 
 
1396
def _ioctl_terminal_size(width, height):
1253
1397
    try:
1254
1398
        import struct, fcntl, termios
1255
1399
        s = struct.pack('HHHH', 0, 0, 0, 0)
1256
1400
        x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
1257
 
        width = struct.unpack('HHHH', x)[1]
1258
 
    except IOError:
 
1401
        height, width = struct.unpack('HHHH', x)[0:2]
 
1402
    except (IOError, AttributeError):
1259
1403
        pass
1260
 
    if width <= 0:
1261
 
        try:
1262
 
            width = int(os.environ['COLUMNS'])
1263
 
        except:
1264
 
            pass
1265
 
    if width <= 0:
1266
 
        width = 80
1267
 
 
1268
 
    return width
 
1404
    return width, height
 
1405
 
 
1406
_terminal_size = None
 
1407
"""Returns the terminal size as (width, height).
 
1408
 
 
1409
:param width: Default value for width.
 
1410
:param height: Default value for height.
 
1411
 
 
1412
This is defined specifically for each OS and query the size of the controlling
 
1413
terminal. If any error occurs, the provided default values should be returned.
 
1414
"""
 
1415
if sys.platform == 'win32':
 
1416
    _terminal_size = _win32_terminal_size
 
1417
else:
 
1418
    _terminal_size = _ioctl_terminal_size
1269
1419
 
1270
1420
 
1271
1421
def supports_executable():
1473
1623
            try:
1474
1624
                from bzrlib._readdir_pyx import UTF8DirReader
1475
1625
                _selected_dir_reader = UTF8DirReader()
1476
 
            except ImportError:
 
1626
            except ImportError, e:
 
1627
                failed_to_load_extension(e)
1477
1628
                pass
1478
1629
 
1479
1630
    if _selected_dir_reader is None:
1785
1936
        try:
1786
1937
            from bzrlib._readdir_pyx import UTF8DirReader
1787
1938
            file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1788
 
        except ImportError:
 
1939
        except ImportError, e:
 
1940
            # This is one time where we won't warn that an extension failed to
 
1941
            # load. The extension is never available on Windows anyway.
1789
1942
            from bzrlib._readdir_py import (
1790
1943
                _kind_from_mode as file_kind_from_stat_mode
1791
1944
                )
1893
2046
    anything goes wrong.
1894
2047
    """
1895
2048
    global _cached_local_concurrency
 
2049
 
1896
2050
    if _cached_local_concurrency is not None and use_cache:
1897
2051
        return _cached_local_concurrency
1898
2052
 
1899
 
    try:
1900
 
        concurrency = _local_concurrency()
1901
 
    except (OSError, IOError):
1902
 
        concurrency = None
 
2053
    concurrency = os.environ.get('BZR_CONCURRENCY', None)
 
2054
    if concurrency is None:
 
2055
        try:
 
2056
            concurrency = _local_concurrency()
 
2057
        except (OSError, IOError):
 
2058
            pass
1903
2059
    try:
1904
2060
        concurrency = int(concurrency)
1905
2061
    except (TypeError, ValueError):