use std::env;
use std::fs;
use std::path::PathBuf;
use anyhow::Context;
use anyhow::Result;
use chrono::{Duration, Local};
use clap::ValueHint;
use garbage_fs::Filesystem;
use crate::TrashDir;
#[derive(Parser)]
pub struct EmptyOptions {
#[clap(long = "dry")]
pub dry: bool,
#[clap(long = "days")]
days: Option<u32>,
#[clap(long = "trash-dir", value_parser, value_hint(ValueHint::DirPath))]
trash_dir: Option<PathBuf>,
#[clap(short = 'a', long = "all")]
all: bool,
}
pub fn empty(options: EmptyOptions, fs: &impl Filesystem) -> Result<()> {
let trash_dir = TrashDir::from_opt(options.trash_dir.as_ref());
let cutoff = if let Some(days) = options.days {
Local::now() - Duration::days(days.into())
} else {
Local::now()
};
let current_dir = env::current_dir()?;
trash_dir
.iter(fs)?
.collect::<Result<Vec<_>>>()?
.into_iter()
.filter(|info| info.deletion_date <= cutoff)
.filter(|info| options.all || info.path.starts_with(¤t_dir))
.map(|info| -> Result<_> {
if options.dry {
println!("Deleting {:?}", info.path);
} else {
if info.deleted_path.exists() {
if info.deleted_path.is_dir() {
if let Err(err) = fs::remove_dir_all(&info.deleted_path) {
error!(?info.deleted_path, "Failed to remove original directory.");
return Err(err.into());
}
} else {
if let Err(err) = fs::remove_file(&info.deleted_path) {
error!(?info.deleted_path, "Failed to remove original file.");
return Err(err.into());
}
}
}
fs::remove_file(&info.info_path).with_context(|| {
format!("Failed to remove info file {:?}.", info.info_path.display())
})?;
}
Ok(())
})
.collect::<Result<_>>()?;
Ok(())
}