use crate::CacheKey;
use chrono::DateTime;
use chrono::Local;
use eyre::Context;
use eyre::Result;
use std::path::PathBuf;
use std::time::Duration;
pub async fn discover_caches(root: &PathBuf) -> Result<Vec<(CacheKey, DateTime<Local>)>> {
let mut dirs = vec![root.clone()];
let mut results: Vec<(CacheKey, DateTime<Local>)> = Vec::new();
while let Some(dir) = dirs.pop() {
let mut read_dir = tokio::fs::read_dir(&dir)
.await
.wrap_err_with(|| format!("failed reading directory {}", dir.display()))?;
while let Some(entry) = read_dir
.next_entry()
.await
.wrap_err_with(|| format!("failed reading directory {}", dir.display()))?
{
let path = entry.path();
if path.is_dir() {
dirs.push(path);
} else if let Some(file_name) = path.file_name()
&& file_name == "timestamp.txt"
{
let contents = tokio::fs::read_to_string(&path).await.wrap_err_with(|| {
format!("failed reading timestamp file {}", path.display())
})?;
if let Some(last_line) = contents.lines().last() {
let parsed = DateTime::parse_from_rfc2822(last_line)
.wrap_err_with(|| {
format!("failed parsing timestamp in {}", path.display())
})?
.with_timezone(&Local);
if let Some(parent) = path.parent() {
let rel = match parent.strip_prefix(root) {
Ok(x) => x.to_path_buf(),
Err(_) => parent.to_path_buf(),
};
let mut key = CacheKey::new(rel);
key.valid_for = Duration::MAX;
results.push((key, parsed));
}
}
}
}
}
Ok(results)
}