Mercurial > public > mercurial-scm > hg
view rust/hg-core/src/repo.rs @ 46446:1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Differential Revision: https://phab.mercurial-scm.org/D9906
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Thu, 28 Jan 2021 20:31:42 +0100 |
parents | 43d63979a75e |
children | d03b0601e0eb |
line wrap: on
line source
use crate::errors::{HgError, IoResultExt}; use crate::requirements; use memmap::{Mmap, MmapOptions}; use std::path::{Path, PathBuf}; /// A repository on disk pub struct Repo { working_directory: PathBuf, dot_hg: PathBuf, store: PathBuf, } #[derive(Debug, derive_more::From)] pub enum RepoFindError { NotFoundInCurrentDirectoryOrAncestors { current_directory: PathBuf, }, #[from] Other(HgError), } /// Filesystem access abstraction for the contents of a given "base" diretory #[derive(Clone, Copy)] pub(crate) struct Vfs<'a> { base: &'a Path, } impl Repo { /// Search the current directory and its ancestores for a repository: /// a working directory that contains a `.hg` sub-directory. pub fn find() -> Result<Self, RepoFindError> { 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); } } Err(RepoFindError::NotFoundInCurrentDirectoryOrAncestors { current_directory, }) } pub fn working_directory_path(&self) -> &Path { &self.working_directory } /// For accessing repository files (in `.hg`), except for the store /// (`.hg/store`). pub(crate) fn hg_vfs(&self) -> Vfs<'_> { Vfs { base: &self.dot_hg } } /// For accessing repository store files (in `.hg/store`) pub(crate) fn store_vfs(&self) -> Vfs<'_> { Vfs { base: &self.store } } /// For accessing the working copy // The undescore prefix silences the "never used" warning. Remove before // using. pub(crate) fn _working_directory_vfs(&self) -> Vfs<'_> { Vfs { base: &self.working_directory, } } } impl Vfs<'_> { pub(crate) fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf { self.base.join(relative_path) } pub(crate) fn read( &self, relative_path: impl AsRef<Path>, ) -> Result<Vec<u8>, HgError> { let path = self.join(relative_path); std::fs::read(&path).for_file(&path) } pub(crate) fn mmap_open( &self, relative_path: impl AsRef<Path>, ) -> Result<Mmap, HgError> { let path = self.base.join(relative_path); let file = std::fs::File::open(&path).for_file(&path)?; // TODO: what are the safety requirements here? let mmap = unsafe { MmapOptions::new().map(&file) }.for_file(&path)?; Ok(mmap) } }