garbage/src/ops/empty.rs

73 lines
2.1 KiB
Rust

use std::env;
use std::fs;
use std::path::PathBuf;
use chrono::{Duration, Local};
use crate::errors::Result;
use crate::TrashDir;
/// Options to pass to empty
#[derive(StructOpt)]
pub struct EmptyOptions {
/// Only list the files that are to be deleted, without
/// actually deleting anything.
#[structopt(long = "dry")]
pub dry: bool,
/// Delete all files older than (this number) of integer days.
/// Removes everything if this option is not specified
#[structopt(long = "days")]
days: Option<u32>,
/// The path to the trash directory to empty.
/// By default, this is your home directory's trash ($XDG_DATA_HOME/Trash)
#[structopt(long = "trash-dir", parse(from_os_str))]
trash_dir: Option<PathBuf>,
/// Delete all files in the trash (by default, only files in the current
/// directory are listed)
#[structopt(short = "a", long = "all")]
all: bool,
}
/// Actually delete files in the trash.
pub fn empty(options: EmptyOptions) -> Result<()> {
let trash_dir = TrashDir::from_opt(options.trash_dir.as_ref());
// cutoff date
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()?
.collect::<Result<Vec<_>>>()?
.into_iter()
// ignore files that were deleted after the cutoff (younger)
.filter(|info| info.deletion_date <= cutoff)
.filter(|info| options.all || info.path.starts_with(&current_dir))
.map(|info| -> Result<_> {
if options.dry {
println!("deleting {:?}", info.path);
} else {
fs::remove_file(info.info_path)?;
if info.deleted_path.exists() {
if info.deleted_path.is_dir() {
fs::remove_dir_all(info.deleted_path)?;
} else {
fs::remove_file(info.deleted_path)?;
}
}
}
Ok(())
})
.collect::<Result<_>>()?;
Ok(())
}