1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
use std::fs; use std::path::{Path, PathBuf}; use walkdir::{DirEntry, WalkDir}; use crate::errors::Error; use crate::info::TrashInfo; use crate::XDG; #[derive(Clone, Debug)] pub struct TrashDir(pub PathBuf); impl TrashDir { pub fn get_home_trash() -> Self { TrashDir(XDG.get_data_home().join("Trash")) } pub fn path(&self) -> &Path { self.0.as_ref() } pub fn files_dir(&self) -> Result<PathBuf, Error> { let target = self.0.join("files"); if !target.exists() { fs::create_dir_all(&target)?; } Ok(target) } pub fn info_dir(&self) -> Result<PathBuf, Error> { let target = self.0.join("info"); if !target.exists() { fs::create_dir_all(&target)?; } Ok(target) } pub fn iter(&self) -> Result<TrashDirIter, Error> { let iter = WalkDir::new(&self.info_dir()?) .contents_first(true) .into_iter() .filter_entry(|entry| match entry.path().extension() { Some(x) => x == "trashinfo", _ => false, }); Ok(TrashDirIter(self.0.clone(), Box::new(iter))) } } pub struct TrashDirIter(PathBuf, Box<dyn Iterator<Item = walkdir::Result<DirEntry>>>); impl Iterator for TrashDirIter { type Item = Result<TrashInfo, Error>; fn next(&mut self) -> Option<Self::Item> { let entry = { let mut entry; loop { entry = match self.1.next() { Some(Ok(entry)) => entry, Some(Err(err)) => return Some(Err(Error::from(err))), None => return None, }; if entry.path().is_dir() { continue; } break; } entry }; let name = entry.path().file_name().unwrap().to_str().unwrap(); let deleted_path = if !name.ends_with(".trashinfo") { return self.next(); } else { self.0 .join("files") .join(name.trim_end_matches(".trashinfo")) }; Some(TrashInfo::from_files(entry.path(), deleted_path).map_err(Error::from)) } }