From 3c15dd03737c5e5d3e8d0a08b6e3063e35d21471 Mon Sep 17 00:00:00 2001 From: Maks Snegov Date: Wed, 16 Jan 2019 23:02:35 +0300 Subject: [PATCH] add symlink support to recursive hardlink --- main.py | 57 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/main.py b/main.py index db3dd7d..6514fb3 100755 --- a/main.py +++ b/main.py @@ -9,35 +9,47 @@ logging.basicConfig(level=logging.DEBUG) def hardlink_dir(src_dir, dst_dir): + """ + Make hardlink for a directory with all its content. + :param src_dir: path to source directory + :param dst_dir: path to target directory + :return: None + """ logging.info(f'Recursive hardlinking: {src_dir} -> {dst_dir}') src_abs = os.path.abspath(src_dir) dst_abs = os.path.abspath(dst_dir) - if os.path.isdir(dst_abs): - logging.error(f"Destination directory already exists: {dst_dir}") - raise RuntimeError(f'dst dir already exists: {dst_dir}') + def recursive_hardlink(src, dst): + logging.debug(f'Creating directory: {src} -> {dst}') + os.mkdir(dst) + + with os.scandir(src) as it: + for ent in it: + ent_dst_path = os.path.join(dst, ent.name) + if ent.is_symlink(): + symlink_target = os.readlink(ent.path) + logging.debug(f"Symlink to {symlink_target}: {ent.path} -> {ent_dst_path}") + os.symlink(symlink_target, ent_dst_path) + continue + if ent.is_dir(follow_symlinks=False): + recursive_hardlink(ent.path, ent_dst_path) + continue + if ent.is_file(follow_symlinks=False): + logging.debug(f"Hardlink file: {ent.path} -> {ent_dst_path}") + os.link(ent.path, ent_dst_path) + continue + + if not os.path.isdir(src_abs): + logging.error(f"Error reading source directory: {src_dir}") + raise RuntimeError(f"Error reading source directory: {src_dir}") + + if os.path.exists(dst_abs): + logging.error(f"Destination already exists: {dst_dir}") + raise RuntimeError(f'Destination already exists: {dst_dir}') recursive_hardlink(src_abs, dst_abs) return -def recursive_hardlink(src, dst): - logging.debug(f'Hardlink: {src} -> {dst}') - logging.debug(f'Creating top directory: {dst}') - os.mkdir(dst) - - with os.scandir(src) as it: - for ent in it: - if ent.is_symlink(): - logging.error(f'{ent.path}: symlink, skipping') - continue - if ent.is_dir(follow_symlinks=False): - recursive_hardlink(ent.path, os.path.join(dst, ent.name)) - continue - if ent.is_file(follow_symlinks=False): - os.link(ent.path, os.path.join(dst, ent.name), follow_symlinks=False) - - - def main(): if len(sys.argv) != 3: @@ -46,5 +58,6 @@ def main(): hardlink_dir(sys.argv[1], sys.argv[2]) + if __name__ == '__main__': - sys.exit(main()) \ No newline at end of file + sys.exit(main())