Mercurial > hg
comparison rust/hg-core/src/repo.rs @ 46462:d03b0601e0eb
rhg: initial support for shared repositories
Differential Revision: https://phab.mercurial-scm.org/D9941
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Thu, 14 Jan 2021 13:04:12 +0100 |
parents | 1dcd9c9975ed |
children | 95b276283b67 |
comparison
equal
deleted
inserted
replaced
46461:f3f4d1b7dc97 | 46462:d03b0601e0eb |
---|---|
1 use crate::errors::{HgError, IoResultExt}; | 1 use crate::errors::{HgError, IoResultExt}; |
2 use crate::requirements; | 2 use crate::requirements; |
3 use crate::utils::files::get_path_from_bytes; | |
3 use memmap::{Mmap, MmapOptions}; | 4 use memmap::{Mmap, MmapOptions}; |
5 use std::collections::HashSet; | |
4 use std::path::{Path, PathBuf}; | 6 use std::path::{Path, PathBuf}; |
5 | 7 |
6 /// A repository on disk | 8 /// A repository on disk |
7 pub struct Repo { | 9 pub struct Repo { |
8 working_directory: PathBuf, | 10 working_directory: PathBuf, |
9 dot_hg: PathBuf, | 11 dot_hg: PathBuf, |
10 store: PathBuf, | 12 store: PathBuf, |
13 requirements: HashSet<String>, | |
11 } | 14 } |
12 | 15 |
13 #[derive(Debug, derive_more::From)] | 16 #[derive(Debug, derive_more::From)] |
14 pub enum RepoFindError { | 17 pub enum RepoFindError { |
15 NotFoundInCurrentDirectoryOrAncestors { | 18 NotFoundInCurrentDirectoryOrAncestors { |
30 /// a working directory that contains a `.hg` sub-directory. | 33 /// a working directory that contains a `.hg` sub-directory. |
31 pub fn find() -> Result<Self, RepoFindError> { | 34 pub fn find() -> Result<Self, RepoFindError> { |
32 let current_directory = crate::utils::current_dir()?; | 35 let current_directory = crate::utils::current_dir()?; |
33 // ancestors() is inclusive: it first yields `current_directory` as-is. | 36 // ancestors() is inclusive: it first yields `current_directory` as-is. |
34 for ancestor in current_directory.ancestors() { | 37 for ancestor in current_directory.ancestors() { |
35 let dot_hg = ancestor.join(".hg"); | 38 if ancestor.join(".hg").is_dir() { |
36 if dot_hg.is_dir() { | 39 return Ok(Self::new_at_path(ancestor.to_owned())?); |
37 let repo = Self { | |
38 store: dot_hg.join("store"), | |
39 dot_hg, | |
40 working_directory: ancestor.to_owned(), | |
41 }; | |
42 requirements::check(&repo)?; | |
43 return Ok(repo); | |
44 } | 40 } |
45 } | 41 } |
46 Err(RepoFindError::NotFoundInCurrentDirectoryOrAncestors { | 42 Err(RepoFindError::NotFoundInCurrentDirectoryOrAncestors { |
47 current_directory, | 43 current_directory, |
48 }) | 44 }) |
49 } | 45 } |
50 | 46 |
47 /// To be called after checking that `.hg` is a sub-directory | |
48 fn new_at_path(working_directory: PathBuf) -> Result<Self, HgError> { | |
49 let dot_hg = working_directory.join(".hg"); | |
50 let hg_vfs = Vfs { base: &dot_hg }; | |
51 let reqs = requirements::load_if_exists(hg_vfs)?; | |
52 let relative = | |
53 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT); | |
54 let shared = | |
55 reqs.contains(requirements::SHARED_REQUIREMENT) || relative; | |
56 let store_path; | |
57 if !shared { | |
58 store_path = dot_hg.join("store"); | |
59 } else { | |
60 let bytes = hg_vfs.read("sharedpath")?; | |
61 let mut shared_path = get_path_from_bytes(&bytes).to_owned(); | |
62 if relative { | |
63 shared_path = dot_hg.join(shared_path) | |
64 } | |
65 if !shared_path.is_dir() { | |
66 return Err(HgError::corrupted(format!( | |
67 ".hg/sharedpath points to nonexistent directory {}", | |
68 shared_path.display() | |
69 ))); | |
70 } | |
71 | |
72 store_path = shared_path.join("store"); | |
73 } | |
74 | |
75 let repo = Self { | |
76 requirements: reqs, | |
77 working_directory, | |
78 store: store_path, | |
79 dot_hg, | |
80 }; | |
81 | |
82 requirements::check(&repo)?; | |
83 | |
84 Ok(repo) | |
85 } | |
86 | |
51 pub fn working_directory_path(&self) -> &Path { | 87 pub fn working_directory_path(&self) -> &Path { |
52 &self.working_directory | 88 &self.working_directory |
89 } | |
90 | |
91 pub fn requirements(&self) -> &HashSet<String> { | |
92 &self.requirements | |
53 } | 93 } |
54 | 94 |
55 /// For accessing repository files (in `.hg`), except for the store | 95 /// For accessing repository files (in `.hg`), except for the store |
56 /// (`.hg/store`). | 96 /// (`.hg/store`). |
57 pub(crate) fn hg_vfs(&self) -> Vfs<'_> { | 97 pub(crate) fn hg_vfs(&self) -> Vfs<'_> { |