1use std::{env, fs, io::Result, path::PathBuf};
4
5use crate::config::{dev_dir, downloads_dir};
6
7#[derive(Debug, Clone)]
9#[cfg_attr(feature = "cli", derive(clap::Subcommand))]
10pub enum Drain {
11 All,
13 Oci,
15 Lib,
17 Dev,
19 Downloads,
21}
22
23impl IntoIterator for &Drain {
24 type Item = PathBuf;
25 type IntoIter = std::vec::IntoIter<Self::Item>;
26
27 fn into_iter(self) -> Self::IntoIter {
28 let paths = match self {
29 Drain::All => vec![
30 env::temp_dir().join("wasmcloudcache"),
31 env::temp_dir().join("wasmcloud_ocicache"),
32 downloads_dir().unwrap_or_default(),
33 ],
34 Drain::Lib => vec![env::temp_dir().join("wasmcloudcache")],
35 Drain::Oci => vec![env::temp_dir().join("wasmcloud_ocicache")],
36 Drain::Dev => vec![dev_dir().unwrap_or_default()],
37 Drain::Downloads => vec![downloads_dir().unwrap_or_default()],
38 };
39 paths.into_iter()
40 }
41}
42
43impl Drain {
44 pub fn drain(self) -> Result<Vec<PathBuf>> {
47 self.into_iter()
48 .filter(|path| path.exists())
49 .map(remove_dir_contents)
50 .collect::<Result<Vec<PathBuf>>>()
51 }
52}
53
54fn remove_dir_contents(path: PathBuf) -> Result<PathBuf> {
55 for entry in fs::read_dir(&path)? {
56 let path = entry?.path();
57 if path.is_dir() {
58 fs::remove_dir_all(&path)?;
59 } else if path.is_file() {
60 fs::remove_file(&path)?;
61 }
62 }
63 Ok(path)
64}
65
66#[cfg(test)]
67mod test {
68 use super::*;
69
70 #[test]
71 fn test_dir_clean() {
72 let tempdir = tempfile::tempdir().expect("Unable to create tempdir");
73
74 let subdir = tempdir.path().join("foobar");
75 fs::create_dir(&subdir).unwrap();
76
77 {
79 fs::File::create(subdir.join("baz")).unwrap();
80 fs::File::create(tempdir.path().join("baz")).unwrap();
81 }
82
83 remove_dir_contents(tempdir.path().to_owned())
84 .expect("Shouldn't get an error when cleaning files");
85 assert!(
86 tempdir
87 .path()
88 .read_dir()
89 .expect("Top level dir should still exist")
90 .next()
91 .is_none(),
92 "Directory should be empty"
93 );
94 }
95}