Mercurial > public > mercurial-scm > hg
view rust/hg-core/src/operations/find_root.rs @ 45944:595979dc924e
copies: introduce a basic Rust function for `combine_changeset_copies`
This new function mirror the python code. This first implementation does a lot
of data copies and is therefore quite slow. However my goal here is to create a
simple "frame" from where to start adding optimization.
This patch focus on the `hg-core` part of this work. Coming patches will do the
necessary `hg-cpython` work to be able to use this from Python.
Differential Revision: https://phab.mercurial-scm.org/D9297
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 01 Oct 2020 18:51:06 +0200 |
parents | 3d9f1dfc52c2 |
children | dca9cb99971c |
line wrap: on
line source
use std::fmt; use std::path::{Path, PathBuf}; /// Kind of error encoutered by FindRoot #[derive(Debug)] pub enum FindRootErrorKind { /// Root of the repository has not been found /// Contains the current directory used by FindRoot RootNotFound(PathBuf), /// The current directory does not exists or permissions are insufficient /// to get access to it GetCurrentDirError(std::io::Error), } /// A FindRoot error #[derive(Debug)] pub struct FindRootError { /// Kind of error encoutered by FindRoot pub kind: FindRootErrorKind, } impl std::error::Error for FindRootError {} impl fmt::Display for FindRootError { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { unimplemented!() } } /// Find the root of the repository /// by searching for a .hg directory in the current directory and its /// ancestors pub struct FindRoot<'a> { current_dir: Option<&'a Path>, } impl<'a> FindRoot<'a> { pub fn new() -> Self { Self { current_dir: None } } pub fn new_from_path(current_dir: &'a Path) -> Self { Self { current_dir: Some(current_dir), } } pub fn run(&self) -> Result<PathBuf, FindRootError> { let current_dir = match self.current_dir { None => std::env::current_dir().or_else(|e| { Err(FindRootError { kind: FindRootErrorKind::GetCurrentDirError(e), }) })?, Some(path) => path.into(), }; if current_dir.join(".hg").exists() { return Ok(current_dir); } let ancestors = current_dir.ancestors(); for parent in ancestors { if parent.join(".hg").exists() { return Ok(parent.into()); } } Err(FindRootError { kind: FindRootErrorKind::RootNotFound(current_dir.to_path_buf()), }) } } #[cfg(test)] mod tests { use super::*; use std::fs; use tempfile; #[test] fn dot_hg_not_found() { let tmp_dir = tempfile::tempdir().unwrap(); let path = tmp_dir.path(); let err = FindRoot::new_from_path(&path).run().unwrap_err(); // TODO do something better assert!(match err { FindRootError { kind } => match kind { FindRootErrorKind::RootNotFound(p) => p == path.to_path_buf(), _ => false, }, }) } #[test] fn dot_hg_in_current_path() { let tmp_dir = tempfile::tempdir().unwrap(); let root = tmp_dir.path(); fs::create_dir_all(root.join(".hg")).unwrap(); let result = FindRoot::new_from_path(&root).run().unwrap(); assert_eq!(result, root) } #[test] fn dot_hg_in_parent() { let tmp_dir = tempfile::tempdir().unwrap(); let root = tmp_dir.path(); fs::create_dir_all(root.join(".hg")).unwrap(); let result = FindRoot::new_from_path(&root.join("some/nested/directory")) .run() .unwrap(); assert_eq!(result, root) } } /* tests */