77
70
O_BINARY = getattr(os, 'O_BINARY', 0)
80
def get_unicode_argv():
82
user_encoding = get_user_encoding()
83
return [a.decode(user_encoding) for a in sys.argv[1:]]
84
except UnicodeDecodeError:
85
raise errors.BzrError(("Parameter '%r' is unsupported by the current "
89
73
def make_readonly(filename):
90
74
"""Make a filename read-only."""
91
mod = os.lstat(filename).st_mode
92
if not stat.S_ISLNK(mod):
94
os.chmod(filename, mod)
75
mod = os.stat(filename).st_mode
77
os.chmod(filename, mod)
97
80
def make_writable(filename):
98
mod = os.lstat(filename).st_mode
99
if not stat.S_ISLNK(mod):
101
os.chmod(filename, mod)
104
def minimum_path_selection(paths):
105
"""Return the smallset subset of paths which are outside paths.
107
:param paths: A container (and hence not None) of paths.
108
:return: A set of paths sufficient to include everything in paths via
109
is_inside, drawn from the paths parameter.
115
return path.split('/')
116
sorted_paths = sorted(list(paths), key=sort_key)
118
search_paths = [sorted_paths[0]]
119
for path in sorted_paths[1:]:
120
if not is_inside(search_paths[-1], path):
121
# This path is unique, add it
122
search_paths.append(path)
124
return set(search_paths)
81
mod = os.stat(filename).st_mode
83
os.chmod(filename, mod)
332
319
"""We expect to be able to atomically replace 'new' with old.
334
321
On win32, if new exists, it must be moved out of the way first,
338
325
fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
339
326
except OSError, e:
340
327
if e.errno in (errno.EPERM, errno.EACCES, errno.EBUSY, errno.EINVAL):
341
# If we try to rename a non-existant file onto cwd, we get
342
# EPERM or EACCES instead of ENOENT, this will raise ENOENT
328
# If we try to rename a non-existant file onto cwd, we get
329
# EPERM or EACCES instead of ENOENT, this will raise ENOENT
343
330
# if the old path doesn't exist, sometimes we get EACCES
344
331
# On Linux, we seem to get EBUSY, on Mac we get EINVAL
531
def pumpfile(from_file, to_file, read_length=-1, buff_size=32768,
532
report_activity=None, direction='read'):
533
"""Copy contents of one file to another.
535
The read_length can either be -1 to read to end-of-file (EOF) or
536
it can specify the maximum number of bytes to read.
538
The buff_size represents the maximum size for each read operation
539
performed on from_file.
541
:param report_activity: Call this as bytes are read, see
542
Transport._report_activity
543
:param direction: Will be passed to report_activity
545
:return: The number of bytes copied.
549
# read specified number of bytes
551
while read_length > 0:
552
num_bytes_to_read = min(read_length, buff_size)
554
block = from_file.read(num_bytes_to_read)
558
if report_activity is not None:
559
report_activity(len(block), direction)
562
actual_bytes_read = len(block)
563
read_length -= actual_bytes_read
564
length += actual_bytes_read
568
block = from_file.read(buff_size)
572
if report_activity is not None:
573
report_activity(len(block), direction)
579
def pump_string_file(bytes, file_handle, segment_size=None):
580
"""Write bytes to file_handle in many smaller writes.
582
:param bytes: The string to write.
583
:param file_handle: The file to write to.
585
# Write data in chunks rather than all at once, because very large
586
# writes fail on some platforms (e.g. Windows with SMB mounted
589
segment_size = 5242880 # 5MB
590
segments = range(len(bytes) / segment_size + 1)
591
write = file_handle.write
592
for segment_index in segments:
593
segment = buffer(bytes, segment_index * segment_size, segment_size)
535
def pumpfile(fromfile, tofile):
536
"""Copy contents of one file to another."""
539
b = fromfile.read(BUFSIZE)
597
545
def file_iterator(input_file, readsize=32768):
685
605
offset = datetime.fromtimestamp(t) - datetime.utcfromtimestamp(t)
686
606
return offset.days * 86400 + offset.seconds
688
weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
690
def format_date(t, offset=0, timezone='original', date_fmt=None,
609
def format_date(t, offset=0, timezone='original', date_fmt=None,
691
610
show_offset=True):
692
"""Return a formatted date string.
694
:param t: Seconds since the epoch.
695
:param offset: Timezone offset in seconds east of utc.
696
:param timezone: How to display the time: 'utc', 'original' for the
697
timezone specified by offset, or 'local' for the process's current
699
:param date_fmt: strftime format.
700
:param show_offset: Whether to append the timezone.
702
(date_fmt, tt, offset_str) = \
703
_format_date(t, offset, timezone, date_fmt, show_offset)
704
date_fmt = date_fmt.replace('%a', weekdays[tt[6]])
705
date_str = time.strftime(date_fmt, tt)
706
return date_str + offset_str
708
def format_local_date(t, offset=0, timezone='original', date_fmt=None,
710
"""Return an unicode date string formatted according to the current locale.
712
:param t: Seconds since the epoch.
713
:param offset: Timezone offset in seconds east of utc.
714
:param timezone: How to display the time: 'utc', 'original' for the
715
timezone specified by offset, or 'local' for the process's current
717
:param date_fmt: strftime format.
718
:param show_offset: Whether to append the timezone.
720
(date_fmt, tt, offset_str) = \
721
_format_date(t, offset, timezone, date_fmt, show_offset)
722
date_str = time.strftime(date_fmt, tt)
723
if not isinstance(date_str, unicode):
724
date_str = date_str.decode(bzrlib.user_encoding, 'replace')
725
return date_str + offset_str
727
def _format_date(t, offset, timezone, date_fmt, show_offset):
611
## TODO: Perhaps a global option to use either universal or local time?
612
## Or perhaps just let people set $TZ?
613
assert isinstance(t, float)
728
615
if timezone == 'utc':
729
616
tt = time.gmtime(t)
753
assert isinstance(p, (list, tuple))
865
755
if (f == '..') or (f is None) or (f == ''):
866
756
raise errors.BzrError("sorry, %r not allowed in path" % f)
867
757
return pathjoin(*p)
870
def parent_directories(filename):
871
"""Return the list of parent directories, deepest first.
760
@deprecated_function(zero_nine)
761
def appendpath(p1, p2):
765
return pathjoin(p1, p2)
873
For example, parent_directories("a/b/c") -> ["a/b", "a"].
876
parts = splitpath(dirname(filename))
878
parents.append(joinpath(parts))
884
from bzrlib._chunks_to_lines_pyx import chunks_to_lines
886
from bzrlib._chunks_to_lines_py import chunks_to_lines
889
768
def split_lines(s):
890
769
"""Split s into lines, but without removing the newline characters."""
891
# Trivially convert a fulltext into a 'chunked' representation, and let
892
# chunks_to_lines do the heavy lifting.
893
if isinstance(s, str):
894
# chunks_to_lines only supports 8-bit strings
895
return chunks_to_lines([s])
897
return _split_lines(s)
901
"""Split s into lines, but without removing the newline characters.
903
This supports Unicode or plain string objects.
905
770
lines = s.split('\n')
906
771
result = [line + '\n' for line in lines[:-1]]
1039
def _cicp_canonical_relpath(base, path):
1040
"""Return the canonical path relative to base.
1042
Like relpath, but on case-insensitive-case-preserving file-systems, this
1043
will return the relpath as stored on the file-system rather than in the
1044
case specified in the input string, for all existing portions of the path.
1046
This will cause O(N) behaviour if called for every path in a tree; if you
1047
have a number of paths to convert, you should use canonical_relpaths().
1049
# TODO: it should be possible to optimize this for Windows by using the
1050
# win32 API FindFiles function to look for the specified name - but using
1051
# os.listdir() still gives us the correct, platform agnostic semantics in
1054
rel = relpath(base, path)
1055
# '.' will have been turned into ''
1059
abs_base = abspath(base)
1061
_listdir = os.listdir
1063
# use an explicit iterator so we can easily consume the rest on early exit.
1064
bit_iter = iter(rel.split('/'))
1065
for bit in bit_iter:
1067
for look in _listdir(current):
1068
if lbit == look.lower():
1069
current = pathjoin(current, look)
1072
# got to the end, nothing matched, so we just return the
1073
# non-existing bits as they were specified (the filename may be
1074
# the target of a move, for example).
1075
current = pathjoin(current, bit, *list(bit_iter))
1077
return current[len(abs_base)+1:]
1079
# XXX - TODO - we need better detection/integration of case-insensitive
1080
# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
1081
# filesystems), for example, so could probably benefit from the same basic
1082
# support there. For now though, only Windows and OSX get that support, and
1083
# they get it for *all* file-systems!
1084
if sys.platform in ('win32', 'darwin'):
1085
canonical_relpath = _cicp_canonical_relpath
1087
canonical_relpath = relpath
1089
def canonical_relpaths(base, paths):
1090
"""Create an iterable to canonicalize a sequence of relative paths.
1092
The intent is for this implementation to use a cache, vastly speeding
1093
up multiple transformations in the same directory.
1095
# but for now, we haven't optimized...
1096
return [canonical_relpath(base, p) for p in paths]
1098
874
def safe_unicode(unicode_or_utf8_string):
1099
875
"""Coerce unicode_or_utf8_string into unicode.
1101
877
If it is unicode, it is returned.
1102
Otherwise it is decoded from utf-8. If decoding fails, the exception is
1103
wrapped in a BzrBadParameterNotUnicode exception.
878
Otherwise it is decoded from utf-8. If a decoding error
879
occurs, it is wrapped as a If the decoding fails, the exception is wrapped
880
as a BzrBadParameter exception.
1105
882
if isinstance(unicode_or_utf8_string, unicode):
1106
883
return unicode_or_utf8_string
1194
971
On platforms where the system normalizes filenames (Mac OSX),
1195
972
you can access a file by any path which will normalize correctly.
1196
On platforms where the system does not normalize filenames
973
On platforms where the system does not normalize filenames
1197
974
(Windows, Linux), you have to access a file by its exact path.
1199
Internally, bzr only supports NFC normalization, since that is
976
Internally, bzr only supports NFC/NFKC normalization, since that is
1200
977
the standard for XML documents.
1202
979
So return the normalized path, and a flag indicating if the file
1203
980
can be accessed by that path.
1206
return unicodedata.normalize('NFC', unicode(path)), True
983
return unicodedata.normalize('NFKC', unicode(path)), True
1209
986
def _inaccessible_normalized_filename(path):
1210
987
__doc__ = _accessible_normalized_filename.__doc__
1212
normalized = unicodedata.normalize('NFC', unicode(path))
989
normalized = unicodedata.normalize('NFKC', unicode(path))
1213
990
return normalized, normalized == path
1292
1069
raise errors.IllegalPath(path)
1295
_WIN32_ERROR_DIRECTORY = 267 # Similar to errno.ENOTDIR
1297
def _is_error_enotdir(e):
1298
"""Check if this exception represents ENOTDIR.
1300
Unfortunately, python is very inconsistent about the exception
1301
here. The cases are:
1302
1) Linux, Mac OSX all versions seem to set errno == ENOTDIR
1303
2) Windows, Python2.4, uses errno == ERROR_DIRECTORY (267)
1304
which is the windows error code.
1305
3) Windows, Python2.5 uses errno == EINVAL and
1306
winerror == ERROR_DIRECTORY
1308
:param e: An Exception object (expected to be OSError with an errno
1309
attribute, but we should be able to cope with anything)
1310
:return: True if this represents an ENOTDIR error. False otherwise.
1312
en = getattr(e, 'errno', None)
1313
if (en == errno.ENOTDIR
1314
or (sys.platform == 'win32'
1315
and (en == _WIN32_ERROR_DIRECTORY
1316
or (en == errno.EINVAL
1317
and getattr(e, 'winerror', None) == _WIN32_ERROR_DIRECTORY)
1323
1072
def walkdirs(top, prefix=""):
1324
1073
"""Yield data about all the directories in a tree.
1326
1075
This yields all the data about the contents of a directory at a time.
1327
1076
After each directory has been yielded, if the caller has mutated the list
1328
1077
to exclude some directories, they are then not descended into.
1330
1079
The data yielded is of the form:
1331
1080
((directory-relpath, directory-path-from-top),
1332
[(relpath, basename, kind, lstat, path-from-top), ...]),
1081
[(directory-relpath, basename, kind, lstat, path-from-top), ...]),
1333
1082
- directory-relpath is the relative path of the directory being returned
1334
1083
with respect to top. prefix is prepended to this.
1335
- directory-path-from-root is the path including top for this directory.
1084
- directory-path-from-root is the path including top for this directory.
1336
1085
It is suitable for use with os functions.
1337
1086
- relpath is the relative path within the subtree being walked.
1338
1087
- basename is the basename of the path
1340
1089
present within the tree - but it may be recorded as versioned. See
1341
1090
versioned_kind.
1342
1091
- lstat is the stat data *if* the file was statted.
1343
- planned, not implemented:
1092
- planned, not implemented:
1344
1093
path_from_tree_root is the path from the root of the tree.
1346
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
1095
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
1347
1096
allows one to walk a subtree but get paths that are relative to a tree
1348
1097
rooted higher up.
1349
1098
:return: an iterator over the dirs.
1351
1100
#TODO there is a bit of a smell where the results of the directory-
1352
# summary in this, and the path from the root, may not agree
1101
# summary in this, and the path from the root, may not agree
1353
1102
# depending on top and prefix - i.e. ./foo and foo as a pair leads to
1354
1103
# potentially confusing output. We should make this more robust - but
1355
1104
# not at a speed cost. RBC 20060731
1356
1105
_lstat = os.lstat
1357
1106
_directory = _directory_kind
1358
1107
_listdir = os.listdir
1359
_kind_from_mode = file_kind_from_stat_mode
1108
_kind_from_mode = _formats.get
1360
1109
pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
1362
1111
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1371
1120
append = dirblock.append
1373
names = sorted(_listdir(top))
1375
if not _is_error_enotdir(e):
1379
abspath = top_slash + name
1380
statvalue = _lstat(abspath)
1381
kind = _kind_from_mode(statvalue.st_mode)
1382
append((relprefix + name, name, kind, statvalue, abspath))
1121
for name in sorted(_listdir(top)):
1122
abspath = top_slash + name
1123
statvalue = _lstat(abspath)
1124
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1125
append((relprefix + name, name, kind, statvalue, abspath))
1383
1126
yield (relroot, top), dirblock
1385
1128
# push the user specified dirs from dirblock
1386
1129
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1389
class DirReader(object):
1390
"""An interface for reading directories."""
1392
def top_prefix_to_starting_dir(self, top, prefix=""):
1393
"""Converts top and prefix to a starting dir entry
1395
:param top: A utf8 path
1396
:param prefix: An optional utf8 path to prefix output relative paths
1398
:return: A tuple starting with prefix, and ending with the native
1401
raise NotImplementedError(self.top_prefix_to_starting_dir)
1403
def read_dir(self, prefix, top):
1404
"""Read a specific dir.
1406
:param prefix: A utf8 prefix to be preprended to the path basenames.
1407
:param top: A natively encoded path to read.
1408
:return: A list of the directories contents. Each item contains:
1409
(utf8_relpath, utf8_name, kind, lstatvalue, native_abspath)
1411
raise NotImplementedError(self.read_dir)
1414
_selected_dir_reader = None
1417
1132
def _walkdirs_utf8(top, prefix=""):
1418
1133
"""Yield data about all the directories in a tree.
1428
1143
path-from-top might be unicode or utf8, but it is the correct path to
1429
1144
pass to os functions to affect the file in question. (such as os.lstat)
1431
global _selected_dir_reader
1432
if _selected_dir_reader is None:
1433
fs_encoding = _fs_enc.upper()
1434
if sys.platform == "win32" and win32utils.winver == 'Windows NT':
1435
# Win98 doesn't have unicode apis like FindFirstFileW
1436
# TODO: We possibly could support Win98 by falling back to the
1437
# original FindFirstFile, and using TCHAR instead of WCHAR,
1438
# but that gets a bit tricky, and requires custom compiling
1441
from bzrlib._walkdirs_win32 import Win32ReadDir
1442
_selected_dir_reader = Win32ReadDir()
1445
elif fs_encoding in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
1446
# ANSI_X3.4-1968 is a form of ASCII
1448
from bzrlib._readdir_pyx import UTF8DirReader
1449
_selected_dir_reader = UTF8DirReader()
1453
if _selected_dir_reader is None:
1454
# Fallback to the python version
1455
_selected_dir_reader = UnicodeDirReader()
1146
fs_encoding = sys.getfilesystemencoding()
1147
if (sys.platform == 'win32' or
1148
fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968')): # ascii
1149
return _walkdirs_unicode_to_utf8(top, prefix=prefix)
1151
return _walkdirs_fs_utf8(top, prefix=prefix)
1154
def _walkdirs_fs_utf8(top, prefix=""):
1155
"""See _walkdirs_utf8.
1157
This sub-function is called when we know the filesystem is already in utf8
1158
encoding. So we don't need to transcode filenames.
1161
_directory = _directory_kind
1162
_listdir = os.listdir
1163
_kind_from_mode = _formats.get
1457
1165
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1458
1166
# But we don't actually uses 1-3 in pending, so set them to None
1459
pending = [[_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]]
1460
read_dir = _selected_dir_reader.read_dir
1461
_directory = _directory_kind
1167
pending = [(safe_utf8(prefix), None, None, None, safe_utf8(top))]
1463
relroot, _, _, _, top = pending[-1].pop()
1466
dirblock = sorted(read_dir(relroot, top))
1169
relroot, _, _, _, top = pending.pop()
1171
relprefix = relroot + '/'
1174
top_slash = top + '/'
1177
append = dirblock.append
1178
for name in sorted(_listdir(top)):
1179
abspath = top_slash + name
1180
statvalue = _lstat(abspath)
1181
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1182
append((relprefix + name, name, kind, statvalue, abspath))
1467
1183
yield (relroot, top), dirblock
1468
1185
# push the user specified dirs from dirblock
1469
next = [d for d in reversed(dirblock) if d[2] == _directory]
1471
pending.append(next)
1474
class UnicodeDirReader(DirReader):
1475
"""A dir reader for non-utf8 file systems, which transcodes."""
1477
__slots__ = ['_utf8_encode']
1480
self._utf8_encode = codecs.getencoder('utf8')
1482
def top_prefix_to_starting_dir(self, top, prefix=""):
1483
"""See DirReader.top_prefix_to_starting_dir."""
1484
return (safe_utf8(prefix), None, None, None, safe_unicode(top))
1486
def read_dir(self, prefix, top):
1487
"""Read a single directory from a non-utf8 file system.
1489
top, and the abspath element in the output are unicode, all other paths
1490
are utf8. Local disk IO is done via unicode calls to listdir etc.
1492
This is currently the fallback code path when the filesystem encoding is
1493
not UTF-8. It may be better to implement an alternative so that we can
1494
safely handle paths that are not properly decodable in the current
1497
See DirReader.read_dir for details.
1499
_utf8_encode = self._utf8_encode
1501
_listdir = os.listdir
1502
_kind_from_mode = file_kind_from_stat_mode
1505
relprefix = prefix + '/'
1186
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1189
def _walkdirs_unicode_to_utf8(top, prefix=""):
1190
"""See _walkdirs_utf8
1192
Because Win32 has a Unicode api, all of the 'path-from-top' entries will be
1194
This is currently the fallback code path when the filesystem encoding is
1195
not UTF-8. It may be better to implement an alternative so that we can
1196
safely handle paths that are not properly decodable in the current
1199
_utf8_encode = codecs.getencoder('utf8')
1201
_directory = _directory_kind
1202
_listdir = os.listdir
1203
_kind_from_mode = _formats.get
1205
pending = [(safe_utf8(prefix), None, None, None, safe_unicode(top))]
1207
relroot, _, _, _, top = pending.pop()
1209
relprefix = relroot + '/'
1508
1212
top_slash = top + u'/'
1511
1215
append = dirblock.append
1512
1216
for name in sorted(_listdir(top)):
1514
name_utf8 = _utf8_encode(name)[0]
1515
except UnicodeDecodeError:
1516
raise errors.BadFilenameEncoding(
1517
_utf8_encode(relprefix)[0] + name, _fs_enc)
1217
name_utf8 = _utf8_encode(name)[0]
1518
1218
abspath = top_slash + name
1519
1219
statvalue = _lstat(abspath)
1520
kind = _kind_from_mode(statvalue.st_mode)
1220
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1521
1221
append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
1222
yield (relroot, top), dirblock
1224
# push the user specified dirs from dirblock
1225
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1525
1228
def copy_tree(from_path, to_path, handlers={}):
1526
1229
"""Copy all of the entries in from_path into to_path.
1528
:param from_path: The base directory to copy.
1231
:param from_path: The base directory to copy.
1529
1232
:param to_path: The target directory. If it does not exist, it will
1531
1234
:param handlers: A dictionary of functions, which takes a source and
1683
1360
while len(b) < bytes:
1684
new = until_no_eintr(socket.recv, bytes - len(b))
1361
new = socket.recv(bytes - len(b))
1691
def send_all(socket, bytes, report_activity=None):
1692
"""Send all bytes on a socket.
1694
Regular socket.sendall() can give socket error 10053 on Windows. This
1695
implementation sends no more than 64k at a time, which avoids this problem.
1697
:param report_activity: Call this as bytes are read, see
1698
Transport._report_activity
1701
for pos in xrange(0, len(bytes), chunk_size):
1702
block = bytes[pos:pos+chunk_size]
1703
if report_activity is not None:
1704
report_activity(len(block), 'write')
1705
until_no_eintr(socket.sendall, block)
1708
1367
def dereference_path(path):
1709
1368
"""Determine the real path to a file.
1717
1376
# The pathjoin for '.' is a workaround for Python bug #1213894.
1718
1377
# (initial path components aren't dereferenced)
1719
1378
return pathjoin(realpath(pathjoin('.', parent)), base)
1722
def supports_mapi():
1723
"""Return True if we can use MAPI to launch a mail client."""
1724
return sys.platform == "win32"
1727
def resource_string(package, resource_name):
1728
"""Load a resource from a package and return it as a string.
1730
Note: Only packages that start with bzrlib are currently supported.
1732
This is designed to be a lightweight implementation of resource
1733
loading in a way which is API compatible with the same API from
1735
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access.
1736
If and when pkg_resources becomes a standard library, this routine
1739
# Check package name is within bzrlib
1740
if package == "bzrlib":
1741
resource_relpath = resource_name
1742
elif package.startswith("bzrlib."):
1743
package = package[len("bzrlib."):].replace('.', os.sep)
1744
resource_relpath = pathjoin(package, resource_name)
1746
raise errors.BzrError('resource package %s not in bzrlib' % package)
1748
# Map the resource to a file and read its contents
1749
base = dirname(bzrlib.__file__)
1750
if getattr(sys, 'frozen', None): # bzr.exe
1751
base = abspath(pathjoin(base, '..', '..'))
1752
filename = pathjoin(base, resource_relpath)
1753
return open(filename, 'rU').read()
1756
def file_kind_from_stat_mode_thunk(mode):
1757
global file_kind_from_stat_mode
1758
if file_kind_from_stat_mode is file_kind_from_stat_mode_thunk:
1760
from bzrlib._readdir_pyx import UTF8DirReader
1761
file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1763
from bzrlib._readdir_py import (
1764
_kind_from_mode as file_kind_from_stat_mode
1766
return file_kind_from_stat_mode(mode)
1767
file_kind_from_stat_mode = file_kind_from_stat_mode_thunk
1770
def file_kind(f, _lstat=os.lstat):
1772
return file_kind_from_stat_mode(_lstat(f).st_mode)
1774
if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
1775
raise errors.NoSuchFile(f)
1779
def until_no_eintr(f, *a, **kw):
1780
"""Run f(*a, **kw), retrying if an EINTR error occurs."""
1781
# Borrowed from Twisted's twisted.python.util.untilConcludes function.
1785
except (IOError, OSError), e:
1786
if e.errno == errno.EINTR:
1790
def re_compile_checked(re_string, flags=0, where=""):
1791
"""Return a compiled re, or raise a sensible error.
1793
This should only be used when compiling user-supplied REs.
1795
:param re_string: Text form of regular expression.
1796
:param flags: eg re.IGNORECASE
1797
:param where: Message explaining to the user the context where
1798
it occurred, eg 'log search filter'.
1800
# from https://bugs.launchpad.net/bzr/+bug/251352
1802
re_obj = re.compile(re_string, flags)
1807
where = ' in ' + where
1808
# despite the name 'error' is a type
1809
raise errors.BzrCommandError('Invalid regular expression%s: %r: %s'
1810
% (where, re_string, e))
1813
if sys.platform == "win32":
1816
return msvcrt.getch()
1821
fd = sys.stdin.fileno()
1822
settings = termios.tcgetattr(fd)
1825
ch = sys.stdin.read(1)
1827
termios.tcsetattr(fd, termios.TCSADRAIN, settings)