annotate rust/hg-core/src/operations/find_root.rs @ 45358:452ece5654c5

hg-core: remove the `Operation` trait There is no way to currently define a trait which can both return references to `self` and to passed data, which is what we would need. Generic Associated Types may fix this and allow us to have a unified interface. See: rust #44265 Differential Revision: https://phab.mercurial-scm.org/D8862
author Antoine Cezar <antoine.cezar@octobus.net>
date Wed, 29 Jul 2020 10:08:09 +0200
parents 5965efb609b6
children 3d9f1dfc52c2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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() {
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
59 return Ok(current_dir.into());
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
60 }
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
61 let mut ancestors = current_dir.ancestors();
5965efb609b6 hg-core: add FindRoot operation to find repository root path
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
62 while let Some(parent) = ancestors.next() {
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 */