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 |
7 #[derive(Clone, Copy)] |
7 #[derive(Clone, Copy)] |
8 pub struct Vfs<'a> { |
8 pub struct Vfs<'a> { |
103 relative_link_path: impl AsRef<Path>, |
103 relative_link_path: impl AsRef<Path>, |
104 target_path: impl AsRef<Path>, |
104 target_path: impl AsRef<Path>, |
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 |
112 fn fs_metadata( |
133 fn fs_metadata( |
113 path: impl AsRef<Path>, |
134 path: impl AsRef<Path>, |