##// END OF EJS Templates
rust: Add Vfs::write_atomic...
Simon Sapin -
r49246:abeae090 default
parent child Browse files
Show More
@@ -151,6 +151,8 b' pub trait IoResultExt<T> {'
151 151 /// Converts a `Result` with `std::io::Error` into one with `HgError`.
152 152 fn when_reading_file(self, path: &std::path::Path) -> Result<T, HgError>;
153 153
154 fn when_writing_file(self, path: &std::path::Path) -> Result<T, HgError>;
155
154 156 fn with_context(
155 157 self,
156 158 context: impl FnOnce() -> IoErrorContext,
@@ -162,6 +164,10 b' impl<T> IoResultExt<T> for std::io::Resu'
162 164 self.with_context(|| IoErrorContext::ReadingFile(path.to_owned()))
163 165 }
164 166
167 fn when_writing_file(self, path: &std::path::Path) -> Result<T, HgError> {
168 self.with_context(|| IoErrorContext::WritingFile(path.to_owned()))
169 }
170
165 171 fn with_context(
166 172 self,
167 173 context: impl FnOnce() -> IoErrorContext,
@@ -1,6 +1,6 b''
1 1 use crate::errors::{HgError, IoErrorContext, IoResultExt};
2 2 use memmap2::{Mmap, MmapOptions};
3 use std::io::ErrorKind;
3 use std::io::{ErrorKind, Write};
4 4 use std::path::{Path, PathBuf};
5 5
6 6 /// Filesystem access abstraction for the contents of a given "base" diretory
@@ -105,7 +105,28 b" impl Vfs<'_> {"
105 105 ) -> Result<(), HgError> {
106 106 let link_path = self.join(relative_link_path);
107 107 std::os::unix::fs::symlink(target_path, &link_path)
108 .with_context(|| IoErrorContext::WritingFile(link_path))
108 .when_writing_file(&link_path)
109 }
110
111 /// Write `contents` into a temporary file, then rename to `relative_path`.
112 /// This makes writing to a file "atomic": a reader opening that path will
113 /// see either the previous contents of the file or the complete new
114 /// content, never a partial write.
115 pub fn atomic_write(
116 &self,
117 relative_path: impl AsRef<Path>,
118 contents: &[u8],
119 ) -> Result<(), HgError> {
120 let mut tmp = tempfile::NamedTempFile::new_in(self.base)
121 .when_writing_file(self.base)?;
122 tmp.write_all(contents)
123 .and_then(|()| tmp.flush())
124 .when_writing_file(tmp.path())?;
125 let path = self.join(relative_path);
126 tmp.persist(&path)
127 .map_err(|e| e.error)
128 .when_writing_file(&path)?;
129 Ok(())
109 130 }
110 131 }
111 132
General Comments 0
You need to be logged in to leave comments. Login now