122 lines
3.1 KiB
Rust
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);
|
|
}
|