1use std::path::Path;
2
3use crate::log::log_status;
4
5pub fn delete_cached_model(canonical: &Path, output: Option<&Path>) -> anyhow::Result<()> {
9 let mut deleted_any = false;
10
11 if let Some(cache_dir) = canonical.parent() {
12 if cache_dir.exists() {
13 let file_count = walk_file_count(cache_dir);
14 std::fs::remove_dir_all(cache_dir)?;
15 log_status(&format!(
16 "Deleted cache directory {} ({} files)",
17 cache_dir.display(),
18 file_count
19 ));
20 deleted_any = true;
21 } else if canonical.exists() {
22 std::fs::remove_file(canonical)?;
23 log_status(&format!("Deleted {}", canonical.display()));
24 deleted_any = true;
25 } else {
26 log_status(&format!(
27 "No cache found at {} (already deleted?)",
28 cache_dir.display()
29 ));
30 }
31 } else if canonical.exists() {
32 std::fs::remove_file(canonical)?;
33 log_status(&format!("Deleted {}", canonical.display()));
34 deleted_any = true;
35 }
36
37 if let Some(out) = output {
38 if out.exists() {
39 std::fs::remove_file(out)?;
40 log_status(&format!("Deleted output {}", out.display()));
41 deleted_any = true;
42 } else {
43 log_status(&format!(
44 "Output file not found: {} (already deleted?)",
45 out.display()
46 ));
47 }
48 }
49
50 if !deleted_any {
51 log_status("Nothing to delete.");
52 }
53 Ok(())
54}
55
56fn walk_file_count(dir: &Path) -> usize {
57 let mut count = 0;
58 if let Ok(entries) = std::fs::read_dir(dir) {
59 for entry in entries.flatten() {
60 let path = entry.path();
61 if path.is_dir() {
62 count += walk_file_count(&path);
63 } else {
64 count += 1;
65 }
66 }
67 }
68 count
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use std::fs;
75
76 #[test]
77 fn deletes_cache_dir_and_output() {
78 let base = std::env::temp_dir().join(format!("zsfm-del-{}", std::process::id()));
79 let _ = fs::remove_dir_all(&base);
80 let cache_dir = base.join("owner__repo");
81 fs::create_dir_all(&cache_dir).unwrap();
82 let canonical = cache_dir.join("model-f32.gguf");
83 fs::write(&canonical, b"gguf").unwrap();
84 let out = base.join("out.gguf");
85 fs::write(&out, b"out").unwrap();
86 delete_cached_model(&canonical, Some(&out)).unwrap();
87 assert!(!cache_dir.exists());
88 assert!(!out.exists());
89 let _ = fs::remove_dir_all(&base);
90 }
91
92 #[test]
93 fn missing_cache_is_ok() {
94 let base = std::env::temp_dir().join(format!("zsfm-del-miss-{}", std::process::id()));
95 let canonical = base.join("owner__repo").join("model-f32.gguf");
96 delete_cached_model(&canonical, None).unwrap();
97 }
98}