Skip to main content

zag_agent/
file_util.rs

1//! Atomic file write utilities.
2//!
3//! Provides helpers that write to a temporary file and then rename,
4//! ensuring the target file is never left in a partially-written state.
5
6use anyhow::{Context, Result};
7use std::path::Path;
8
9/// Write `content` to `path` atomically.
10///
11/// Writes to a sibling `.tmp` file first, then renames. On Unix,
12/// `rename()` is atomic within the same filesystem, so the target file
13/// is either the old version or the new one — never a partial write.
14pub fn atomic_write(path: &Path, content: &[u8]) -> Result<()> {
15    if let Some(parent) = path.parent() {
16        std::fs::create_dir_all(parent)
17            .with_context(|| format!("Failed to create directory: {}", parent.display()))?;
18    }
19    let tmp_path = path.with_extension("tmp");
20    std::fs::write(&tmp_path, content)
21        .with_context(|| format!("Failed to write temp file: {}", tmp_path.display()))?;
22    std::fs::rename(&tmp_path, path).with_context(|| {
23        format!(
24            "Failed to rename {} -> {}",
25            tmp_path.display(),
26            path.display()
27        )
28    })?;
29    Ok(())
30}
31
32/// Convenience wrapper: atomically write a `&str` to `path`.
33pub fn atomic_write_str(path: &Path, content: &str) -> Result<()> {
34    atomic_write(path, content.as_bytes())
35}
36
37#[cfg(test)]
38#[path = "file_util_tests.rs"]
39mod tests;