use crate::Result;
use crate::vfs::Vfs;
const SCRATCH_DIR: &str = "tmp";
const SCRATCH_PREFIX: &str = "scratch-";
pub async fn delete_orphaned_scratch<V: Vfs + Clone>(vfs: &V) -> Result<u64> {
let entries = vfs.list_dir(SCRATCH_DIR).await?;
let mut count: u64 = 0;
for name in entries {
if !name.starts_with(SCRATCH_PREFIX) {
continue;
}
vfs.remove(&format!("{SCRATCH_DIR}/{name}")).await?;
count += 1;
}
if count > 0 {
vfs.sync_dir(SCRATCH_DIR).await?;
}
Ok(count)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::vfs::VfsFile;
use crate::vfs::memory::MemVfs;
use crate::vfs::types::OpenMode;
async fn write(vfs: &MemVfs, path: &str) {
vfs.mkdir_all(SCRATCH_DIR).await.unwrap();
let mut f = vfs.open(path, OpenMode::CreateNew).await.unwrap();
f.write_at(0, b"scratch").await.unwrap();
}
#[tokio::test(flavor = "current_thread")]
async fn sweeps_scratch_and_spares_unrelated_names() {
let vfs = MemVfs::new();
write(&vfs, "tmp/scratch-1").await;
write(&vfs, "tmp/scratch-9").await;
write(&vfs, "tmp/unrelated").await;
assert_eq!(delete_orphaned_scratch(&vfs).await.unwrap(), 2);
assert!(vfs.open("tmp/scratch-1", OpenMode::Read).await.is_err());
assert!(vfs.open("tmp/scratch-9", OpenMode::Read).await.is_err());
assert!(vfs.open("tmp/unrelated", OpenMode::Read).await.is_ok());
}
#[tokio::test(flavor = "current_thread")]
async fn absent_scratch_directory_is_not_an_error() {
let vfs = MemVfs::new();
assert_eq!(delete_orphaned_scratch(&vfs).await.unwrap(), 0);
}
}