From 16310ed2c7b60147f790433da5e4d17f5724a7b8 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Fri, 7 May 2021 23:48:04 -0500 Subject: [PATCH] Add reflink support for unlinkable files and a set of all property files processed that can be safely skipped --- requirements.txt | 1 + tibi_hardlinks/__init__.py | 25 +++++++++++++++---------- tibi_hardlinks/backups.py | 21 +++++++++++++++++---- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/requirements.txt b/requirements.txt index 81dd2f5..a01f88b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ pytz python-dateutil PyYAML appdirs +reflink diff --git a/tibi_hardlinks/__init__.py b/tibi_hardlinks/__init__.py index 457529b..f2f5ed4 100644 --- a/tibi_hardlinks/__init__.py +++ b/tibi_hardlinks/__init__.py @@ -16,19 +16,24 @@ def find_all_property_files(): def hardlink_all_files(files, dry=False): for prop_file in files: - backup = Backup(prop_file) - dest_dir = create_backup_directory_name( - backup.backup_info, CONFIG_DATA["customization"]["time_format"] - ) - dest_dir = Path(CONFIG_DATA["output"]["output_root"]) / dest_dir - if dry: - print(f"mkdir: {dest_dir}") - else: - dest_dir.mkdir(parents=True, exist_ok=True) - backup.hardlink_to(dest_dir, dry) + try: already_processed = cache_manager.tibi_cache["already_processed"] + except KeyError: + already_processed = set() cache_manager.tibi_cache["already_processed"] = already_processed cache_manager.tibi_cache.sync() + if prop_file not in already_processed: + backup = Backup(prop_file) + dest_dir = create_backup_directory_name( + backup.backup_info, CONFIG_DATA["customization"]["time_format"] + ) + dest_dir = Path(CONFIG_DATA["output"]["output_root"]) / dest_dir + if not dest_dir.exists(): + if dry: + print(f"mkdir: {dest_dir}") + else: + dest_dir.mkdir(parents=True) + backup.hardlink_to(dest_dir, dry) def main(): diff --git a/tibi_hardlinks/backups.py b/tibi_hardlinks/backups.py index 5bb20fc..c17b2ff 100644 --- a/tibi_hardlinks/backups.py +++ b/tibi_hardlinks/backups.py @@ -1,5 +1,8 @@ from pathlib import Path import datetime +import re + +from reflink import reflink from tibi_hardlinks.backup_parser import read_backup_properties from tibi_hardlinks.exceptions import ConfigurationException @@ -99,8 +102,18 @@ class Backup: for filepath in self.related_files.values(): if filepath: filename = filepath.name - if dry: - print(f'link: "{filepath}" => "{dest_dir / filename}"') - else: - filepath.link_to(dest_dir / filename) + dest_path = dest_dir / filename + can_skip = True + if not dest_path.exists(): + can_skip = False + if dry: + print(f'link: "{filepath}" => "{dest_path}"') + else: + try: + filepath.link_to(dest_path) + except OSError: + reflink(str(filepath), str(dest_path)) + except Exception: + raise + if can_skip and not dry: cache_manager.tibi_cache["already_processed"].add(self.property_file)