Mercurial > hg
comparison rust/hg-core/src/repo.rs @ 46167:8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
This is similar to the corresponding Python classes.
Repo represents a repository and knows the path to the `.hg` directory,
the `store` directory, and the working directory.
Separating these will enable supporting the share extension.
A Vfs is created from a Repo for one of these three directories.
It has filesystem access APIs that take a relative std::path::Path
as a parameter.
Differential Revision: https://phab.mercurial-scm.org/D9596
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Mon, 14 Dec 2020 16:33:15 +0100 |
parents | |
children | 02d3bb972121 |
comparison
equal
deleted
inserted
replaced
46166:c511fef30290 | 46167:8a4914397d02 |
---|---|
1 use crate::operations::{find_root, FindRootError}; | |
2 use crate::requirements; | |
3 use memmap::{Mmap, MmapOptions}; | |
4 use std::path::{Path, PathBuf}; | |
5 | |
6 /// A repository on disk | |
7 pub struct Repo { | |
8 working_directory: PathBuf, | |
9 dot_hg: PathBuf, | |
10 store: PathBuf, | |
11 } | |
12 | |
13 /// Filesystem access abstraction for the contents of a given "base" diretory | |
14 #[derive(Clone, Copy)] | |
15 pub(crate) struct Vfs<'a> { | |
16 base: &'a Path, | |
17 } | |
18 | |
19 impl Repo { | |
20 /// Returns `None` if the given path doesn’t look like a repository | |
21 /// (doesn’t contain a `.hg` sub-directory). | |
22 pub fn for_path(root: impl Into<PathBuf>) -> Self { | |
23 let working_directory = root.into(); | |
24 let dot_hg = working_directory.join(".hg"); | |
25 Self { | |
26 store: dot_hg.join("store"), | |
27 dot_hg, | |
28 working_directory, | |
29 } | |
30 } | |
31 | |
32 pub fn find() -> Result<Self, FindRootError> { | |
33 find_root().map(Self::for_path) | |
34 } | |
35 | |
36 pub fn check_requirements( | |
37 &self, | |
38 ) -> Result<(), requirements::RequirementsError> { | |
39 requirements::check(self) | |
40 } | |
41 | |
42 pub fn working_directory_path(&self) -> &Path { | |
43 &self.working_directory | |
44 } | |
45 | |
46 /// For accessing repository files (in `.hg`), except for the store | |
47 /// (`.hg/store`). | |
48 pub(crate) fn hg_vfs(&self) -> Vfs<'_> { | |
49 Vfs { base: &self.dot_hg } | |
50 } | |
51 | |
52 /// For accessing repository store files (in `.hg/store`) | |
53 pub(crate) fn store_vfs(&self) -> Vfs<'_> { | |
54 Vfs { base: &self.store } | |
55 } | |
56 | |
57 /// For accessing the working copy | |
58 | |
59 // The undescore prefix silences the "never used" warning. Remove before | |
60 // using. | |
61 pub(crate) fn _working_directory_vfs(&self) -> Vfs<'_> { | |
62 Vfs { | |
63 base: &self.working_directory, | |
64 } | |
65 } | |
66 } | |
67 | |
68 impl Vfs<'_> { | |
69 pub(crate) fn read( | |
70 &self, | |
71 relative_path: impl AsRef<Path>, | |
72 ) -> std::io::Result<Vec<u8>> { | |
73 std::fs::read(self.base.join(relative_path)) | |
74 } | |
75 | |
76 pub(crate) fn open( | |
77 &self, | |
78 relative_path: impl AsRef<Path>, | |
79 ) -> std::io::Result<std::fs::File> { | |
80 std::fs::File::open(self.base.join(relative_path)) | |
81 } | |
82 | |
83 pub(crate) fn mmap_open( | |
84 &self, | |
85 relative_path: impl AsRef<Path>, | |
86 ) -> std::io::Result<Mmap> { | |
87 let file = self.open(relative_path)?; | |
88 // TODO: what are the safety requirements here? | |
89 let mmap = unsafe { MmapOptions::new().map(&file) }?; | |
90 Ok(mmap) | |
91 } | |
92 } |