use std::path::{Path, PathBuf};
use crate::snapshot::error::SnapshotError;
pub fn list_snapshot_files(dir: &Path, name: &str) -> Result<Vec<PathBuf>, SnapshotError> {
let prefix = format!("{}-", name);
let extensions = [
".snap",
".snap.zst",
".snap.lz4",
".json",
".json.zst",
".json.lz4",
];
let read_dir_iter = match std::fs::read_dir(dir) {
Ok(r) => r,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(vec![]),
Err(e) => return Err(SnapshotError::Io(e)),
};
let mut entries: Vec<(std::time::SystemTime, PathBuf)> = read_dir_iter
.filter_map(|e| e.ok())
.filter_map(|e| {
let path = e.path();
if !path.is_file() {
return None;
}
let fname = path.file_name()?.to_str()?.to_owned();
if !fname.starts_with(&prefix) {
return None;
}
let has_ext = extensions
.iter()
.any(|ext| fname.ends_with(ext) && !fname.ends_with(".tmp"));
if !has_ext {
return None;
}
let mtime = e.metadata().ok()?.modified().ok()?;
Some((mtime, path))
})
.collect();
entries.sort_by_key(|(mtime, _)| *mtime);
Ok(entries.into_iter().map(|(_, p)| p).collect())
}
pub fn keep_n(dir: &Path, name: &str, n: usize) -> Result<(), SnapshotError> {
let files = list_snapshot_files(dir, name)?;
if files.len() <= n {
return Ok(());
}
let to_delete = files.len() - n;
for path in files.into_iter().take(to_delete) {
std::fs::remove_file(path)?;
}
Ok(())
}