/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: Jonathan Lange
  • Date: 2009-12-09 09:20:42 UTC
  • mfrom: (4881 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4907.
  • Revision ID: jml@canonical.com-20091209092042-s2zgqcf8f39yzxpj
Merge trunk.

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
 
1040
1125
 
1041
1126
    s = []
1042
1127
    head = rp
1043
 
    while len(head) >= len(base):
 
1128
    while True:
 
1129
        if len(head) <= len(base) and head != base:
 
1130
            raise errors.PathNotChild(rp, base)
1044
1131
        if head == base:
1045
1132
            break
1046
 
        head, tail = os.path.split(head)
 
1133
        head, tail = split(head)
1047
1134
        if tail:
1048
 
            s.insert(0, tail)
1049
 
    else:
1050
 
        raise errors.PathNotChild(rp, base)
 
1135
            s.append(tail)
1051
1136
 
1052
1137
    if s:
1053
 
        return pathjoin(*s)
 
1138
        return pathjoin(*reversed(s))
1054
1139
    else:
1055
1140
        return ''
1056
1141
 
1083
1168
    bit_iter = iter(rel.split('/'))
1084
1169
    for bit in bit_iter:
1085
1170
        lbit = bit.lower()
1086
 
        for look in _listdir(current):
 
1171
        try:
 
1172
            next_entries = _listdir(current)
 
1173
        except OSError: # enoent, eperm, etc
 
1174
            # We can't find this in the filesystem, so just append the
 
1175
            # remaining bits.
 
1176
            current = pathjoin(current, bit, *list(bit_iter))
 
1177
            break
 
1178
        for look in next_entries:
1087
1179
            if lbit == look.lower():
1088
1180
                current = pathjoin(current, look)
1089
1181
                break
1093
1185
            # the target of a move, for example).
1094
1186
            current = pathjoin(current, bit, *list(bit_iter))
1095
1187
            break
1096
 
    return current[len(abs_base)+1:]
 
1188
    return current[len(abs_base):].lstrip('/')
1097
1189
 
1098
1190
# XXX - TODO - we need better detection/integration of case-insensitive
1099
1191
# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
1238
1330
    normalized_filename = _inaccessible_normalized_filename
1239
1331
 
1240
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
 
1241
1341
def terminal_width():
1242
 
    """Return estimated terminal width."""
 
1342
    """Return terminal width.
 
1343
 
 
1344
    None is returned if the width can't established precisely.
 
1345
    """
 
1346
 
 
1347
    # If BZR_COLUMNS is set, take it, user is always right
 
1348
    try:
 
1349
        return int(os.environ['BZR_COLUMNS'])
 
1350
    except (KeyError, ValueError):
 
1351
        pass
 
1352
 
 
1353
    isatty = getattr(sys.stdout, 'isatty', None)
 
1354
    if  isatty is None or not isatty():
 
1355
        # Don't guess, setting BZR_COLUMNS is the recommended way to override.
 
1356
        return None
 
1357
 
1243
1358
    if sys.platform == 'win32':
1244
 
        return win32utils.get_console_size()[0]
1245
 
    width = 0
 
1359
        return win32utils.get_console_size(defaultx=None)[0]
 
1360
 
1246
1361
    try:
1247
1362
        import struct, fcntl, termios
1248
1363
        s = struct.pack('HHHH', 0, 0, 0, 0)
1249
1364
        x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
1250
1365
        width = struct.unpack('HHHH', x)[1]
1251
 
    except IOError:
1252
 
        pass
1253
 
    if width <= 0:
 
1366
    except (IOError, AttributeError):
 
1367
        # If COLUMNS is set, take it
1254
1368
        try:
1255
 
            width = int(os.environ['COLUMNS'])
1256
 
        except:
1257
 
            pass
 
1369
            return int(os.environ['COLUMNS'])
 
1370
        except (KeyError, ValueError):
 
1371
            return None
 
1372
 
1258
1373
    if width <= 0:
1259
 
        width = 80
 
1374
        # Consider invalid values as meaning no width
 
1375
        return None
1260
1376
 
1261
1377
    return width
1262
1378
 
1466
1582
            try:
1467
1583
                from bzrlib._readdir_pyx import UTF8DirReader
1468
1584
                _selected_dir_reader = UTF8DirReader()
1469
 
            except ImportError:
 
1585
            except ImportError, e:
 
1586
                failed_to_load_extension(e)
1470
1587
                pass
1471
1588
 
1472
1589
    if _selected_dir_reader is None:
1778
1895
        try:
1779
1896
            from bzrlib._readdir_pyx import UTF8DirReader
1780
1897
            file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1781
 
        except ImportError:
 
1898
        except ImportError, e:
 
1899
            # This is one time where we won't warn that an extension failed to
 
1900
            # load. The extension is never available on Windows anyway.
1782
1901
            from bzrlib._readdir_py import (
1783
1902
                _kind_from_mode as file_kind_from_stat_mode
1784
1903
                )
1886
2005
    anything goes wrong.
1887
2006
    """
1888
2007
    global _cached_local_concurrency
 
2008
 
1889
2009
    if _cached_local_concurrency is not None and use_cache:
1890
2010
        return _cached_local_concurrency
1891
2011
 
1892
 
    try:
1893
 
        concurrency = _local_concurrency()
1894
 
    except (OSError, IOError):
1895
 
        concurrency = None
 
2012
    concurrency = os.environ.get('BZR_CONCURRENCY', None)
 
2013
    if concurrency is None:
 
2014
        try:
 
2015
            concurrency = _local_concurrency()
 
2016
        except (OSError, IOError):
 
2017
            pass
1896
2018
    try:
1897
2019
        concurrency = int(concurrency)
1898
2020
    except (TypeError, ValueError):