acme_disk_use/
disk_use.rs1use std::{io, path::Path};
4
5use crate::cache::CacheManager;
6use crate::scanner::{self, DirStat};
7
8pub struct DiskUse {
10 cache_manager: CacheManager,
11}
12
13impl DiskUse {
14 pub fn new(cache_path: impl AsRef<Path>) -> Self {
16 Self {
17 cache_manager: CacheManager::new(cache_path),
18 }
19 }
20
21 pub fn new_with_default_cache() -> Self {
23 Self::new(crate::get_default_cache_path())
24 }
25
26 pub fn scan(&mut self, path: impl AsRef<Path>) -> io::Result<u64> {
33 self.scan_with_options(path, false)
34 }
35
36 pub fn scan_with_options(
42 &mut self,
43 path: impl AsRef<Path>,
44 ignore_cache: bool,
45 ) -> io::Result<u64> {
46 let path = path.as_ref();
47
48 let path_buf = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
50
51 let old_entry = if ignore_cache {
53 None
54 } else {
55 self.cache_manager.get(&path_buf)
56 };
57
58 let new_entry = scanner::scan_directory(path, old_entry)?;
60
61 let total_size = new_entry.total_size();
63
64 if !ignore_cache {
66 self.cache_manager.update(&path_buf, new_entry);
67 }
69
70 Ok(total_size)
71 }
72
73 pub fn get_stats(&self, path: impl AsRef<Path>) -> Option<&DirStat> {
75 self.cache_manager.get(path.as_ref())
76 }
77
78 pub fn get_file_count(&self, path: impl AsRef<Path>, ignore_cache: bool) -> io::Result<u64> {
84 if ignore_cache {
85 scanner::count_files(path.as_ref())
86 } else {
87 Ok(self
88 .get_stats(path)
89 .map(|stats| stats.file_count())
90 .unwrap_or(0))
91 }
92 }
93
94 pub fn save_cache(&mut self) -> io::Result<()> {
96 self.cache_manager.save()
97 }
98
99 pub fn clear_cache(&mut self) -> io::Result<()> {
101 self.cache_manager.clear()
102 }
103
104 pub fn delete_cache(&self) -> io::Result<()> {
106 self.cache_manager.delete()
107 }
108
109 pub fn cache_path(&self) -> &Path {
111 self.cache_manager.path()
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use std::fs;
119 use tempfile::TempDir;
120
121 fn create_test_directory_structure(base: &Path) -> io::Result<()> {
122 fs::create_dir_all(base.join("subdir1"))?;
123 fs::create_dir_all(base.join("subdir2/nested"))?;
124
125 fs::write(base.join("file1.txt"), "Hello World")?;
126 fs::write(base.join("file2.txt"), "Test content")?;
127 fs::write(base.join("subdir1/nested_file.txt"), "Nested content here")?;
128 fs::write(base.join("subdir2/another.txt"), "More content")?;
129 fs::write(base.join("subdir2/nested/deep.txt"), "Deep file content")?;
130
131 Ok(())
132 }
133
134 #[test]
135 fn test_disk_use_with_cache() -> io::Result<()> {
136 let temp_dir = TempDir::new()?;
137 let test_dir = temp_dir.path().join("test");
138 let cache_file = temp_dir.path().join("cache.bin");
139
140 fs::create_dir(&test_dir)?;
141 create_test_directory_structure(&test_dir)?;
142
143 let canonical_test_dir = test_dir.canonicalize()?;
144
145 {
146 let mut disk_use = DiskUse::new(&cache_file);
147 let size1 = disk_use.scan(&canonical_test_dir)?;
148 assert_eq!(size1, 71);
149
150 disk_use.save_cache()?;
152 } assert!(cache_file.exists());
155
156 {
157 let mut disk_use = DiskUse::new(&cache_file);
158 let _size2 = disk_use.scan(&canonical_test_dir)?;
159 assert_eq!(_size2, 71);
160
161 let file_count = disk_use.get_file_count(&canonical_test_dir, false)?;
162 assert_eq!(file_count, 5);
163 }
164
165 Ok(())
166 }
167
168 #[test]
169 fn test_disk_use_ignore_cache() -> io::Result<()> {
170 let temp_dir = TempDir::new()?;
171 let test_dir = temp_dir.path().join("test");
172 let cache_file = temp_dir.path().join("cache.json");
173
174 fs::create_dir(&test_dir)?;
175 create_test_directory_structure(&test_dir)?;
176
177 let mut disk_use = DiskUse::new(&cache_file);
178
179 let size1 = disk_use.scan(&test_dir)?;
180 assert_eq!(size1, 71);
181
182 fs::write(test_dir.join("new_file.txt"), "New content")?;
183
184 let _size2 = disk_use.scan(&test_dir)?;
185
186 let size3 = disk_use.scan_with_options(&test_dir, true)?;
187 assert_eq!(size3, 82);
188
189 Ok(())
190 }
191
192 #[test]
193 fn test_cache_management() -> io::Result<()> {
194 let temp_dir = TempDir::new()?;
195 let test_dir = temp_dir.path().join("test");
196 let cache_file = temp_dir.path().join("cache.bin");
197
198 fs::create_dir(&test_dir)?;
199 create_test_directory_structure(&test_dir)?;
200
201 {
202 let mut disk_use = DiskUse::new(&cache_file);
203
204 disk_use.scan(&test_dir)?;
205 disk_use.save_cache()?; } assert!(cache_file.exists());
209
210 {
211 let mut disk_use = DiskUse::new(&cache_file);
212 disk_use.clear_cache()?;
213
214 disk_use.delete_cache()?;
215 }
216
217 assert!(!cache_file.exists());
218
219 Ok(())
220 }
221}