Files
pile/crates/pile-value/src/source/misc.rs
2026-03-16 09:56:46 -07:00

122 lines
3.1 KiB
Rust

use chrono::{DateTime, Utc};
use std::fs;
use std::path::Path;
/// Returns the age of a path as a [DateTime].
/// - If the path doesn't exist, returns [None]
/// - If it's a file, returns the modified time
/// - If it's a directory, returns the LATEST modified time of all files within
pub fn path_ts_latest(path: impl AsRef<Path>) -> Result<Option<DateTime<Utc>>, std::io::Error> {
let path = path.as_ref();
if !path.exists() {
return Ok(None);
}
let metadata = fs::metadata(path)?;
if metadata.is_file() {
let modified = metadata.modified()?;
Ok(Some(modified.into()))
} else if metadata.is_dir() {
find_latest_modified(path)
} else {
Ok(None)
}
}
/// Returns the age of a path as a [DateTime].
/// - If the path doesn't exist, returns [None]
/// - If it's a file, returns the modified time
/// - If it's a directory, returns the EARLIEST modified time of all files within
pub fn path_ts_earliest(path: impl AsRef<Path>) -> Result<Option<DateTime<Utc>>, std::io::Error> {
let path = path.as_ref();
if !path.exists() {
return Ok(None);
}
let metadata = fs::metadata(path)?;
if metadata.is_file() {
let modified = metadata.modified()?;
Ok(Some(modified.into()))
} else if metadata.is_dir() {
find_earliest_modified(path)
} else {
Ok(None)
}
}
fn find_latest_modified(dir: &Path) -> Result<Option<DateTime<Utc>>, std::io::Error> {
let mut latest: Option<DateTime<Utc>> = None;
// Include the directory's own modification time
let dir_metadata = fs::metadata(dir)?;
if let Ok(modified) = dir_metadata.modified() {
let dt: DateTime<Utc> = modified.into();
latest = Some(dt);
}
let entries = fs::read_dir(dir)?;
for entry in entries.flatten() {
let path = entry.path();
let metadata = entry.metadata()?;
if metadata.is_file() {
if let Ok(modified) = metadata.modified() {
let dt: DateTime<Utc> = modified.into();
latest = Some(match latest {
Some(prev) if prev > dt => prev,
_ => dt,
});
}
} else if metadata.is_dir()
&& let Some(dir_latest) = find_latest_modified(&path)?
{
latest = Some(match latest {
Some(prev) if prev > dir_latest => prev,
_ => dir_latest,
});
}
}
return Ok(latest);
}
fn find_earliest_modified(dir: &Path) -> Result<Option<DateTime<Utc>>, std::io::Error> {
let mut earliest: Option<DateTime<Utc>> = None;
// Include the directory's own modification time
let dir_metadata = fs::metadata(dir)?;
if let Ok(modified) = dir_metadata.modified() {
let dt: DateTime<Utc> = modified.into();
earliest = Some(dt);
}
let entries = fs::read_dir(dir)?;
for entry in entries.flatten() {
let path = entry.path();
let metadata = entry.metadata()?;
if metadata.is_file() {
if let Ok(modified) = metadata.modified() {
let dt: DateTime<Utc> = modified.into();
earliest = Some(match earliest {
Some(prev) if prev < dt => prev,
_ => dt,
});
}
} else if metadata.is_dir()
&& let Some(dir_earliest) = find_earliest_modified(&path)?
{
earliest = Some(match earliest {
Some(prev) if prev < dir_earliest => prev,
_ => dir_earliest,
});
}
}
return Ok(earliest);
}