##// 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 /// Converts a `Result` with `std::io::Error` into one with `HgError`.
151 /// Converts a `Result` with `std::io::Error` into one with `HgError`.
152 fn when_reading_file(self, path: &std::path::Path) -> Result<T, HgError>;
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 fn with_context(
156 fn with_context(
155 self,
157 self,
156 context: impl FnOnce() -> IoErrorContext,
158 context: impl FnOnce() -> IoErrorContext,
@@ -162,6 +164,10 b' impl<T> IoResultExt<T> for std::io::Resu'
162 self.with_context(|| IoErrorContext::ReadingFile(path.to_owned()))
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 fn with_context(
171 fn with_context(
166 self,
172 self,
167 context: impl FnOnce() -> IoErrorContext,
173 context: impl FnOnce() -> IoErrorContext,
@@ -1,6 +1,6 b''
1 use crate::errors::{HgError, IoErrorContext, IoResultExt};
1 use crate::errors::{HgError, IoErrorContext, IoResultExt};
2 use memmap2::{Mmap, MmapOptions};
2 use memmap2::{Mmap, MmapOptions};
3 use std::io::ErrorKind;
3 use std::io::{ErrorKind, Write};
4 use std::path::{Path, PathBuf};
4 use std::path::{Path, PathBuf};
5
5
6 /// Filesystem access abstraction for the contents of a given "base" diretory
6 /// Filesystem access abstraction for the contents of a given "base" diretory
@@ -105,7 +105,28 b" impl Vfs<'_> {"
105 ) -> Result<(), HgError> {
105 ) -> Result<(), HgError> {
106 let link_path = self.join(relative_link_path);
106 let link_path = self.join(relative_link_path);
107 std::os::unix::fs::symlink(target_path, &link_path)
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