author | Simon Sapin <simon.sapin@octobus.net> |
Thu, 28 Jan 2021 20:31:42 +0100 | |
changeset 46446 | 1dcd9c9975ed |
parent 46443 | 43d63979a75e |
child 46462 | d03b0601e0eb |
permissions | -rw-r--r-- |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46442
diff
changeset
|
1 |
use crate::errors::{HgError, IoResultExt}; |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
2 |
use crate::requirements; |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
3 |
use memmap::{Mmap, MmapOptions}; |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
4 |
use std::path::{Path, PathBuf}; |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
5 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
6 |
/// A repository on disk |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
7 |
pub struct Repo { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
8 |
working_directory: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
9 |
dot_hg: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
10 |
store: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
11 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
12 |
|
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
13 |
#[derive(Debug, derive_more::From)] |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
14 |
pub enum RepoFindError { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
15 |
NotFoundInCurrentDirectoryOrAncestors { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
16 |
current_directory: PathBuf, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
17 |
}, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
18 |
#[from] |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
19 |
Other(HgError), |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
20 |
} |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
21 |
|
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
22 |
/// Filesystem access abstraction for the contents of a given "base" diretory |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
23 |
#[derive(Clone, Copy)] |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
24 |
pub(crate) struct Vfs<'a> { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
25 |
base: &'a Path, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
26 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
27 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
28 |
impl Repo { |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
29 |
/// Search the current directory and its ancestores for a repository: |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
30 |
/// a working directory that contains a `.hg` sub-directory. |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
31 |
pub fn find() -> Result<Self, RepoFindError> { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
32 |
let current_directory = crate::utils::current_dir()?; |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
33 |
// ancestors() is inclusive: it first yields `current_directory` as-is. |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
34 |
for ancestor in current_directory.ancestors() { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
35 |
let dot_hg = ancestor.join(".hg"); |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
36 |
if dot_hg.is_dir() { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
37 |
let repo = Self { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
38 |
store: dot_hg.join("store"), |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
39 |
dot_hg, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
40 |
working_directory: ancestor.to_owned(), |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
41 |
}; |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
42 |
requirements::check(&repo)?; |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
43 |
return Ok(repo); |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
44 |
} |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
45 |
} |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
46 |
Err(RepoFindError::NotFoundInCurrentDirectoryOrAncestors { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
47 |
current_directory, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
48 |
}) |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
49 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
50 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
51 |
pub fn working_directory_path(&self) -> &Path { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
52 |
&self.working_directory |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
53 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
54 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
55 |
/// For accessing repository files (in `.hg`), except for the store |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
56 |
/// (`.hg/store`). |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
57 |
pub(crate) fn hg_vfs(&self) -> Vfs<'_> { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
58 |
Vfs { base: &self.dot_hg } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
59 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
60 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
61 |
/// For accessing repository store files (in `.hg/store`) |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
62 |
pub(crate) fn store_vfs(&self) -> Vfs<'_> { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
63 |
Vfs { base: &self.store } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
64 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
65 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
66 |
/// For accessing the working copy |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
67 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
68 |
// The undescore prefix silences the "never used" warning. Remove before |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
69 |
// using. |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
70 |
pub(crate) fn _working_directory_vfs(&self) -> Vfs<'_> { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
71 |
Vfs { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
72 |
base: &self.working_directory, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
73 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
74 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
75 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
76 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
77 |
impl Vfs<'_> { |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
78 |
pub(crate) fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf { |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
79 |
self.base.join(relative_path) |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
80 |
} |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
81 |
|
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
82 |
pub(crate) fn read( |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
83 |
&self, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
84 |
relative_path: impl AsRef<Path>, |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46442
diff
changeset
|
85 |
) -> Result<Vec<u8>, HgError> { |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
86 |
let path = self.join(relative_path); |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46442
diff
changeset
|
87 |
std::fs::read(&path).for_file(&path) |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
88 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
89 |
|
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
90 |
pub(crate) fn mmap_open( |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
91 |
&self, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
92 |
relative_path: impl AsRef<Path>, |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46442
diff
changeset
|
93 |
) -> Result<Mmap, HgError> { |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46442
diff
changeset
|
94 |
let path = self.base.join(relative_path); |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46442
diff
changeset
|
95 |
let file = std::fs::File::open(&path).for_file(&path)?; |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
96 |
// TODO: what are the safety requirements here? |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46442
diff
changeset
|
97 |
let mmap = unsafe { MmapOptions::new().map(&file) }.for_file(&path)?; |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
98 |
Ok(mmap) |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
99 |
} |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
100 |
} |