def _collect_folding_actions(self): """ find candidates for folding i.e. when a directory contains symlinks to files that all share the same parent directory """ for parent in self.actions.get_unlink_target_parents(): items = utils.get_directory_contents(parent) other_links_parents = [] other_links = [] source_parent = None is_normal_files_detected = False for item in items: if item not in self.actions.get_unlink_targets(): does_item_exist = False try: does_item_exist = item.exists() except PermissionError: self.errors.add( error.PermissionDenied(self.subcmd, item)) return if does_item_exist and item.is_symlink(): source_parent = item.resolve().parent other_links_parents.append(item.resolve().parent) other_links.append(item) else: is_normal_files_detected = True break if not is_normal_files_detected: other_links_parent_count = len(Counter(other_links_parents)) if other_links_parent_count == 1: assert source_parent is not None if utils.is_same_files( utils.get_directory_contents(source_parent), other_links): self._fold(source_parent, parent) elif (other_links_parent_count == 0 and not utils.is_same_file(parent, self.dest_input)): self.actions.add( actions.RemoveDirectory(self.subcmd, parent))
def _collect_clean_actions(self, source, source_names, dest): subdests = utils.get_directory_contents(dest) for subdest in subdests: if subdest.is_symlink(): link_target = utils.readlink(subdest, absolute_target=True) if (not link_target.exists() and not source_names.isdisjoint(set(link_target.parents))): self.actions.add(actions.UnLink(self.subcmd, subdest)) elif subdest.is_dir(): self._collect_clean_actions(source, source_names, subdest)
def get_directory_contents(self, directory): """ Get the contents of a directory while handling errors that may occur """ contents = [] try: contents = utils.get_directory_contents(directory) except PermissionError: self.errors.add(error.PermissionDenied(self.subcmd, directory)) except FileNotFoundError: self.errors.add( error.NoSuchFileOrDirectory(self.subcmd, directory)) except NotADirectoryError: self.errors.add(error.NoSuchDirectory(self.subcmd, directory)) return contents