73
73
def make_readonly(filename):
74
74
"""Make a filename read-only."""
75
mod = os.stat(filename).st_mode
77
os.chmod(filename, mod)
75
mod = os.lstat(filename).st_mode
76
if not stat.S_ISLNK(mod):
78
os.chmod(filename, mod)
80
81
def make_writable(filename):
81
mod = os.stat(filename).st_mode
83
os.chmod(filename, mod)
82
mod = os.lstat(filename).st_mode
83
if not stat.S_ISLNK(mod):
85
os.chmod(filename, mod)
88
def minimum_path_selection(paths):
89
"""Return the smallset subset of paths which are outside paths.
91
:param paths: A container (and hence not None) of paths.
92
:return: A set of paths sufficient to include everything in paths via
93
is_inside_any, drawn from the paths parameter.
98
other_paths = paths.difference([path])
99
if not is_inside_any(other_paths, path):
100
# this is a top level path, we must check it.
101
search_paths.add(path)
218
# This may throw an exception, in which case success will
220
rename_func(old, new)
238
# This may throw an exception, in which case success will
240
rename_func(old, new)
242
except (IOError, OSError), e:
243
# source and target may be aliases of each other (e.g. on a
244
# case-insensitive filesystem), so we may have accidentally renamed
245
# source by when we tried to rename target
246
if not (file_existed and e.errno in (None, errno.ENOENT)):
224
250
# If the file used to exist, rename it back into place
535
562
def pumpfile(fromfile, tofile):
536
"""Copy contents of one file to another."""
563
"""Copy contents of one file to another.
565
:return: The number of bytes copied.
539
570
b = fromfile.read(BUFSIZE)
545
578
def file_iterator(input_file, readsize=32768):
563
596
return s.hexdigest()
567
def sha_strings(strings):
599
def sha_file_by_name(fname):
600
"""Calculate the SHA1 of a file by reading the full text"""
602
f = os.open(fname, os.O_RDONLY | O_BINARY)
605
b = os.read(f, 1<<16)
613
def sha_strings(strings, _factory=sha.new):
568
614
"""Return the sha-1 of concatenation of strings"""
570
616
map(s.update, strings)
571
617
return s.hexdigest()
620
def sha_string(f, _factory=sha.new):
621
return _factory(f).hexdigest()
580
624
def fingerprint_file(f):
585
return {'size': size,
586
'sha1': s.hexdigest()}
626
return {'size': len(b),
627
'sha1': sha.new(b).hexdigest()}
589
630
def compare_files(a, b):
629
670
tt = time.localtime(t)
630
671
offset = local_time_offset(t)
632
raise errors.BzrError("unsupported timezone format %r" % timezone,
633
['options are "utc", "original", "local"'])
673
raise errors.UnsupportedTimezoneFormat(timezone)
634
674
if date_fmt is None:
635
675
date_fmt = "%a %Y-%m-%d %H:%M:%S"
797
829
shutil.copyfile(src, dest)
799
def delete_any(full_path):
832
# Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
833
# Forgiveness than Permission (EAFP) because:
834
# - root can damage a solaris file system by using unlink,
835
# - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
836
# EACCES, OSX: EPERM) when invoked on a directory.
837
def delete_any(path):
800
838
"""Delete a file or directory."""
804
# We may be renaming a dangling inventory id
805
if e.errno not in (errno.EISDIR, errno.EACCES, errno.EPERM):
839
if isdir(path): # Takes care of symlinks
810
845
def has_symlinks():
1085
1120
The data yielded is of the form:
1086
1121
((directory-relpath, directory-path-from-top),
1087
[(directory-relpath, basename, kind, lstat, path-from-top), ...]),
1122
[(relpath, basename, kind, lstat, path-from-top), ...]),
1088
1123
- directory-relpath is the relative path of the directory being returned
1089
1124
with respect to top. prefix is prepended to this.
1090
1125
- directory-path-from-root is the path including top for this directory.
1149
1184
path-from-top might be unicode or utf8, but it is the correct path to
1150
1185
pass to os functions to affect the file in question. (such as os.lstat)
1152
fs_encoding = sys.getfilesystemencoding().upper()
1187
fs_encoding = _fs_enc.upper()
1153
1188
if (sys.platform == 'win32' or
1154
1189
fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968')): # ascii
1155
1190
return _walkdirs_unicode_to_utf8(top, prefix=prefix)
1409
def send_all(socket, bytes):
1410
"""Send all bytes on a socket.
1412
Regular socket.sendall() can give socket error 10053 on Windows. This
1413
implementation sends no more than 64k at a time, which avoids this problem.
1416
for pos in xrange(0, len(bytes), chunk_size):
1417
socket.sendall(bytes[pos:pos+chunk_size])
1373
1420
def dereference_path(path):
1374
1421
"""Determine the real path to a file.
1382
1429
# The pathjoin for '.' is a workaround for Python bug #1213894.
1383
1430
# (initial path components aren't dereferenced)
1384
1431
return pathjoin(realpath(pathjoin('.', parent)), base)
1434
def supports_mapi():
1435
"""Return True if we can use MAPI to launch a mail client."""
1436
return sys.platform == "win32"
1439
def resource_string(package, resource_name):
1440
"""Load a resource from a package and return it as a string.
1442
Note: Only packages that start with bzrlib are currently supported.
1444
This is designed to be a lightweight implementation of resource
1445
loading in a way which is API compatible with the same API from
1447
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access.
1448
If and when pkg_resources becomes a standard library, this routine
1451
# Check package name is within bzrlib
1452
if package == "bzrlib":
1453
resource_relpath = resource_name
1454
elif package.startswith("bzrlib."):
1455
package = package[len("bzrlib."):].replace('.', os.sep)
1456
resource_relpath = pathjoin(package, resource_name)
1458
raise errors.BzrError('resource package %s not in bzrlib' % package)
1460
# Map the resource to a file and read its contents
1461
base = dirname(bzrlib.__file__)
1462
if getattr(sys, 'frozen', None): # bzr.exe
1463
base = abspath(pathjoin(base, '..', '..'))
1464
filename = pathjoin(base, resource_relpath)
1465
return open(filename, 'rU').read()