rust/hg-core/src/operations/find_root.rs
author Antoine Cezar <antoine.cezar@octobus.net>
Mon, 17 Aug 2020 10:59:30 +0200
changeset 45441 3d9f1dfc52c2
parent 45358 452ece5654c5
child 46135 dca9cb99971c
permissions -rw-r--r--
hg-core: fix some `clippy` warnings Differential Revision: https://phab.mercurial-scm.org/D8957
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
44980
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     1
use std::fmt;
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     2
use std::path::{Path, PathBuf};
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     3
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     4
/// Kind of error encoutered by FindRoot
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     5
#[derive(Debug)]
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     6
pub enum FindRootErrorKind {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     7
    /// Root of the repository has not been found
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     8
    /// Contains the current directory used by FindRoot
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     9
    RootNotFound(PathBuf),
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    10
    /// The current directory does not exists or permissions are insufficient
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    11
    /// to get access to it
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    12
    GetCurrentDirError(std::io::Error),
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    13
}
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    14
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    15
/// A FindRoot error
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    16
#[derive(Debug)]
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    17
pub struct FindRootError {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    18
    /// Kind of error encoutered by FindRoot
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    19
    pub kind: FindRootErrorKind,
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    20
}
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    21
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    22
impl std::error::Error for FindRootError {}
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    23
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    24
impl fmt::Display for FindRootError {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    25
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    26
        unimplemented!()
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    27
    }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    28
}
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    29
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    30
/// Find the root of the repository
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    31
/// by searching for a .hg directory in the current directory and its
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    32
/// ancestors
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    33
pub struct FindRoot<'a> {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    34
    current_dir: Option<&'a Path>,
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    35
}
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    36
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    37
impl<'a> FindRoot<'a> {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    38
    pub fn new() -> Self {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    39
        Self { current_dir: None }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    40
    }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    41
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    42
    pub fn new_from_path(current_dir: &'a Path) -> Self {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    43
        Self {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    44
            current_dir: Some(current_dir),
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    45
        }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    46
    }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    47
45358
452ece5654c5 hg-core: remove the `Operation` trait
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44980
diff changeset
    48
    pub fn run(&self) -> Result<PathBuf, FindRootError> {
44980
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    49
        let current_dir = match self.current_dir {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    50
            None => std::env::current_dir().or_else(|e| {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    51
                Err(FindRootError {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    52
                    kind: FindRootErrorKind::GetCurrentDirError(e),
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    53
                })
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    54
            })?,
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    55
            Some(path) => path.into(),
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    56
        };
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    57
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    58
        if current_dir.join(".hg").exists() {
45441
3d9f1dfc52c2 hg-core: fix some `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45358
diff changeset
    59
            return Ok(current_dir);
44980
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    60
        }
45441
3d9f1dfc52c2 hg-core: fix some `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45358
diff changeset
    61
        let ancestors = current_dir.ancestors();
3d9f1dfc52c2 hg-core: fix some `clippy` warnings
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45358
diff changeset
    62
        for parent in ancestors {
44980
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    63
            if parent.join(".hg").exists() {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    64
                return Ok(parent.into());
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    65
            }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    66
        }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    67
        Err(FindRootError {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    68
            kind: FindRootErrorKind::RootNotFound(current_dir.to_path_buf()),
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    69
        })
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    70
    }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    71
}
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    72
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    73
#[cfg(test)]
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    74
mod tests {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    75
    use super::*;
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    76
    use std::fs;
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    77
    use tempfile;
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    78
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    79
    #[test]
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    80
    fn dot_hg_not_found() {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    81
        let tmp_dir = tempfile::tempdir().unwrap();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    82
        let path = tmp_dir.path();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    83
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    84
        let err = FindRoot::new_from_path(&path).run().unwrap_err();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    85
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    86
        // TODO do something better
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    87
        assert!(match err {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    88
            FindRootError { kind } => match kind {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    89
                FindRootErrorKind::RootNotFound(p) => p == path.to_path_buf(),
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    90
                _ => false,
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    91
            },
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    92
        })
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    93
    }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    94
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    95
    #[test]
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    96
    fn dot_hg_in_current_path() {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    97
        let tmp_dir = tempfile::tempdir().unwrap();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    98
        let root = tmp_dir.path();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    99
        fs::create_dir_all(root.join(".hg")).unwrap();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   100
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   101
        let result = FindRoot::new_from_path(&root).run().unwrap();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   102
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   103
        assert_eq!(result, root)
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   104
    }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   105
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   106
    #[test]
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   107
    fn dot_hg_in_parent() {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   108
        let tmp_dir = tempfile::tempdir().unwrap();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   109
        let root = tmp_dir.path();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   110
        fs::create_dir_all(root.join(".hg")).unwrap();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   111
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   112
        let result =
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   113
            FindRoot::new_from_path(&root.join("some/nested/directory"))
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   114
                .run()
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   115
                .unwrap();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   116
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   117
        assert_eq!(result, root)
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   118
    }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   119
} /* tests */