use std::fs;
use std::path::Path;
use std::time::SystemTime;
use crate::error::DocError;
use crate::walk;
pub(crate) fn is_up_to_date(
output_path: &Path,
md_mtime: SystemTime,
template_mtime: Option<SystemTime>,
) -> Result<bool, DocError> {
let Ok(output_meta) = fs::metadata(output_path) else {
return Ok(false);
};
let output_mtime = output_meta.modified()?;
let newest_input = match template_mtime {
Some(t) if t > md_mtime => t,
_ => md_mtime,
};
Ok(output_mtime >= newest_input)
}
pub(crate) fn latest_mtime(dir: &Path, extension: &str) -> Result<Option<SystemTime>, DocError> {
let mut latest: Option<SystemTime> = None;
for path in walk::walk_files_with_extension(dir, extension)? {
let mtime = fs::metadata(&path)?.modified()?;
latest = Some(match latest {
Some(l) if l > mtime => l,
_ => mtime,
});
}
Ok(latest)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn missing_output_is_never_up_to_date() {
let dir = tempfile::tempdir().expect("create tempdir");
let missing = dir.path().join("does-not-exist.html");
let up_to_date =
is_up_to_date(&missing, SystemTime::now(), None).expect("check should succeed");
assert!(!up_to_date);
}
#[test]
fn output_older_than_md_is_not_up_to_date() {
let dir = tempfile::tempdir().expect("create tempdir");
let output = dir.path().join("out.html");
fs::write(&output, "stale").expect("write output");
let output_mtime = fs::metadata(&output)
.expect("stat output")
.modified()
.expect("mtime");
let newer_md_mtime = output_mtime + std::time::Duration::from_secs(1);
let up_to_date =
is_up_to_date(&output, newer_md_mtime, None).expect("check should succeed");
assert!(!up_to_date);
}
#[test]
fn output_newer_than_both_inputs_is_up_to_date() {
let dir = tempfile::tempdir().expect("create tempdir");
let output = dir.path().join("out.html");
fs::write(&output, "fresh").expect("write output");
let output_mtime = fs::metadata(&output)
.expect("stat output")
.modified()
.expect("mtime");
let older = output_mtime - std::time::Duration::from_secs(1);
let up_to_date = is_up_to_date(&output, older, Some(older)).expect("check should succeed");
assert!(up_to_date);
}
#[test]
fn output_older_than_template_is_not_up_to_date_even_if_newer_than_md() {
let dir = tempfile::tempdir().expect("create tempdir");
let output = dir.path().join("out.html");
fs::write(&output, "stale").expect("write output");
let output_mtime = fs::metadata(&output)
.expect("stat output")
.modified()
.expect("mtime");
let older_md = output_mtime - std::time::Duration::from_secs(2);
let newer_template = output_mtime + std::time::Duration::from_secs(1);
let up_to_date =
is_up_to_date(&output, older_md, Some(newer_template)).expect("check should succeed");
assert!(!up_to_date);
}
}