1 use crate::config::{Config, ConfigError, ConfigParseError}; |
1 use crate::config::{Config, ConfigError, ConfigParseError}; |
2 use crate::errors::{HgError, IoResultExt}; |
2 use crate::errors::{HgError, IoErrorContext, IoResultExt}; |
3 use crate::requirements; |
3 use crate::requirements; |
4 use crate::utils::current_dir; |
4 use crate::utils::current_dir; |
5 use crate::utils::files::get_path_from_bytes; |
5 use crate::utils::files::get_path_from_bytes; |
6 use memmap::{Mmap, MmapOptions}; |
6 use memmap::{Mmap, MmapOptions}; |
7 use std::collections::HashSet; |
7 use std::collections::HashSet; |
36 } |
36 } |
37 } |
37 } |
38 |
38 |
39 /// Filesystem access abstraction for the contents of a given "base" diretory |
39 /// Filesystem access abstraction for the contents of a given "base" diretory |
40 #[derive(Clone, Copy)] |
40 #[derive(Clone, Copy)] |
41 pub(crate) struct Vfs<'a> { |
41 pub struct Vfs<'a> { |
42 base: &'a Path, |
42 pub(crate) base: &'a Path, |
43 } |
43 } |
44 |
44 |
45 impl Repo { |
45 impl Repo { |
46 /// Find a repository, either at the given path (which must contain a `.hg` |
46 /// Find a repository, either at the given path (which must contain a `.hg` |
47 /// sub-directory) or by searching the current directory and its |
47 /// sub-directory) or by searching the current directory and its |
194 &self.config |
194 &self.config |
195 } |
195 } |
196 |
196 |
197 /// For accessing repository files (in `.hg`), except for the store |
197 /// For accessing repository files (in `.hg`), except for the store |
198 /// (`.hg/store`). |
198 /// (`.hg/store`). |
199 pub(crate) fn hg_vfs(&self) -> Vfs<'_> { |
199 pub fn hg_vfs(&self) -> Vfs<'_> { |
200 Vfs { base: &self.dot_hg } |
200 Vfs { base: &self.dot_hg } |
201 } |
201 } |
202 |
202 |
203 /// For accessing repository store files (in `.hg/store`) |
203 /// For accessing repository store files (in `.hg/store`) |
204 pub(crate) fn store_vfs(&self) -> Vfs<'_> { |
204 pub fn store_vfs(&self) -> Vfs<'_> { |
205 Vfs { base: &self.store } |
205 Vfs { base: &self.store } |
206 } |
206 } |
207 |
207 |
208 /// For accessing the working copy |
208 /// For accessing the working copy |
209 |
209 |
210 // The undescore prefix silences the "never used" warning. Remove before |
210 // The undescore prefix silences the "never used" warning. Remove before |
211 // using. |
211 // using. |
212 pub(crate) fn _working_directory_vfs(&self) -> Vfs<'_> { |
212 pub fn _working_directory_vfs(&self) -> Vfs<'_> { |
213 Vfs { |
213 Vfs { |
214 base: &self.working_directory, |
214 base: &self.working_directory, |
215 } |
215 } |
216 } |
216 } |
217 } |
217 } |
218 |
218 |
219 impl Vfs<'_> { |
219 impl Vfs<'_> { |
220 pub(crate) fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf { |
220 pub fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf { |
221 self.base.join(relative_path) |
221 self.base.join(relative_path) |
222 } |
222 } |
223 |
223 |
224 pub(crate) fn read( |
224 pub fn read( |
225 &self, |
225 &self, |
226 relative_path: impl AsRef<Path>, |
226 relative_path: impl AsRef<Path>, |
227 ) -> Result<Vec<u8>, HgError> { |
227 ) -> Result<Vec<u8>, HgError> { |
228 let path = self.join(relative_path); |
228 let path = self.join(relative_path); |
229 std::fs::read(&path).for_file(&path) |
229 std::fs::read(&path).when_reading_file(&path) |
230 } |
230 } |
231 |
231 |
232 pub(crate) fn mmap_open( |
232 pub fn mmap_open( |
233 &self, |
233 &self, |
234 relative_path: impl AsRef<Path>, |
234 relative_path: impl AsRef<Path>, |
235 ) -> Result<Mmap, HgError> { |
235 ) -> Result<Mmap, HgError> { |
236 let path = self.base.join(relative_path); |
236 let path = self.base.join(relative_path); |
237 let file = std::fs::File::open(&path).for_file(&path)?; |
237 let file = std::fs::File::open(&path).when_reading_file(&path)?; |
238 // TODO: what are the safety requirements here? |
238 // TODO: what are the safety requirements here? |
239 let mmap = unsafe { MmapOptions::new().map(&file) }.for_file(&path)?; |
239 let mmap = unsafe { MmapOptions::new().map(&file) } |
|
240 .when_reading_file(&path)?; |
240 Ok(mmap) |
241 Ok(mmap) |
241 } |
242 } |
242 } |
243 |
|
244 pub fn rename( |
|
245 &self, |
|
246 relative_from: impl AsRef<Path>, |
|
247 relative_to: impl AsRef<Path>, |
|
248 ) -> Result<(), HgError> { |
|
249 let from = self.join(relative_from); |
|
250 let to = self.join(relative_to); |
|
251 std::fs::rename(&from, &to) |
|
252 .with_context(|| IoErrorContext::RenamingFile { from, to }) |
|
253 } |
|
254 } |