|
|
|
//! 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<state::State>, logger: &mut progress::logging::Logger, path: impl AsRef<Path>) -> eyre::Result<()>
|
|
|
|
{
|
|
|
|
let path = path.as_ref();
|
|
|
|
debug_assert!(path.is_file(), "process_single() expected a file, but {:?} is not one.", path);
|
|
|
|
|
|
|
|
let _g = state.lock().await;
|
|
|
|
trace!(logger => "{:?} Processing", path);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Process this path
|
|
|
|
///
|
|
|
|
/// This will not return until all its children finish too (if any)
|
|
|
|
pub async fn process<'a, P, L>(state: Arc<state::State>, mut logger: L, path: P) -> eyre::Result<()>
|
|
|
|
where P: 'a + Send + AsRef<Path>,
|
|
|
|
L: std::borrow::BorrowMut<progress::logging::Logger>
|
|
|
|
{
|
|
|
|
let path = path.as_ref();
|
|
|
|
|
|
|
|
if path.is_dir() {
|
|
|
|
let read = fs::read_dir(path).await?;
|
|
|
|
fn proc_dir(state: Arc<state::State>, logger: &mut progress::logging::Logger, mut read: fs::ReadDir) -> BoxFuture<'static, JoinHandle<Result<(), eyre::Report>>>
|
|
|
|
{
|
|
|
|
let mut logger = logger.clone();
|
|
|
|
async move {
|
|
|
|
tokio::spawn(async move {
|
|
|
|
while let Some(entry) = read.next_entry().await?
|
|
|
|
{
|
|
|
|
let path = entry.path();
|
|
|
|
if let Err(error) = process(Arc::clone(&state), &mut logger, &path).await {
|
|
|
|
{
|
|
|
|
let err = &error;
|
|
|
|
let path = &path; //TODO: Get these macros to stop moving
|
|
|
|
error!(logger => "{:?} child failed: {}", path, err);
|
|
|
|
}
|
|
|
|
debug!(logger => "Error for {:?}: {:?}", path, error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok::<_, eyre::Report>(())
|
|
|
|
})
|
|
|
|
}.boxed()
|
|
|
|
}
|
|
|
|
let handle = proc_dir(state, logger.borrow_mut(), 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, logger.borrow_mut(), path).await
|
|
|
|
} else {
|
|
|
|
Err(eyre!("Invalid/unsupported FSO"))
|
|
|
|
}.with_section(|| format!("{:?}", path).header("Path was"))
|
|
|
|
}
|