def test_unstow_folding_with_multiple_sources_with_execute_permission_unset( source_a, source_b, dest): dploy.stow([source_a, source_b], dest) utils.remove_execute_permission(source_b) dest_dir = os.path.join(dest, 'aaa', 'ddd') message = str(error.PermissionDenied(subcmd=SUBCMD, file=dest_dir)) with pytest.raises(error.PermissionDenied, match=message): dploy.unstow([source_a], dest)
def test_stow_unfolding_with_first_sources_execute_permission_removed( source_a, source_b, dest): dploy.stow([source_a], dest) utils.remove_execute_permission(source_a) dest_dir = os.path.join(dest, 'aaa') message = str(error.PermissionDenied(subcmd=SUBCMD, file=dest_dir)) with pytest.raises(error.PermissionDenied, match=message): dploy.stow([source_b], dest)
def test_unstow_folding_with_multiple_sources_with_execute_permission_unset( source_a, source_b, dest): dploy.stow([source_a, source_b], dest) utils.remove_execute_permission(source_b) with pytest.raises(PermissionError) as e: dploy.unstow([source_a], dest) dest_dir = os.path.join(dest, 'aaa', 'ddd') assert error.PermissionDenied(subcmd=SUBCMD, file=dest_dir).msg in str(e.value)
def test_stow_unfolding_with_first_sources_execute_permission_removed( source_a, source_b, dest): dploy.stow([source_a], dest) utils.remove_execute_permission(source_a) with pytest.raises(PermissionError) as e: dploy.stow([source_b], dest) dest_dir = os.path.join(dest, 'aaa') assert (error.PermissionDenied(subcmd=SUBCMD, file=dest_dir).msg in str(e.value))
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
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_actions(self, source, dest): """ Concrete method to collect required actions to perform a stow sub-command """ if self.ignore.should_ignore(source): self.ignore.ignore(source) return if not StowInput(self.errors, self.subcmd).is_valid_collection_input( source, dest): return sources = self.get_directory_contents(source) for subsources in sources: if self.ignore.should_ignore(subsources): self.ignore.ignore(subsources) continue dest_path = dest / pathlib.Path(subsources.name) does_dest_path_exist = False try: does_dest_path_exist = dest_path.exists() except PermissionError: self.errors.add(error.PermissionDenied(self.subcmd, dest_path)) return if does_dest_path_exist: self._collect_actions_existing_dest(subsources, dest_path) elif dest_path.is_symlink(): self.errors.add( error.ConflictsWithExistingLink(self.subcmd, subsources, dest_path)) elif not dest_path.parent.exists() and not self.is_unfolding: self.errors.add( error.NoSuchDirectory(self.subcmd, dest_path.parent)) else: self._are_other(subsources, dest_path)