diff --git a/crates/paths/Cargo.toml b/crates/paths/Cargo.toml index c293807a35e..49dd1bbdece 100644 --- a/crates/paths/Cargo.toml +++ b/crates/paths/Cargo.toml @@ -12,6 +12,7 @@ chrono = { workspace = true, features = ["now"] } fs2.workspace = true itoa.workspace = true serde.workspace = true +tempfile.workspace = true thiserror.workspace = true [target.'cfg(windows)'.dependencies] @@ -21,8 +22,5 @@ junction.workspace = true [target.'cfg(not(windows))'.dependencies] xdg.workspace = true -[dev-dependencies] -tempfile.workspace = true - [lints] workspace = true diff --git a/crates/paths/src/utils.rs b/crates/paths/src/utils.rs index a03a9b87d9c..326ba795775 100644 --- a/crates/paths/src/utils.rs +++ b/crates/paths/src/utils.rs @@ -104,8 +104,23 @@ macro_rules! path_type { } pub fn write(&self, contents: impl AsRef<[u8]>) -> std::io::Result<()> { - self.create_parent()?; - std::fs::write(self, contents) + use std::io::Write as _; + + let path = self.0.canonicalize()?; + let parent = path.parent().ok_or_else(|| + std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("cannot replace {} without enclosing directory", path.display())) + )?; + std::fs::create_dir_all(&path)?; + + let mut tmp = tempfile::NamedTempFile::new_in(parent)?; + tmp.write_all(contents.as_ref())?; + tmp.as_file().sync_all()?; + tmp.persist(&path)?; + std::fs::File::open(parent)?.sync_all()?; + + Ok(()) } /// Opens a file at this path with the given options, ensuring its parent directory exists.