diff --git a/Backupper.py b/Backupper.py index 767f7c8..511b826 100644 --- a/Backupper.py +++ b/Backupper.py @@ -572,6 +572,7 @@ def _generate_tree( directories_to_parse_queue, parsed_queue, skipped_entries_abs, + self._config_manager.get_config("follow_symlinks"), self._stats_tree_parsed_dirs, self._stats_tree_parsed_files, control_value, diff --git a/ConfigManager.py b/ConfigManager.py index bcd2473..bbb252f 100644 --- a/ConfigManager.py +++ b/ConfigManager.py @@ -26,6 +26,7 @@ "version": __version__, "input_paths": [], "save_to": "", + "follow_symlinks": False, "delete_data": True, "delete_skipped": False, "create_empty_dirs": True, diff --git a/GUIHandler.py b/GUIHandler.py index 9984492..4c58075 100644 --- a/GUIHandler.py +++ b/GUIHandler.py @@ -149,6 +149,7 @@ def __init__( self.cb_delete_data.setChecked(self._config_manager.get_config("delete_data")) self.cb_delete_skipped.setChecked(self._config_manager.get_config("delete_skipped")) self.cb_delete_skipped.setEnabled(self._config_manager.get_config("delete_data")) + self.cb_follow_symlinks.setChecked(self._config_manager.get_config("follow_symlinks")) self.cb_create_empty_dirs.setChecked(self._config_manager.get_config("create_empty_dirs")) self.cb_generate_tree.setChecked(self._config_manager.get_config("generate_tree")) self.cob_checksum_alg.setCurrentText(self._config_manager.get_config("checksum_alg")) @@ -162,6 +163,9 @@ def __init__( # Connect updaters self.le_save_to.textChanged.connect(lambda: self._config_manager.set_config("save_to", self.le_save_to.text())) + self.cb_follow_symlinks.clicked.connect( + lambda: self._config_manager.set_config("follow_symlinks", self.cb_follow_symlinks.isChecked()) + ) self.cb_delete_data.clicked.connect( lambda: self._config_manager.set_config("delete_data", self.cb_delete_data.isChecked()) ) diff --git a/gui.ui b/gui.ui index 1bc7d14..675439a 100644 --- a/gui.ui +++ b/gui.ui @@ -7,8 +7,8 @@ 0 0 - 502 - 608 + 474 + 757 @@ -28,17 +28,20 @@ + + 9 + - 12 + 9 - 12 + 9 - 12 + 9 - 6 + 9 @@ -74,8 +77,8 @@ 0 0 - 474 - 137 + 448 + 112 @@ -140,6 +143,33 @@ + + + + + + Follow symbolic links when parsing files + + + Follow symlinks + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/tree_parser.py b/tree_parser.py index 9f48ba1..bd6fe5e 100644 --- a/tree_parser.py +++ b/tree_parser.py @@ -40,6 +40,7 @@ def tree_parser( directories_to_parse_queue: multiprocessing.Queue, parsed_queue: multiprocessing.Queue, skipped_entries_abs: List[str], + follow_symlinks: bool, stats_tree_parsed_dirs: multiprocessing.Value, stats_tree_parsed_files: multiprocessing.Value, control_value: multiprocessing.Value or None = None, @@ -55,6 +56,7 @@ def tree_parser( parsed_queue (multiprocessing.Queue): parsing results as tuples (relative path, root dir path, PATH_..., is empty directory) skipped_entries_abs (List[str]): list of normalized absolute paths to skip, + follow_symlinks (bool): True to follow symlinks, false to ignore them stats_tree_parsed_dirs (multiprocessing.Value): counter of total successfully parsed directories stats_tree_parsed_files (multiprocessing.Value): counter of total successfully parsed files control_value (multiprocessing.Value or None, optional): value (int) to pause / cancel process @@ -135,7 +137,7 @@ def tree_parser( while True: # Try to get next path try: - dir_or_file = next(parent_dir_abs_generator) + dir_or_file = next(parent_dir_abs_generator).is_symlink # No more paths -> exit except StopIteration: @@ -149,6 +151,10 @@ def tree_parser( # Parse it try: + # Ignore symlinks + if dir_or_file.is_symlink() and not follow_symlinks: + continue + # Ignore if found in skipped paths if os.path.normpath(str(dir_or_file)) in skipped_entries_abs: continue