use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
use anyhow::{Context, Result};
use fs2::FileExt;
use tempfile::NamedTempFile;
pub fn atomic_write(path: &Path, bytes: &[u8]) -> Result<()> {
let parent = path
.parent()
.filter(|p| !p.as_os_str().is_empty())
.unwrap_or_else(|| Path::new("."));
std::fs::create_dir_all(parent)?;
let mut temp = NamedTempFile::new_in(parent)?;
if let Ok(metadata) = std::fs::metadata(path) {
temp.as_file().set_permissions(metadata.permissions())?;
}
temp.write_all(bytes)?;
temp.as_file().sync_all()?;
temp.persist(path)
.with_context(|| format!("replacing {}", path.display()))?;
#[cfg(unix)]
File::open(parent)?.sync_all()?;
Ok(())
}
pub fn lock(path: &Path) -> Result<File> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
let file = OpenOptions::new()
.create(true)
.truncate(false)
.write(true)
.open(path)?;
file.lock_exclusive()?;
Ok(file)
}