70
72
from bzrlib import symbol_versioning
75
# Cross platform wall-clock time functionality with decent resolution.
76
# On Linux ``time.clock`` returns only CPU time. On Windows, ``time.time()``
77
# only has a resolution of ~15ms. Note that ``time.clock()`` is not
78
# synchronized with ``time.time()``, this is only meant to be used to find
79
# delta times by subtracting from another call to this function.
80
timer_func = time.time
81
if sys.platform == 'win32':
82
timer_func = time.clock
73
84
# On win32, O_BINARY is used to indicate the file should
74
85
# be opened in binary mode, rather than text mode.
75
86
# On other platforms, O_BINARY doesn't exist, because
191
202
:param old: The old path, to rename from
192
203
:param new: The new path, to rename to
193
204
:param rename_func: The potentially non-atomic rename function
194
:param unlink_func: A way to delete the target file if the full rename succeeds
205
:param unlink_func: A way to delete the target file if the full rename
197
208
# sftp rename doesn't allow overwriting, so play tricks:
198
209
base = os.path.basename(new)
199
210
dirname = os.path.dirname(new)
200
tmp_name = u'tmp.%s.%.9f.%d.%s' % (base, time.time(), os.getpid(), rand_chars(10))
211
# callers use different encodings for the paths so the following MUST
212
# respect that. We rely on python upcasting to unicode if new is unicode
213
# and keeping a str if not.
214
tmp_name = 'tmp.%s.%.9f.%d.%s' % (base, time.time(),
215
os.getpid(), rand_chars(10))
201
216
tmp_name = pathjoin(dirname, tmp_name)
203
218
# Rename the file out of the way, but keep track if it didn't exist
234
250
# source and target may be aliases of each other (e.g. on a
235
251
# case-insensitive filesystem), so we may have accidentally renamed
236
252
# source by when we tried to rename target
237
if not (file_existed and e.errno in (None, errno.ENOENT)):
253
failure_exc = sys.exc_info()
254
if (file_existed and e.errno in (None, errno.ENOENT)
255
and old.lower() == new.lower()):
256
# source and target are the same file on a case-insensitive
257
# filesystem, so we don't generate an exception
241
261
# If the file used to exist, rename it back into place
706
730
date_str = time.strftime(date_fmt, tt)
707
731
return date_str + offset_str
734
# Cache of formatted offset strings
738
def format_date_with_offset_in_original_timezone(t, offset=0,
739
_cache=_offset_cache):
740
"""Return a formatted date string in the original timezone.
742
This routine may be faster then format_date.
744
:param t: Seconds since the epoch.
745
:param offset: Timezone offset in seconds east of utc.
749
tt = time.gmtime(t + offset)
750
date_fmt = _default_format_by_weekday_num[tt[6]]
751
date_str = time.strftime(date_fmt, tt)
752
offset_str = _cache.get(offset, None)
753
if offset_str is None:
754
offset_str = ' %+03d%02d' % (offset / 3600, (offset / 60) % 60)
755
_cache[offset] = offset_str
756
return date_str + offset_str
709
759
def format_local_date(t, offset=0, timezone='original', date_fmt=None,
710
760
show_offset=True):
711
761
"""Return an unicode date string formatted according to the current locale.
935
_extension_load_failures = []
938
def failed_to_load_extension(exception):
939
"""Handle failing to load a binary extension.
941
This should be called from the ImportError block guarding the attempt to
942
import the native extension. If this function returns, the pure-Python
943
implementation should be loaded instead::
946
>>> import bzrlib._fictional_extension_pyx
947
>>> except ImportError, e:
948
>>> bzrlib.osutils.failed_to_load_extension(e)
949
>>> import bzrlib._fictional_extension_py
951
# NB: This docstring is just an example, not a doctest, because doctest
952
# currently can't cope with the use of lazy imports in this namespace --
955
# This currently doesn't report the failure at the time it occurs, because
956
# they tend to happen very early in startup when we can't check config
957
# files etc, and also we want to report all failures but not spam the user
959
from bzrlib import trace
960
exception_str = str(exception)
961
if exception_str not in _extension_load_failures:
962
trace.mutter("failed to load compiled extension: %s" % exception_str)
963
_extension_load_failures.append(exception_str)
966
def report_extension_load_failures():
967
if not _extension_load_failures:
969
from bzrlib.config import GlobalConfig
970
if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
972
# the warnings framework should by default show this only once
973
from bzrlib.trace import warning
975
"bzr: warning: some compiled extensions could not be loaded; "
976
"see <https://answers.launchpad.net/bzr/+faq/703>")
977
# we no longer show the specific missing extensions here, because it makes
978
# the message too long and scary - see
979
# https://bugs.launchpad.net/bzr/+bug/430529
885
983
from bzrlib._chunks_to_lines_pyx import chunks_to_lines
984
except ImportError, e:
985
failed_to_load_extension(e)
887
986
from bzrlib._chunks_to_lines_py import chunks_to_lines
1238
1344
normalized_filename = _inaccessible_normalized_filename
1347
default_terminal_width = 80
1348
"""The default terminal width for ttys.
1350
This is defined so that higher levels can share a common fallback value when
1351
terminal_width() returns None.
1241
1355
def terminal_width():
1242
"""Return estimated terminal width."""
1243
if sys.platform == 'win32':
1244
return win32utils.get_console_size()[0]
1356
"""Return terminal width.
1358
None is returned if the width can't established precisely.
1361
- if BZR_COLUMNS is set, returns its value
1362
- if there is no controlling terminal, returns None
1363
- if COLUMNS is set, returns its value,
1365
From there, we need to query the OS to get the size of the controlling
1369
- get termios.TIOCGWINSZ
1370
- if an error occurs or a negative value is obtained, returns None
1374
- win32utils.get_console_size() decides,
1375
- returns None on error (provided default value)
1378
# If BZR_COLUMNS is set, take it, user is always right
1380
return int(os.environ['BZR_COLUMNS'])
1381
except (KeyError, ValueError):
1384
isatty = getattr(sys.stdout, 'isatty', None)
1385
if isatty is None or not isatty():
1386
# Don't guess, setting BZR_COLUMNS is the recommended way to override.
1389
# If COLUMNS is set, take it, the terminal knows better (even inside a
1390
# given terminal, the application can decide to set COLUMNS to a lower
1391
# value (splitted screen) or a bigger value (scroll bars))
1393
return int(os.environ['COLUMNS'])
1394
except (KeyError, ValueError):
1397
width, height = _terminal_size(None, None)
1399
# Consider invalid values as meaning no width
1405
def _win32_terminal_size(width, height):
1406
width, height = win32utils.get_console_size(defaultx=width, defaulty=height)
1407
return width, height
1410
def _ioctl_terminal_size(width, height):
1247
1412
import struct, fcntl, termios
1248
1413
s = struct.pack('HHHH', 0, 0, 0, 0)
1249
1414
x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
1250
width = struct.unpack('HHHH', x)[1]
1415
height, width = struct.unpack('HHHH', x)[0:2]
1416
except (IOError, AttributeError):
1255
width = int(os.environ['COLUMNS'])
1418
return width, height
1420
_terminal_size = None
1421
"""Returns the terminal size as (width, height).
1423
:param width: Default value for width.
1424
:param height: Default value for height.
1426
This is defined specifically for each OS and query the size of the controlling
1427
terminal. If any error occurs, the provided default values should be returned.
1429
if sys.platform == 'win32':
1430
_terminal_size = _win32_terminal_size
1432
_terminal_size = _ioctl_terminal_size
1435
def _terminal_size_changed(signum, frame):
1436
"""Set COLUMNS upon receiving a SIGnal for WINdow size CHange."""
1437
width, height = _terminal_size(None, None)
1438
if width is not None:
1439
os.environ['COLUMNS'] = str(width)
1441
if sys.platform == 'win32':
1442
# Martin (gz) mentioned WINDOW_BUFFER_SIZE_RECORD from ReadConsoleInput but
1443
# I've no idea how to plug that in the current design -- vila 20091216
1446
signal.signal(signal.SIGWINCH, _terminal_size_changed)
1264
1449
def supports_executable():