use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use uuid::Uuid;
pub fn atomic_write(path: &Path, bytes: &[u8]) -> io::Result<()> {
let tmp = tmp_path(path);
if let Err(err) = write_tmp(&tmp, bytes) {
let _ = fs::remove_file(&tmp);
return Err(err);
}
if let Err(err) = fs::rename(&tmp, path) {
let _ = fs::remove_file(&tmp);
return Err(err);
}
Ok(())
}
fn tmp_path(path: &Path) -> PathBuf {
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("tmp");
let mut tmp = path.to_path_buf();
tmp.set_file_name(format!(".{name}.{}.tmp", Uuid::new_v4()));
tmp
}
fn write_tmp(tmp: &Path, bytes: &[u8]) -> io::Result<()> {
let mut file = File::create(tmp)?;
file.write_all(bytes)?;
file.sync_all()?;
Ok(())
}
#[cfg(test)]
#[path = "atomic_tests.rs"]
mod atomic_tests;