[Updated] D8609: hg-core: add FindRoot operation to find repository root path

acezar (Antoine Cezar) phabricator at mercurial-scm.org
Tue Jun 16 21:43:27 UTC 2020


Closed by commit rHG5965efb609b6: hg-core: add FindRoot operation to find repository root path (authored by acezar).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D8609?vs=21644&id=21650

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8609/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8609

AFFECTED FILES
  rust/hg-core/src/operations/find_root.rs
  rust/hg-core/src/operations/mod.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/operations/mod.rs b/rust/hg-core/src/operations/mod.rs
--- a/rust/hg-core/src/operations/mod.rs
+++ b/rust/hg-core/src/operations/mod.rs
@@ -1,3 +1,6 @@
+mod find_root;
+pub use find_root::{FindRoot, FindRootError, FindRootErrorKind};
+
 /// An interface for high-level hg operations.
 ///
 /// A distinction is made between operation and commands.
diff --git a/rust/hg-core/src/operations/find_root.rs b/rust/hg-core/src/operations/find_root.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/operations/find_root.rs
@@ -0,0 +1,124 @@
+use super::Operation;
+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),
+        }
+    }
+}
+
+impl<'a> Operation<PathBuf> for FindRoot<'a> {
+    type Error = FindRootError;
+
+    fn run(&self) -> Result<PathBuf, Self::Error> {
+        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.into());
+        }
+        let mut ancestors = current_dir.ancestors();
+        while let Some(parent) = ancestors.next() {
+            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 */



To: acezar, #hg-reviewers, Alphare
Cc: Alphare, marmoute, mercurial-patches
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-patches/attachments/20200616/216d31ab/attachment-0002.html>


More information about the Mercurial-patches mailing list