use crate::utils::atomic::atomic_write;
use serde::{Deserialize, Serialize};
const OVERLAP_POLICY_VERSION: u32 = 1;
#[derive(Deserialize, Serialize)]
struct OverlapPolicy {
version: u32,
allow_overlapping_runs: bool,
}
pub(crate) fn read_overlap_policy(rel_dir: &str) -> Result<bool, String> {
let path = crate::paths::routine_overlap_json_path(rel_dir);
let text = match std::fs::read_to_string(&path) {
Ok(text) => text,
Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(false),
Err(error) => return Err(format!("cannot read {}: {error}", path.display())),
};
let policy: OverlapPolicy = serde_json::from_str(&text)
.map_err(|error| format!("invalid overlap policy {}: {error}", path.display()))?;
if policy.version != OVERLAP_POLICY_VERSION {
return Err(format!(
"unsupported overlap policy version {} in {}",
policy.version,
path.display()
));
}
Ok(policy.allow_overlapping_runs)
}
pub(crate) fn ensure_overlap_policy(rel_dir: &str) -> std::io::Result<()> {
let path = crate::paths::routine_overlap_json_path(rel_dir);
if path.exists() {
return Ok(());
}
write_overlap_policy_file(&path, false)
}
fn write_overlap_policy_file(
path: &std::path::Path,
allow_overlapping_runs: bool,
) -> std::io::Result<()> {
let policy = OverlapPolicy {
version: OVERLAP_POLICY_VERSION,
allow_overlapping_runs,
};
let bytes = serde_json::to_vec(&policy).map_err(std::io::Error::other)?;
atomic_write(path, &bytes)
}
#[cfg(test)]
pub(crate) fn write_overlap_policy(
rel_dir: &str,
allow_overlapping_runs: bool,
) -> std::io::Result<()> {
let path = crate::paths::routine_overlap_json_path(rel_dir);
if !allow_overlapping_runs {
if path.exists() {
std::fs::remove_file(path)?;
}
return Ok(());
}
write_overlap_policy_file(&path, allow_overlapping_runs)
}