pacenotes_installer\cache/
payloads.rs1impl super::Cache {
2 pub fn payload_path(&self, sha256: &str) -> std::path::PathBuf {
4 self.root.join(format!("{sha256}.zip"))
5 }
6
7 pub fn has_payload(&self, sha256: &str) -> bool {
9 self.payload_path(sha256).is_file()
10 }
11
12 pub fn holds(&self, key: &str) -> bool {
14 self.get(key)
15 .is_some_and(|entry| self.has_payload(&entry.sha256))
16 }
17
18 pub fn orphans(&self) -> Vec<std::path::PathBuf> {
21 if self.state != super::IndexState::Loaded {
22 return Vec::new();
23 }
24 let known = self.known_digests();
25 let Ok(entries) = std::fs::read_dir(&self.root) else {
26 return Vec::new();
27 };
28 entries
29 .flatten()
30 .map(|entry| entry.path())
31 .filter(|path| path.extension().is_some_and(|extension| extension == "zip"))
32 .filter(|path| {
33 path.file_stem()
34 .and_then(|stem| stem.to_str())
35 .is_none_or(|stem| !known.contains(stem))
36 })
37 .collect()
38 }
39
40 pub fn sweep(&self, in_use: Option<&[String]>) -> Swept {
45 let mut swept = Swept::default();
46 let Ok(entries) = std::fs::read_dir(&self.root) else {
47 return swept;
48 };
49 for path in entries.flatten().map(|entry| entry.path()) {
50 let stem = path
51 .file_stem()
52 .and_then(|stem| stem.to_str())
53 .unwrap_or("");
54 let removable = match path.extension().and_then(|extension| extension.to_str()) {
55 Some("part") => true,
56 Some("zip") => in_use.is_some_and(|in_use| {
57 self.state == super::IndexState::Loaded
58 && !self.names(stem)
59 && !in_use.iter().any(|sha256| sha256 == stem)
60 }),
61 _ => false,
62 };
63 let size = std::fs::metadata(&path).map_or(0, |metadata| metadata.len());
64 if removable && std::fs::remove_file(&path).is_ok() {
65 swept.files += 1;
66 swept.bytes += size;
67 }
68 }
69 swept
70 }
71}
72
73#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
75pub struct Swept {
76 pub files: usize,
77 pub bytes: u64,
78}