use std::io::Write;
use std::path::Path;
pub(crate) fn atomic_write(path: &Path, contents: &[u8]) -> std::io::Result<()> {
let parent = path.parent().ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"path has no parent directory",
)
})?;
std::fs::create_dir_all(parent)?;
let mut tmp = tempfile::NamedTempFile::new_in(parent)?;
tmp.write_all(contents)?;
tmp.persist(path).map_err(|e| e.error)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn writes_and_replaces_contents() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("nested").join("file.txt");
atomic_write(&path, b"one").unwrap();
assert_eq!(std::fs::read(&path).unwrap(), b"one");
atomic_write(&path, b"two").unwrap();
assert_eq!(std::fs::read(&path).unwrap(), b"two");
assert_eq!(
std::fs::read_dir(path.parent().unwrap()).unwrap().count(),
1
);
}
}