aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-07-31 23:33:21 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-07-31 23:41:28 +0300
commitf3da1e8b8d13a3a52b3eab6f28ed798fa83b4215 (patch)
tree902d639adef758a6cff55283174f0e7754a75a9c
parente1e639fc5c85ba4df83040ddb4ac8dc620ae208b (diff)
downloadydb-f3da1e8b8d13a3a52b3eab6f28ed798fa83b4215.tar.gz
Intermediate changes
-rw-r--r--library/python/fs/__init__.py67
1 files changed, 37 insertions, 30 deletions
diff --git a/library/python/fs/__init__.py b/library/python/fs/__init__.py
index 6b6a011e7f..0beaf6665a 100644
--- a/library/python/fs/__init__.py
+++ b/library/python/fs/__init__.py
@@ -196,32 +196,6 @@ def hardlink(src, lnk):
os.link(src, lnk)
-@errorfix_win
-def hardlink_or_copy(src, lnk):
- def should_fallback_to_copy(exc):
- if WindowsError is not None and isinstance(exc, WindowsError) and exc.winerror == 1142: # too many hardlinks
- return True
- # cross-device hardlink or too many hardlinks, or some known WSL error
- if isinstance(exc, OSError) and exc.errno in (
- errno.EXDEV,
- errno.EMLINK,
- errno.EINVAL,
- errno.EACCES,
- errno.EPERM,
- ):
- return True
- return False
-
- try:
- hardlink(src, lnk)
- except Exception as e:
- logger.debug('Failed to hardlink %s to %s with error %s, will copy it', src, lnk, repr(e))
- if should_fallback_to_copy(e):
- copy2(src, lnk, follow_symlinks=False)
- else:
- raise
-
-
# Atomic file/directory symlink (Unix only)
# Dst must not exist
# Throws OSError
@@ -247,24 +221,57 @@ def copy2(src, lnk, follow_symlinks=True):
symlink(os.readlink(src), lnk)
+def copy2_safe(src, lnk, follow_symlinks=True):
+ try:
+ copy2(src, lnk, follow_symlinks)
+ except shutil.SameFileError:
+ pass
+
+
+@errorfix_win
+def hardlink_or_copy(src, lnk, copy_function=copy2):
+ def should_fallback_to_copy(exc):
+ if WindowsError is not None and isinstance(exc, WindowsError) and exc.winerror == 1142: # too many hardlinks
+ return True
+ # cross-device hardlink or too many hardlinks, or some known WSL error
+ if isinstance(exc, OSError) and exc.errno in (
+ errno.EXDEV,
+ errno.EMLINK,
+ errno.EINVAL,
+ errno.EACCES,
+ errno.EPERM,
+ ):
+ return True
+ return False
+
+ try:
+ hardlink(src, lnk)
+ except Exception as e:
+ logger.debug('Failed to hardlink %s to %s with error %s, will copy it', src, lnk, repr(e))
+ if should_fallback_to_copy(e):
+ copy_function(src, lnk, follow_symlinks=False)
+ else:
+ raise
+
+
# Recursively hardlink directory
# Uses plain hardlink for files
# Dst must not exist
# Non-atomic
# Throws OSError
@errorfix_win
-def hardlink_tree(src, dst):
+def hardlink_tree(src, dst, hardlink_function=hardlink, mkdir_function=os.mkdir):
if not os.path.exists(src):
raise CustomFsError(errno.ENOENT, filename=src)
if os.path.isfile(src):
- hardlink(src, dst)
+ hardlink_function(src, dst)
return
for dirpath, _, filenames in walk_relative(src):
src_dirpath = os.path.join(src, dirpath) if dirpath != '.' else src
dst_dirpath = os.path.join(dst, dirpath) if dirpath != '.' else dst
- os.mkdir(dst_dirpath)
+ mkdir_function(dst_dirpath)
for filename in filenames:
- hardlink(os.path.join(src_dirpath, filename), os.path.join(dst_dirpath, filename))
+ hardlink_function(os.path.join(src_dirpath, filename), os.path.join(dst_dirpath, filename))
# File copy