1use std::fs;
3use std::path::Path;
4
5use ssri::Integrity;
6
7use crate::content::rm;
8use crate::errors::{IoErrorExt, Result};
9use crate::index;
10
11#[cfg(any(feature = "async-std", feature = "tokio"))]
35pub async fn remove<P, K>(cache: P, key: K) -> Result<()>
36where
37 P: AsRef<Path>,
38 K: AsRef<str>,
39{
40 index::delete_async(cache.as_ref(), key.as_ref()).await
41}
42
43#[cfg(any(feature = "async-std", feature = "tokio"))]
68pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> {
69 rm::rm_async(cache.as_ref(), sri).await
70}
71
72#[cfg(any(feature = "async-std", feature = "tokio"))]
95pub async fn clear<P: AsRef<Path>>(cache: P) -> Result<()> {
96 async fn inner(cache: &Path) -> Result<()> {
97 for entry in cache
98 .read_dir()
99 .with_context(|| {
100 format!(
101 "Failed to read directory contents while clearing cache, at {}",
102 cache.display()
103 )
104 })?
105 .flatten()
106 {
107 crate::async_lib::remove_dir_all(entry.path())
108 .await
109 .with_context(|| format!("Failed to clear cache at {}", cache.display()))?;
110 }
111 Ok(())
112 }
113 inner(cache.as_ref()).await
114}
115
116pub fn remove_sync<P, K>(cache: P, key: K) -> Result<()>
138where
139 P: AsRef<Path>,
140 K: AsRef<str>,
141{
142 index::delete(cache.as_ref(), key.as_ref())
143}
144
145pub fn remove_hash_sync<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> {
168 rm::rm(cache.as_ref(), sri)
169}
170
171pub fn clear_sync<P: AsRef<Path>>(cache: P) -> Result<()> {
192 fn inner(cache: &Path) -> Result<()> {
193 for entry in cache
194 .read_dir()
195 .with_context(|| {
196 format!(
197 "Failed to read directory contents while clearing cache, at {}",
198 cache.display()
199 )
200 })?
201 .flatten()
202 {
203 fs::remove_dir_all(entry.path())
204 .with_context(|| format!("Failed to clear cache at {}", cache.display()))?;
205 }
206 Ok(())
207 }
208 inner(cache.as_ref())
209}
210
211#[cfg(test)]
212mod tests {
213
214 #[cfg(feature = "async-std")]
215 use async_attributes::test as async_test;
216 #[cfg(feature = "tokio")]
217 use tokio::test as async_test;
218
219 #[cfg(any(feature = "async-std", feature = "tokio"))]
220 #[async_test]
221 async fn test_remove() {
222 futures::executor::block_on(async {
223 let tmp = tempfile::tempdir().unwrap();
224 let dir = tmp.path().to_owned();
225 let sri = crate::write(&dir, "key", b"my-data").await.unwrap();
226
227 crate::remove(&dir, "key").await.unwrap();
228
229 let entry = crate::metadata(&dir, "key").await.unwrap();
230 assert_eq!(entry, None);
231
232 let data_exists = crate::exists(&dir, &sri).await;
233 assert!(data_exists);
234 });
235 }
236
237 #[cfg(any(feature = "async-std", feature = "tokio"))]
238 #[async_test]
239 async fn test_remove_data() {
240 futures::executor::block_on(async {
241 let tmp = tempfile::tempdir().unwrap();
242 let dir = tmp.path().to_owned();
243 let sri = crate::write(&dir, "key", b"my-data").await.unwrap();
244
245 crate::remove_hash(&dir, &sri).await.unwrap();
246
247 let entry = crate::metadata(&dir, "key").await.unwrap();
248 assert!(entry.is_some());
249
250 let data_exists = crate::exists(&dir, &sri).await;
251 assert!(!data_exists);
252 });
253 }
254
255 #[cfg(any(feature = "async-std", feature = "tokio"))]
256 #[async_test]
257 async fn test_clear() {
258 futures::executor::block_on(async {
259 let tmp = tempfile::tempdir().unwrap();
260 let dir = tmp.path().to_owned();
261 let sri = crate::write(&dir, "key", b"my-data").await.unwrap();
262
263 crate::clear(&dir).await.unwrap();
264
265 let entry = crate::metadata(&dir, "key").await.unwrap();
266 assert!(entry.is_none());
267
268 let data_exists = crate::exists(&dir, &sri).await;
269 assert!(!data_exists);
270 });
271 }
272
273 #[test]
274 fn test_remove_sync() {
275 let tmp = tempfile::tempdir().unwrap();
276 let dir = tmp.path().to_owned();
277 let sri = crate::write_sync(&dir, "key", b"my-data").unwrap();
278
279 crate::remove_sync(&dir, "key").unwrap();
280
281 let new_entry = crate::metadata_sync(&dir, "key").unwrap();
282 assert!(new_entry.is_none());
283
284 let data_exists = crate::exists_sync(&dir, &sri);
285 assert!(data_exists);
286 }
287
288 #[test]
289 fn test_remove_data_sync() {
290 let tmp = tempfile::tempdir().unwrap();
291 let dir = tmp.path().to_owned();
292 let sri = crate::write_sync(&dir, "key", b"my-data").unwrap();
293
294 crate::remove_hash_sync(&dir, &sri).unwrap();
295
296 let entry = crate::metadata_sync(&dir, "key").unwrap();
297 assert!(entry.is_some());
298
299 let data_exists = crate::exists_sync(&dir, &sri);
300 assert!(!data_exists);
301 }
302
303 #[test]
304 fn test_clear_sync() {
305 let tmp = tempfile::tempdir().unwrap();
306 let dir = tmp.path().to_owned();
307 let sri = crate::write_sync(&dir, "key", b"my-data").unwrap();
308
309 crate::clear_sync(&dir).unwrap();
310
311 let entry = crate::metadata_sync(&dir, "key").unwrap();
312 assert_eq!(entry, None);
313
314 let data_exists = crate::exists_sync(&dir, &sri);
315 assert!(!data_exists);
316 }
317}