520
520
"""Replacer for shutil.rmtree: could remove readonly dirs/files"""
521
521
return shutil.rmtree(path, ignore_errors, onerror)
523
get_unicode_argv = getattr(win32utils, 'get_unicode_argv', get_unicode_argv)
523
f = win32utils.get_unicode_argv # special function or None
524
526
path_from_environ = win32utils.get_environ_unicode
525
527
_get_home_dir = win32utils.get_home_location
526
528
getuser_unicode = win32utils.get_user_name
1025
1027
def splitpath(p):
1026
1028
"""Turn string into list of parts."""
1027
use_bytes = isinstance(p, bytes)
1028
1029
if os.path.sep == '\\':
1029
1030
# split on either delimiter because people might use either on
1032
if isinstance(p, bytes):
1032
1033
ps = re.split(b'[\\\\/]', p)
1034
1035
ps = re.split(r'[\\/]', p)
1037
if isinstance(p, bytes):
1037
1038
ps = p.split(b'/')
1039
1040
ps = p.split('/')
1043
current_empty_dir = (b'.', b'')
1046
current_empty_dir = ('.', '')
1044
if f in ('..', b'..'):
1051
1045
raise errors.BzrError(gettext("sorry, %r not allowed in path") % f)
1052
elif f in current_empty_dir:
1046
elif f in ('.', '', b'.', b''):
1668
1662
_terminal_size = _ioctl_terminal_size
1671
def supports_executable(path):
1672
"""Return if filesystem at path supports executable bit.
1674
:param path: Path for which to check the file system
1675
:return: boolean indicating whether executable bit can be stored/relied upon
1677
if sys.platform == 'win32':
1680
fs_type = get_fs_type(path)
1681
except errors.DependencyNotPresent as e:
1682
trace.mutter('Unable to get fs type for %r: %s', path, e)
1684
if fs_type in ('vfat', 'ntfs'):
1685
# filesystems known to not support executable bit
1690
def supports_symlinks(path):
1691
"""Return if the filesystem at path supports the creation of symbolic links.
1694
if not has_symlinks():
1697
fs_type = get_fs_type(path)
1698
except errors.DependencyNotPresent as e:
1699
trace.mutter('Unable to get fs type for %r: %s', path, e)
1701
if fs_type in ('vfat', 'ntfs'):
1702
# filesystems known to not support symlinks
1665
def supports_executable():
1666
return sys.platform != "win32"
1707
1669
def supports_posix_readonly():
2643
def read_mtab(path):
2644
"""Read an fstab-style file and extract mountpoint+filesystem information.
2646
:param path: Path to read from
2647
:yield: Tuples with mountpoints (as bytestrings) and filesystem names
2649
with open(path, 'rb') as f:
2651
if line.startswith(b'#'):
2656
yield cols[1], cols[2].decode('ascii', 'replace')
2659
MTAB_PATH = '/etc/mtab'
2661
class FilesystemFinder(object):
2662
"""Find the filesystem for a particular path."""
2664
def __init__(self, mountpoints):
2667
self._mountpoints = sorted(mountpoints, key=key, reverse=True)
2671
"""Create a FilesystemFinder from an mtab-style file.
2673
Note that this will silenty ignore mtab if it doesn't exist or can not
2676
# TODO(jelmer): Use inotify to be notified when /etc/mtab changes and
2677
# we need to re-read it.
2679
return cls(read_mtab(MTAB_PATH))
2680
except EnvironmentError as e:
2681
trace.mutter('Unable to read mtab: %s', e)
2684
def find(self, path):
2685
"""Find the filesystem used by a particular path.
2687
:param path: Path to find (bytestring or text type)
2688
:return: Filesystem name (as text type) or None, if the filesystem is
2691
for mountpoint, filesystem in self._mountpoints:
2692
if is_inside(mountpoint, path):
2697
_FILESYSTEM_FINDER = None
2700
def get_fs_type(path):
2701
"""Return the filesystem type for the partition a path is in.
2703
:param path: Path to search filesystem type for
2704
:return: A FS type, as string. E.g. "ext2"
2706
global _FILESYSTEM_FINDER
2707
if _FILESYSTEM_FINDER is None:
2708
_FILESYSTEM_FINDER = FilesystemFinder.from_mtab()
2710
if not isinstance(path, bytes):
2711
path = path.encode(_fs_enc)
2713
return _FILESYSTEM_FINDER.find(path)
2717
2606
perf_counter = time.perf_counter