//! Handle deletion //! //! # Handling paths //! Deletion of single files is trivial, deletion of directories is not as trivial. //! Other types of filesystem object are ignored. //! //! ## Directories //! With directories the deletion processes all files containing recursively. //! See `restore` for restoration of directories use super::*; use std::{ path::{ Path, }, }; use tokio::{ fs, task::JoinHandle, }; use futures::{ prelude::*, future::BoxFuture, }; /// Process a single file. /// /// `path` is known to be a file at this point. async fn process_single(state: Arc, path: impl AsRef) -> eyre::Result<()> { let path = path.as_ref(); #[cfg(debug_assertions)] { if !path.is_file() { panic!("process_single() expected a file, but {:?} is not one.", path); } } let _g = state.lock().await; debug!("{:?} Processing", path); //TODO: Actual processing Ok(()) } /// Process this path /// /// This will not return until all its children finish too (if any) pub async fn process<'a, P>(state: Arc, path: P) -> eyre::Result<()> where P: 'a + Send + AsRef { let path = path.as_ref(); if path.is_dir() { let read = fs::read_dir(path).await?; fn proc_dir(state: Arc, mut read: fs::ReadDir) -> BoxFuture<'static, JoinHandle>> { async move { tokio::spawn(async move { while let Some(entry) = read.next_entry().await? { process(Arc::clone(&state), entry.path()).await?; } Ok::<_, eyre::Report>(()) }) }.boxed() } let handle = proc_dir(state, read).await; let res = handle.await .wrap_err(eyre!("Child exited abnormally"))?; res.wrap_err(eyre!("Failed to process children")) } else if path.is_file() { process_single(state, path).await } else { Err(eyre!("Invalid/unsupported FSO")) }.with_section(|| format!("{:?}", path).header("Path was")) }