1use std::path::Path;
2
3use crate::error::{Error, Result};
4use crate::finding::Finding;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum DeleteMode {
9 Trash,
11 Permanent,
13 DryRun,
15}
16
17pub struct CleanResult {
19 pub deleted_count: usize,
20 pub freed_bytes: u64,
21 pub errors: Vec<(String, String)>,
22}
23
24pub fn clean(findings: &[Finding], mode: DeleteMode) -> Result<CleanResult> {
26 let mut deleted_count = 0;
27 let mut freed_bytes = 0;
28 let mut errors: Vec<(String, String)> = Vec::new();
29
30 for finding in findings {
31 if mode == DeleteMode::DryRun {
32 deleted_count += 1;
33 freed_bytes += finding.size_bytes;
34 continue;
35 }
36
37 match delete_path(&finding.path, mode) {
38 Ok(()) => {
39 deleted_count += 1;
40 freed_bytes += finding.size_bytes;
41 }
42 Err(e) => {
43 errors.push((finding.path.display().to_string(), e.to_string()));
44 }
45 }
46 }
47
48 Ok(CleanResult {
49 deleted_count,
50 freed_bytes,
51 errors,
52 })
53}
54
55pub fn delete_path(path: &Path, mode: DeleteMode) -> Result<()> {
57 if !path.exists() {
58 return Ok(());
59 }
60
61 match mode {
62 DeleteMode::Trash => {
63 trash::delete(path).map_err(|e| Error::Trash(e.to_string()))?;
64 }
65 DeleteMode::Permanent => {
66 if path.is_dir() {
67 std::fs::remove_dir_all(path).map_err(|e| Error::io(path, e))?;
68 } else {
69 std::fs::remove_file(path).map_err(|e| Error::io(path, e))?;
70 }
71 }
72 DeleteMode::DryRun => {
73 }
75 }
76
77 Ok(())
78}