1use std::path::PathBuf;
13
14use crate::error::CliError;
15
16pub fn execute_cache_clear(store: Option<&str>) -> Result<(), CliError> {
22 match store {
23 Some(store_name) => clear_store(store_name),
24 None => clear_all(),
25 }
26}
27
28fn clear_store(store: &str) -> Result<(), CliError> {
30 let cache_dir = get_cache_dir(store);
31
32 if !cache_dir.exists() {
33 println!(
34 "Cache store '{}' directory not found: {}",
35 store,
36 cache_dir.display()
37 );
38 return Ok(());
39 }
40
41 let count = remove_dir_contents(&cache_dir)?;
42 println!(
43 "Cache store '{}' cleared: {} file(s) removed from {}",
44 store,
45 count,
46 cache_dir.display()
47 );
48 Ok(())
49}
50
51fn clear_all() -> Result<(), CliError> {
53 let cache_root = get_cache_root();
54
55 if !cache_root.exists() {
56 println!("Cache root directory not found: {}", cache_root.display());
57 println!("Nothing to clear.");
58 return Ok(());
59 }
60
61 let count = remove_dir_contents(&cache_root)?;
62 println!(
63 "All caches cleared: {} file(s)/dir(s) removed from {}",
64 count,
65 cache_root.display()
66 );
67 Ok(())
68}
69
70fn get_cache_root() -> PathBuf {
74 PathBuf::from("runtime/cache")
75}
76
77fn get_cache_dir(store: &str) -> PathBuf {
79 get_cache_root().join(store)
80}
81
82fn remove_dir_contents(path: &PathBuf) -> Result<usize, CliError> {
88 let mut count = 0;
89 let entries = std::fs::read_dir(path)?;
90 for entry in entries {
91 let entry = entry?;
92 let entry_path = entry.path();
93 if entry_path.is_dir() {
94 std::fs::remove_dir_all(&entry_path)?;
95 } else {
96 std::fs::remove_file(&entry_path)?;
97 }
98 count += 1;
99 }
100 Ok(count)
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106 use std::fs;
107 use std::io::Write;
108
109 #[test]
110 fn test_get_cache_root_default() {
111 let root = get_cache_root();
112 assert_eq!(root, PathBuf::from("runtime/cache"));
113 }
114
115 #[test]
116 fn test_get_cache_dir_with_store() {
117 let dir = get_cache_dir("redis");
118 assert_eq!(dir, PathBuf::from("runtime/cache/redis"));
119 }
120
121 #[test]
122 fn test_clear_all_nonexistent_dir() {
123 let temp = tempfile::tempdir().unwrap();
125 let cache_root = temp.path().join("runtime/cache");
126 assert!(!cache_root.exists());
128 }
129
130 #[test]
131 fn test_clear_all_with_files_via_remove_dir_contents() {
132 let temp = tempfile::tempdir().unwrap();
134 let root = temp.path().to_path_buf();
135
136 let file1 = root.join("cache1.txt");
138 let file2 = root.join("cache2.txt");
139 let mut f1 = fs::File::create(&file1).unwrap();
140 writeln!(f1, "data1").unwrap();
141 let mut f2 = fs::File::create(&file2).unwrap();
142 writeln!(f2, "data2").unwrap();
143
144 let count = remove_dir_contents(&root).unwrap();
145 assert_eq!(count, 2);
146 assert!(!file1.exists());
147 assert!(!file2.exists());
148 }
149
150 #[test]
151 fn test_clear_store_nonexistent() {
152 let temp = tempfile::tempdir().unwrap();
154 let store_dir = temp.path().join("nonexistent_store");
155 assert!(!store_dir.exists());
156 }
157
158 #[test]
159 fn test_clear_store_with_files_via_remove_dir_contents() {
160 let temp = tempfile::tempdir().unwrap();
161 let store_dir = temp.path().join("redis");
162 fs::create_dir_all(&store_dir).unwrap();
163
164 let cache_file = store_dir.join("key1.txt");
165 let mut f = fs::File::create(&cache_file).unwrap();
166 writeln!(f, "redis_data").unwrap();
167
168 let count = remove_dir_contents(&store_dir).unwrap();
169 assert_eq!(count, 1);
170 assert!(!cache_file.exists());
171 }
172
173 #[test]
174 fn test_remove_dir_contents_with_subdirs() {
175 let temp = tempfile::tempdir().unwrap();
176 let root = temp.path().to_path_buf();
177
178 let sub_dir = root.join("subdir");
180 fs::create_dir_all(&sub_dir).unwrap();
181 fs::File::create(root.join("file1.txt")).unwrap();
182 fs::File::create(sub_dir.join("file2.txt")).unwrap();
183
184 let count = remove_dir_contents(&root).unwrap();
185 assert_eq!(count, 2); assert!(root.exists());
189 assert!(root.read_dir().unwrap().next().is_none());
190 }
191
192 #[test]
193 fn test_execute_cache_clear_no_store_nonexistent() {
194 let _lock = super::super::test_support::acquire_global_lock();
198 let temp = tempfile::tempdir().unwrap();
199 let original = std::env::current_dir().unwrap();
200 std::env::set_current_dir(temp.path()).unwrap();
201 let result = execute_cache_clear(None);
202 std::env::set_current_dir(&original).unwrap();
203 assert!(result.is_ok());
204 }
205
206 #[test]
207 fn test_execute_cache_clear_with_store_nonexistent() {
208 let result = execute_cache_clear(Some("nonexistent_store_xyz"));
210 assert!(result.is_ok());
211 }
212}