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 }