55
# sha and md5 modules are deprecated in python2.6 but hashlib is available as
57
if sys.version_info < (2, 5):
58
import md5 as _mod_md5
60
import sha as _mod_sha
57
70
from bzrlib import symbol_versioning
58
from bzrlib.symbol_versioning import (
62
from bzrlib.trace import mutter
65
73
# On win32, O_BINARY is used to indicate the file should
66
74
# be opened in binary mode, rather than text mode.
67
75
# On other platforms, O_BINARY doesn't exist, because
68
76
# they always open in binary mode, so it is okay to
69
# OR with 0 on those platforms
77
# OR with 0 on those platforms.
78
# O_NOINHERIT and O_TEXT exists only on win32 too.
70
79
O_BINARY = getattr(os, 'O_BINARY', 0)
72
# On posix, use lstat instead of stat so that we can
73
# operate on broken symlinks. On Windows revert to stat.
74
lstat = getattr(os, 'lstat', os.stat)
80
O_TEXT = getattr(os, 'O_TEXT', 0)
81
O_NOINHERIT = getattr(os, 'O_NOINHERIT', 0)
84
def get_unicode_argv():
86
user_encoding = get_user_encoding()
87
return [a.decode(user_encoding) for a in sys.argv[1:]]
88
except UnicodeDecodeError:
89
raise errors.BzrError(("Parameter '%r' is unsupported by the current "
76
93
def make_readonly(filename):
77
94
"""Make a filename read-only."""
78
mod = lstat(filename).st_mode
95
mod = os.lstat(filename).st_mode
79
96
if not stat.S_ISLNK(mod):
80
97
mod = mod & 0777555
81
98
os.chmod(filename, mod)
84
101
def make_writable(filename):
85
mod = lstat(filename).st_mode
102
mod = os.lstat(filename).st_mode
86
103
if not stat.S_ISLNK(mod):
88
105
os.chmod(filename, mod)
108
def minimum_path_selection(paths):
109
"""Return the smallset subset of paths which are outside paths.
111
:param paths: A container (and hence not None) of paths.
112
:return: A set of paths sufficient to include everything in paths via
113
is_inside, drawn from the paths parameter.
119
return path.split('/')
120
sorted_paths = sorted(list(paths), key=sort_key)
122
search_paths = [sorted_paths[0]]
123
for path in sorted_paths[1:]:
124
if not is_inside(search_paths[-1], path):
125
# This path is unique, add it
126
search_paths.append(path)
128
return set(search_paths)
540
def pumpfile(fromfile, tofile):
541
"""Copy contents of one file to another."""
544
b = fromfile.read(BUFSIZE)
535
def pumpfile(from_file, to_file, read_length=-1, buff_size=32768,
536
report_activity=None, direction='read'):
537
"""Copy contents of one file to another.
539
The read_length can either be -1 to read to end-of-file (EOF) or
540
it can specify the maximum number of bytes to read.
542
The buff_size represents the maximum size for each read operation
543
performed on from_file.
545
:param report_activity: Call this as bytes are read, see
546
Transport._report_activity
547
:param direction: Will be passed to report_activity
549
:return: The number of bytes copied.
553
# read specified number of bytes
555
while read_length > 0:
556
num_bytes_to_read = min(read_length, buff_size)
558
block = from_file.read(num_bytes_to_read)
562
if report_activity is not None:
563
report_activity(len(block), direction)
566
actual_bytes_read = len(block)
567
read_length -= actual_bytes_read
568
length += actual_bytes_read
572
block = from_file.read(buff_size)
576
if report_activity is not None:
577
report_activity(len(block), direction)
583
def pump_string_file(bytes, file_handle, segment_size=None):
584
"""Write bytes to file_handle in many smaller writes.
586
:param bytes: The string to write.
587
:param file_handle: The file to write to.
589
# Write data in chunks rather than all at once, because very large
590
# writes fail on some platforms (e.g. Windows with SMB mounted
593
segment_size = 5242880 # 5MB
594
segments = range(len(bytes) / segment_size + 1)
595
write = file_handle.write
596
for segment_index in segments:
597
segment = buffer(bytes, segment_index * segment_size, segment_size)
550
601
def file_iterator(input_file, readsize=32768):
620
700
:param timezone: How to display the time: 'utc', 'original' for the
621
701
timezone specified by offset, or 'local' for the process's current
623
:param show_offset: Whether to append the timezone.
624
:param date_fmt: strftime format.
703
:param date_fmt: strftime format.
704
:param show_offset: Whether to append the timezone.
706
(date_fmt, tt, offset_str) = \
707
_format_date(t, offset, timezone, date_fmt, show_offset)
708
date_fmt = date_fmt.replace('%a', weekdays[tt[6]])
709
date_str = time.strftime(date_fmt, tt)
710
return date_str + offset_str
712
def format_local_date(t, offset=0, timezone='original', date_fmt=None,
714
"""Return an unicode date string formatted according to the current locale.
716
:param t: Seconds since the epoch.
717
:param offset: Timezone offset in seconds east of utc.
718
:param timezone: How to display the time: 'utc', 'original' for the
719
timezone specified by offset, or 'local' for the process's current
721
:param date_fmt: strftime format.
722
:param show_offset: Whether to append the timezone.
724
(date_fmt, tt, offset_str) = \
725
_format_date(t, offset, timezone, date_fmt, show_offset)
726
date_str = time.strftime(date_fmt, tt)
727
if not isinstance(date_str, unicode):
728
date_str = date_str.decode(get_user_encoding(), 'replace')
729
return date_str + offset_str
731
def _format_date(t, offset, timezone, date_fmt, show_offset):
626
732
if timezone == 'utc':
627
733
tt = time.gmtime(t)
764
assert isinstance(p, (list, tuple))
766
869
if (f == '..') or (f is None) or (f == ''):
767
870
raise errors.BzrError("sorry, %r not allowed in path" % f)
768
871
return pathjoin(*p)
771
@deprecated_function(zero_nine)
772
def appendpath(p1, p2):
776
return pathjoin(p1, p2)
874
def parent_directories(filename):
875
"""Return the list of parent directories, deepest first.
877
For example, parent_directories("a/b/c") -> ["a/b", "a"].
880
parts = splitpath(dirname(filename))
882
parents.append(joinpath(parts))
888
from bzrlib._chunks_to_lines_pyx import chunks_to_lines
890
from bzrlib._chunks_to_lines_py import chunks_to_lines
779
893
def split_lines(s):
780
894
"""Split s into lines, but without removing the newline characters."""
895
# Trivially convert a fulltext into a 'chunked' representation, and let
896
# chunks_to_lines do the heavy lifting.
897
if isinstance(s, str):
898
# chunks_to_lines only supports 8-bit strings
899
return chunks_to_lines([s])
901
return _split_lines(s)
905
"""Split s into lines, but without removing the newline characters.
907
This supports Unicode or plain string objects.
781
909
lines = s.split('\n')
782
910
result = [line + '\n' for line in lines[:-1]]
802
930
shutil.copyfile(src, dest)
804
def delete_any(full_path):
805
"""Delete a file or directory."""
933
def delete_any(path):
934
"""Delete a file, symlink or directory.
936
Will delete even if readonly.
809
# We may be renaming a dangling inventory id
810
if e.errno not in (errno.EISDIR, errno.EACCES, errno.EPERM):
939
_delete_file_or_dir(path)
940
except (OSError, IOError), e:
941
if e.errno in (errno.EPERM, errno.EACCES):
942
# make writable and try again
945
except (OSError, IOError):
947
_delete_file_or_dir(path)
952
def _delete_file_or_dir(path):
953
# Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
954
# Forgiveness than Permission (EAFP) because:
955
# - root can damage a solaris file system by using unlink,
956
# - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
957
# EACCES, OSX: EPERM) when invoked on a directory.
958
if isdir(path): # Takes care of symlinks
815
964
def has_symlinks():
859
1034
avoids that problem.
862
assert len(base) >= MIN_ABS_PATHLENGTH, ('Length of base must be equal or'
863
' exceed the platform minimum length (which is %d)' %
1037
if len(base) < MIN_ABS_PATHLENGTH:
1038
# must have space for e.g. a drive letter
1039
raise ValueError('%r is too short to calculate a relative path'
866
1042
rp = abspath(path)
870
while len(head) >= len(base):
1047
if len(head) <= len(base) and head != base:
1048
raise errors.PathNotChild(rp, base)
871
1049
if head == base:
873
head, tail = os.path.split(head)
1051
head, tail = split(head)
877
raise errors.PathNotChild(rp, base)
1056
return pathjoin(*reversed(s))
1061
def _cicp_canonical_relpath(base, path):
1062
"""Return the canonical path relative to base.
1064
Like relpath, but on case-insensitive-case-preserving file-systems, this
1065
will return the relpath as stored on the file-system rather than in the
1066
case specified in the input string, for all existing portions of the path.
1068
This will cause O(N) behaviour if called for every path in a tree; if you
1069
have a number of paths to convert, you should use canonical_relpaths().
1071
# TODO: it should be possible to optimize this for Windows by using the
1072
# win32 API FindFiles function to look for the specified name - but using
1073
# os.listdir() still gives us the correct, platform agnostic semantics in
1076
rel = relpath(base, path)
1077
# '.' will have been turned into ''
1081
abs_base = abspath(base)
1083
_listdir = os.listdir
1085
# use an explicit iterator so we can easily consume the rest on early exit.
1086
bit_iter = iter(rel.split('/'))
1087
for bit in bit_iter:
1090
next_entries = _listdir(current)
1091
except OSError: # enoent, eperm, etc
1092
# We can't find this in the filesystem, so just append the
1094
current = pathjoin(current, bit, *list(bit_iter))
1096
for look in next_entries:
1097
if lbit == look.lower():
1098
current = pathjoin(current, look)
1101
# got to the end, nothing matched, so we just return the
1102
# non-existing bits as they were specified (the filename may be
1103
# the target of a move, for example).
1104
current = pathjoin(current, bit, *list(bit_iter))
1106
return current[len(abs_base):].lstrip('/')
1108
# XXX - TODO - we need better detection/integration of case-insensitive
1109
# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
1110
# filesystems), for example, so could probably benefit from the same basic
1111
# support there. For now though, only Windows and OSX get that support, and
1112
# they get it for *all* file-systems!
1113
if sys.platform in ('win32', 'darwin'):
1114
canonical_relpath = _cicp_canonical_relpath
1116
canonical_relpath = relpath
1118
def canonical_relpaths(base, paths):
1119
"""Create an iterable to canonicalize a sequence of relative paths.
1121
The intent is for this implementation to use a cache, vastly speeding
1122
up multiple transformations in the same directory.
1124
# but for now, we haven't optimized...
1125
return [canonical_relpath(base, p) for p in paths]
885
1127
def safe_unicode(unicode_or_utf8_string):
886
1128
"""Coerce unicode_or_utf8_string into unicode.
888
1130
If it is unicode, it is returned.
889
Otherwise it is decoded from utf-8. If a decoding error
890
occurs, it is wrapped as a If the decoding fails, the exception is wrapped
891
as a BzrBadParameter exception.
1131
Otherwise it is decoded from utf-8. If decoding fails, the exception is
1132
wrapped in a BzrBadParameterNotUnicode exception.
893
1134
if isinstance(unicode_or_utf8_string, unicode):
894
1135
return unicode_or_utf8_string
982
1223
On platforms where the system normalizes filenames (Mac OSX),
983
1224
you can access a file by any path which will normalize correctly.
984
On platforms where the system does not normalize filenames
1225
On platforms where the system does not normalize filenames
985
1226
(Windows, Linux), you have to access a file by its exact path.
987
Internally, bzr only supports NFC/NFKC normalization, since that is
1228
Internally, bzr only supports NFC normalization, since that is
988
1229
the standard for XML documents.
990
1231
So return the normalized path, and a flag indicating if the file
991
1232
can be accessed by that path.
994
return unicodedata.normalize('NFKC', unicode(path)), True
1235
return unicodedata.normalize('NFC', unicode(path)), True
997
1238
def _inaccessible_normalized_filename(path):
998
1239
__doc__ = _accessible_normalized_filename.__doc__
1000
normalized = unicodedata.normalize('NFKC', unicode(path))
1241
normalized = unicodedata.normalize('NFC', unicode(path))
1001
1242
return normalized, normalized == path
1080
1321
raise errors.IllegalPath(path)
1324
_WIN32_ERROR_DIRECTORY = 267 # Similar to errno.ENOTDIR
1326
def _is_error_enotdir(e):
1327
"""Check if this exception represents ENOTDIR.
1329
Unfortunately, python is very inconsistent about the exception
1330
here. The cases are:
1331
1) Linux, Mac OSX all versions seem to set errno == ENOTDIR
1332
2) Windows, Python2.4, uses errno == ERROR_DIRECTORY (267)
1333
which is the windows error code.
1334
3) Windows, Python2.5 uses errno == EINVAL and
1335
winerror == ERROR_DIRECTORY
1337
:param e: An Exception object (expected to be OSError with an errno
1338
attribute, but we should be able to cope with anything)
1339
:return: True if this represents an ENOTDIR error. False otherwise.
1341
en = getattr(e, 'errno', None)
1342
if (en == errno.ENOTDIR
1343
or (sys.platform == 'win32'
1344
and (en == _WIN32_ERROR_DIRECTORY
1345
or (en == errno.EINVAL
1346
and getattr(e, 'winerror', None) == _WIN32_ERROR_DIRECTORY)
1083
1352
def walkdirs(top, prefix=""):
1084
1353
"""Yield data about all the directories in a tree.
1086
1355
This yields all the data about the contents of a directory at a time.
1087
1356
After each directory has been yielded, if the caller has mutated the list
1088
1357
to exclude some directories, they are then not descended into.
1090
1359
The data yielded is of the form:
1091
1360
((directory-relpath, directory-path-from-top),
1092
[(directory-relpath, basename, kind, lstat, path-from-top), ...]),
1361
[(relpath, basename, kind, lstat, path-from-top), ...]),
1093
1362
- directory-relpath is the relative path of the directory being returned
1094
1363
with respect to top. prefix is prepended to this.
1095
- directory-path-from-root is the path including top for this directory.
1364
- directory-path-from-root is the path including top for this directory.
1096
1365
It is suitable for use with os functions.
1097
1366
- relpath is the relative path within the subtree being walked.
1098
1367
- basename is the basename of the path
1100
1369
present within the tree - but it may be recorded as versioned. See
1101
1370
versioned_kind.
1102
1371
- lstat is the stat data *if* the file was statted.
1103
- planned, not implemented:
1372
- planned, not implemented:
1104
1373
path_from_tree_root is the path from the root of the tree.
1106
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
1375
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
1107
1376
allows one to walk a subtree but get paths that are relative to a tree
1108
1377
rooted higher up.
1109
1378
:return: an iterator over the dirs.
1111
1380
#TODO there is a bit of a smell where the results of the directory-
1112
# summary in this, and the path from the root, may not agree
1381
# summary in this, and the path from the root, may not agree
1113
1382
# depending on top and prefix - i.e. ./foo and foo as a pair leads to
1114
1383
# potentially confusing output. We should make this more robust - but
1115
1384
# not at a speed cost. RBC 20060731
1116
1385
_lstat = os.lstat
1117
1386
_directory = _directory_kind
1118
1387
_listdir = os.listdir
1119
_kind_from_mode = _formats.get
1388
_kind_from_mode = file_kind_from_stat_mode
1120
1389
pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
1122
1391
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1131
1400
append = dirblock.append
1132
for name in sorted(_listdir(top)):
1133
abspath = top_slash + name
1134
statvalue = _lstat(abspath)
1135
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1136
append((relprefix + name, name, kind, statvalue, abspath))
1402
names = sorted(_listdir(top))
1404
if not _is_error_enotdir(e):
1408
abspath = top_slash + name
1409
statvalue = _lstat(abspath)
1410
kind = _kind_from_mode(statvalue.st_mode)
1411
append((relprefix + name, name, kind, statvalue, abspath))
1137
1412
yield (relroot, top), dirblock
1139
1414
# push the user specified dirs from dirblock
1140
1415
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1418
class DirReader(object):
1419
"""An interface for reading directories."""
1421
def top_prefix_to_starting_dir(self, top, prefix=""):
1422
"""Converts top and prefix to a starting dir entry
1424
:param top: A utf8 path
1425
:param prefix: An optional utf8 path to prefix output relative paths
1427
:return: A tuple starting with prefix, and ending with the native
1430
raise NotImplementedError(self.top_prefix_to_starting_dir)
1432
def read_dir(self, prefix, top):
1433
"""Read a specific dir.
1435
:param prefix: A utf8 prefix to be preprended to the path basenames.
1436
:param top: A natively encoded path to read.
1437
:return: A list of the directories contents. Each item contains:
1438
(utf8_relpath, utf8_name, kind, lstatvalue, native_abspath)
1440
raise NotImplementedError(self.read_dir)
1443
_selected_dir_reader = None
1143
1446
def _walkdirs_utf8(top, prefix=""):
1144
1447
"""Yield data about all the directories in a tree.
1154
1457
path-from-top might be unicode or utf8, but it is the correct path to
1155
1458
pass to os functions to affect the file in question. (such as os.lstat)
1157
fs_encoding = _fs_enc.upper()
1158
if (sys.platform == 'win32' or
1159
fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968')): # ascii
1160
return _walkdirs_unicode_to_utf8(top, prefix=prefix)
1162
return _walkdirs_fs_utf8(top, prefix=prefix)
1165
def _walkdirs_fs_utf8(top, prefix=""):
1166
"""See _walkdirs_utf8.
1168
This sub-function is called when we know the filesystem is already in utf8
1169
encoding. So we don't need to transcode filenames.
1172
_directory = _directory_kind
1173
_listdir = os.listdir
1174
_kind_from_mode = _formats.get
1460
global _selected_dir_reader
1461
if _selected_dir_reader is None:
1462
fs_encoding = _fs_enc.upper()
1463
if sys.platform == "win32" and win32utils.winver == 'Windows NT':
1464
# Win98 doesn't have unicode apis like FindFirstFileW
1465
# TODO: We possibly could support Win98 by falling back to the
1466
# original FindFirstFile, and using TCHAR instead of WCHAR,
1467
# but that gets a bit tricky, and requires custom compiling
1470
from bzrlib._walkdirs_win32 import Win32ReadDir
1471
_selected_dir_reader = Win32ReadDir()
1474
elif fs_encoding in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
1475
# ANSI_X3.4-1968 is a form of ASCII
1477
from bzrlib._readdir_pyx import UTF8DirReader
1478
_selected_dir_reader = UTF8DirReader()
1482
if _selected_dir_reader is None:
1483
# Fallback to the python version
1484
_selected_dir_reader = UnicodeDirReader()
1176
1486
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1177
1487
# But we don't actually uses 1-3 in pending, so set them to None
1178
pending = [(safe_utf8(prefix), None, None, None, safe_utf8(top))]
1488
pending = [[_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]]
1489
read_dir = _selected_dir_reader.read_dir
1490
_directory = _directory_kind
1180
relroot, _, _, _, top = pending.pop()
1182
relprefix = relroot + '/'
1185
top_slash = top + '/'
1188
append = dirblock.append
1189
for name in sorted(_listdir(top)):
1190
abspath = top_slash + name
1191
statvalue = _lstat(abspath)
1192
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1193
append((relprefix + name, name, kind, statvalue, abspath))
1492
relroot, _, _, _, top = pending[-1].pop()
1495
dirblock = sorted(read_dir(relroot, top))
1194
1496
yield (relroot, top), dirblock
1196
1497
# push the user specified dirs from dirblock
1197
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1200
def _walkdirs_unicode_to_utf8(top, prefix=""):
1201
"""See _walkdirs_utf8
1203
Because Win32 has a Unicode api, all of the 'path-from-top' entries will be
1205
This is currently the fallback code path when the filesystem encoding is
1206
not UTF-8. It may be better to implement an alternative so that we can
1207
safely handle paths that are not properly decodable in the current
1210
_utf8_encode = codecs.getencoder('utf8')
1212
_directory = _directory_kind
1213
_listdir = os.listdir
1214
_kind_from_mode = _formats.get
1216
pending = [(safe_utf8(prefix), None, None, None, safe_unicode(top))]
1218
relroot, _, _, _, top = pending.pop()
1220
relprefix = relroot + '/'
1498
next = [d for d in reversed(dirblock) if d[2] == _directory]
1500
pending.append(next)
1503
class UnicodeDirReader(DirReader):
1504
"""A dir reader for non-utf8 file systems, which transcodes."""
1506
__slots__ = ['_utf8_encode']
1509
self._utf8_encode = codecs.getencoder('utf8')
1511
def top_prefix_to_starting_dir(self, top, prefix=""):
1512
"""See DirReader.top_prefix_to_starting_dir."""
1513
return (safe_utf8(prefix), None, None, None, safe_unicode(top))
1515
def read_dir(self, prefix, top):
1516
"""Read a single directory from a non-utf8 file system.
1518
top, and the abspath element in the output are unicode, all other paths
1519
are utf8. Local disk IO is done via unicode calls to listdir etc.
1521
This is currently the fallback code path when the filesystem encoding is
1522
not UTF-8. It may be better to implement an alternative so that we can
1523
safely handle paths that are not properly decodable in the current
1526
See DirReader.read_dir for details.
1528
_utf8_encode = self._utf8_encode
1530
_listdir = os.listdir
1531
_kind_from_mode = file_kind_from_stat_mode
1534
relprefix = prefix + '/'
1223
1537
top_slash = top + u'/'
1226
1540
append = dirblock.append
1227
1541
for name in sorted(_listdir(top)):
1228
name_utf8 = _utf8_encode(name)[0]
1543
name_utf8 = _utf8_encode(name)[0]
1544
except UnicodeDecodeError:
1545
raise errors.BadFilenameEncoding(
1546
_utf8_encode(relprefix)[0] + name, _fs_enc)
1229
1547
abspath = top_slash + name
1230
1548
statvalue = _lstat(abspath)
1231
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1549
kind = _kind_from_mode(statvalue.st_mode)
1232
1550
append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
1233
yield (relroot, top), dirblock
1235
# push the user specified dirs from dirblock
1236
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1239
1554
def copy_tree(from_path, to_path, handlers={}):
1240
1555
"""Copy all of the entries in from_path into to_path.
1242
:param from_path: The base directory to copy.
1557
:param from_path: The base directory to copy.
1243
1558
:param to_path: The target directory. If it does not exist, it will
1245
1560
:param handlers: A dictionary of functions, which takes a source and
1387
1746
# The pathjoin for '.' is a workaround for Python bug #1213894.
1388
1747
# (initial path components aren't dereferenced)
1389
1748
return pathjoin(realpath(pathjoin('.', parent)), base)
1751
def supports_mapi():
1752
"""Return True if we can use MAPI to launch a mail client."""
1753
return sys.platform == "win32"
1756
def resource_string(package, resource_name):
1757
"""Load a resource from a package and return it as a string.
1759
Note: Only packages that start with bzrlib are currently supported.
1761
This is designed to be a lightweight implementation of resource
1762
loading in a way which is API compatible with the same API from
1764
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access.
1765
If and when pkg_resources becomes a standard library, this routine
1768
# Check package name is within bzrlib
1769
if package == "bzrlib":
1770
resource_relpath = resource_name
1771
elif package.startswith("bzrlib."):
1772
package = package[len("bzrlib."):].replace('.', os.sep)
1773
resource_relpath = pathjoin(package, resource_name)
1775
raise errors.BzrError('resource package %s not in bzrlib' % package)
1777
# Map the resource to a file and read its contents
1778
base = dirname(bzrlib.__file__)
1779
if getattr(sys, 'frozen', None): # bzr.exe
1780
base = abspath(pathjoin(base, '..', '..'))
1781
filename = pathjoin(base, resource_relpath)
1782
return open(filename, 'rU').read()
1785
def file_kind_from_stat_mode_thunk(mode):
1786
global file_kind_from_stat_mode
1787
if file_kind_from_stat_mode is file_kind_from_stat_mode_thunk:
1789
from bzrlib._readdir_pyx import UTF8DirReader
1790
file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1792
from bzrlib._readdir_py import (
1793
_kind_from_mode as file_kind_from_stat_mode
1795
return file_kind_from_stat_mode(mode)
1796
file_kind_from_stat_mode = file_kind_from_stat_mode_thunk
1799
def file_kind(f, _lstat=os.lstat):
1801
return file_kind_from_stat_mode(_lstat(f).st_mode)
1803
if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
1804
raise errors.NoSuchFile(f)
1808
def until_no_eintr(f, *a, **kw):
1809
"""Run f(*a, **kw), retrying if an EINTR error occurs."""
1810
# Borrowed from Twisted's twisted.python.util.untilConcludes function.
1814
except (IOError, OSError), e:
1815
if e.errno == errno.EINTR:
1819
def re_compile_checked(re_string, flags=0, where=""):
1820
"""Return a compiled re, or raise a sensible error.
1822
This should only be used when compiling user-supplied REs.
1824
:param re_string: Text form of regular expression.
1825
:param flags: eg re.IGNORECASE
1826
:param where: Message explaining to the user the context where
1827
it occurred, eg 'log search filter'.
1829
# from https://bugs.launchpad.net/bzr/+bug/251352
1831
re_obj = re.compile(re_string, flags)
1836
where = ' in ' + where
1837
# despite the name 'error' is a type
1838
raise errors.BzrCommandError('Invalid regular expression%s: %r: %s'
1839
% (where, re_string, e))
1842
if sys.platform == "win32":
1845
return msvcrt.getch()
1850
fd = sys.stdin.fileno()
1851
settings = termios.tcgetattr(fd)
1854
ch = sys.stdin.read(1)
1856
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
1860
if sys.platform == 'linux2':
1861
def _local_concurrency():
1863
prefix = 'processor'
1864
for line in file('/proc/cpuinfo', 'rb'):
1865
if line.startswith(prefix):
1866
concurrency = int(line[line.find(':')+1:]) + 1
1868
elif sys.platform == 'darwin':
1869
def _local_concurrency():
1870
return subprocess.Popen(['sysctl', '-n', 'hw.availcpu'],
1871
stdout=subprocess.PIPE).communicate()[0]
1872
elif sys.platform[0:7] == 'freebsd':
1873
def _local_concurrency():
1874
return subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
1875
stdout=subprocess.PIPE).communicate()[0]
1876
elif sys.platform == 'sunos5':
1877
def _local_concurrency():
1878
return subprocess.Popen(['psrinfo', '-p',],
1879
stdout=subprocess.PIPE).communicate()[0]
1880
elif sys.platform == "win32":
1881
def _local_concurrency():
1882
# This appears to return the number of cores.
1883
return os.environ.get('NUMBER_OF_PROCESSORS')
1885
def _local_concurrency():
1890
_cached_local_concurrency = None
1892
def local_concurrency(use_cache=True):
1893
"""Return how many processes can be run concurrently.
1895
Rely on platform specific implementations and default to 1 (one) if
1896
anything goes wrong.
1898
global _cached_local_concurrency
1899
if _cached_local_concurrency is not None and use_cache:
1900
return _cached_local_concurrency
1903
concurrency = _local_concurrency()
1904
except (OSError, IOError):
1907
concurrency = int(concurrency)
1908
except (TypeError, ValueError):
1911
_cached_concurrency = concurrency
1914
if sys.platform == 'win32':
1915
def open_file(filename, mode='r', bufsize=-1):
1916
"""This function is used to override the ``open`` builtin.
1918
But it uses O_NOINHERIT flag so the file handle is not inherited by
1919
child processes. Deleting or renaming a closed file opened with this
1920
function is not blocking child processes.
1922
writing = 'w' in mode
1923
appending = 'a' in mode
1924
updating = '+' in mode
1925
binary = 'b' in mode
1928
# see http://msdn.microsoft.com/en-us/library/yeby3zcb%28VS.71%29.aspx
1929
# for flags for each modes.
1939
flags |= os.O_WRONLY
1940
flags |= os.O_CREAT | os.O_TRUNC
1945
flags |= os.O_WRONLY
1946
flags |= os.O_CREAT | os.O_APPEND
1951
flags |= os.O_RDONLY
1953
return os.fdopen(os.open(filename, flags), mode, bufsize)