use crate::*; #[must_use] pub fn copy(source_path: impl AsRef, destination_path: impl AsRef) -> WriteResult<()> { let source = get_entry(&source_path)?; let destination = get_optional_entry(&destination_path)?; let destination_type = destination.and_then(|e| Some(e.entry_type)); match (source.entry_type, destination_type) { (EntryType::File, Some(EntryType::File)) => { copy_file(source_path, destination_path)?; } (EntryType::File, Some(EntryType::Directory)) => { let destination_path = destination_path.as_ref().join(source.name); copy_file(source_path, destination_path)?; } (EntryType::File, None) => { make_parent_directory(&destination_path)?; copy_file(&source_path, &destination_path)?; } (EntryType::Directory, Some(EntryType::File)) => { // The file is replaced by a copy of the source directory remove_file(&destination_path)?; copy_directory(&source_path, &destination_path)?; } (EntryType::Directory, Some(EntryType::Directory)) => { // The destination is filled with the contents of the source directory for entry in list_directory(source_path)? { let destination_path = destination_path.as_ref().join(&entry.name); copy(entry.path, destination_path)?; } } (EntryType::Directory, None) => { // The destination is created as a copy of the source directory copy_directory(&source_path, &destination_path)?; } } Ok(()) } #[must_use] fn copy_file(source_path: impl AsRef, destination_path: impl AsRef) -> WriteResult<()> { let copy_result = std::fs::copy(&source_path, &destination_path); io_result_to_write_result(copy_result, &destination_path.as_ref())?; Ok(()) } #[must_use] fn copy_directory(source_path: impl AsRef, destination_path: impl AsRef) -> WriteResult<()> { for entry in list_directory(&source_path)? { let destination_path = destination_path.as_ref().join(entry.name); copy(entry.path, &destination_path)?; } Ok(()) }