Mercurial > public > mercurial-scm > hg-stable
diff rust/hg-core/src/repo.rs @ 46524: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 |
line wrap: on
line diff
--- a/rust/hg-core/src/repo.rs Mon Feb 01 19:30:28 2021 +0100 +++ b/rust/hg-core/src/repo.rs Thu Jan 14 13:04:12 2021 +0100 @@ -1,6 +1,8 @@ use crate::errors::{HgError, IoResultExt}; use crate::requirements; +use crate::utils::files::get_path_from_bytes; use memmap::{Mmap, MmapOptions}; +use std::collections::HashSet; use std::path::{Path, PathBuf}; /// A repository on disk @@ -8,6 +10,7 @@ working_directory: PathBuf, dot_hg: PathBuf, store: PathBuf, + requirements: HashSet<String>, } #[derive(Debug, derive_more::From)] @@ -32,15 +35,8 @@ let current_directory = crate::utils::current_dir()?; // ancestors() is inclusive: it first yields `current_directory` as-is. for ancestor in current_directory.ancestors() { - let dot_hg = ancestor.join(".hg"); - if dot_hg.is_dir() { - let repo = Self { - store: dot_hg.join("store"), - dot_hg, - working_directory: ancestor.to_owned(), - }; - requirements::check(&repo)?; - return Ok(repo); + if ancestor.join(".hg").is_dir() { + return Ok(Self::new_at_path(ancestor.to_owned())?); } } Err(RepoFindError::NotFoundInCurrentDirectoryOrAncestors { @@ -48,10 +44,54 @@ }) } + /// To be called after checking that `.hg` is a sub-directory + fn new_at_path(working_directory: PathBuf) -> Result<Self, HgError> { + let dot_hg = working_directory.join(".hg"); + let hg_vfs = Vfs { base: &dot_hg }; + let reqs = requirements::load_if_exists(hg_vfs)?; + let relative = + reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT); + let shared = + reqs.contains(requirements::SHARED_REQUIREMENT) || relative; + let store_path; + if !shared { + store_path = dot_hg.join("store"); + } else { + let bytes = hg_vfs.read("sharedpath")?; + let mut shared_path = get_path_from_bytes(&bytes).to_owned(); + if relative { + shared_path = dot_hg.join(shared_path) + } + if !shared_path.is_dir() { + return Err(HgError::corrupted(format!( + ".hg/sharedpath points to nonexistent directory {}", + shared_path.display() + ))); + } + + store_path = shared_path.join("store"); + } + + let repo = Self { + requirements: reqs, + working_directory, + store: store_path, + dot_hg, + }; + + requirements::check(&repo)?; + + Ok(repo) + } + pub fn working_directory_path(&self) -> &Path { &self.working_directory } + pub fn requirements(&self) -> &HashSet<String> { + &self.requirements + } + /// For accessing repository files (in `.hg`), except for the store /// (`.hg/store`). pub(crate) fn hg_vfs(&self) -> Vfs<'_> {