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 |
.w |
|
|
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