Show More
@@ -1,119 +1,119 b'' | |||||
1 | use std::fmt; |
|
1 | use std::fmt; | |
2 | use std::path::{Path, PathBuf}; |
|
2 | use std::path::{Path, PathBuf}; | |
3 |
|
3 | |||
4 | /// Kind of error encoutered by FindRoot |
|
4 | /// Kind of error encoutered by FindRoot | |
5 | #[derive(Debug)] |
|
5 | #[derive(Debug)] | |
6 | pub enum FindRootErrorKind { |
|
6 | pub enum FindRootErrorKind { | |
7 | /// Root of the repository has not been found |
|
7 | /// Root of the repository has not been found | |
8 | /// Contains the current directory used by FindRoot |
|
8 | /// Contains the current directory used by FindRoot | |
9 | RootNotFound(PathBuf), |
|
9 | RootNotFound(PathBuf), | |
10 | /// The current directory does not exists or permissions are insufficient |
|
10 | /// The current directory does not exists or permissions are insufficient | |
11 | /// to get access to it |
|
11 | /// to get access to it | |
12 | GetCurrentDirError(std::io::Error), |
|
12 | GetCurrentDirError(std::io::Error), | |
13 | } |
|
13 | } | |
14 |
|
14 | |||
15 | /// A FindRoot error |
|
15 | /// A FindRoot error | |
16 | #[derive(Debug)] |
|
16 | #[derive(Debug)] | |
17 | pub struct FindRootError { |
|
17 | pub struct FindRootError { | |
18 | /// Kind of error encoutered by FindRoot |
|
18 | /// Kind of error encoutered by FindRoot | |
19 | pub kind: FindRootErrorKind, |
|
19 | pub kind: FindRootErrorKind, | |
20 | } |
|
20 | } | |
21 |
|
21 | |||
22 | impl std::error::Error for FindRootError {} |
|
22 | impl std::error::Error for FindRootError {} | |
23 |
|
23 | |||
24 | impl fmt::Display for FindRootError { |
|
24 | impl fmt::Display for FindRootError { | |
25 | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { |
|
25 | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
26 | unimplemented!() |
|
26 | unimplemented!() | |
27 | } |
|
27 | } | |
28 | } |
|
28 | } | |
29 |
|
29 | |||
30 | /// Find the root of the repository |
|
30 | /// Find the root of the repository | |
31 | /// by searching for a .hg directory in the current directory and its |
|
31 | /// by searching for a .hg directory in the current directory and its | |
32 | /// ancestors |
|
32 | /// ancestors | |
33 | pub struct FindRoot<'a> { |
|
33 | pub struct FindRoot<'a> { | |
34 | current_dir: Option<&'a Path>, |
|
34 | current_dir: Option<&'a Path>, | |
35 | } |
|
35 | } | |
36 |
|
36 | |||
37 | impl<'a> FindRoot<'a> { |
|
37 | impl<'a> FindRoot<'a> { | |
38 | pub fn new() -> Self { |
|
38 | pub fn new() -> Self { | |
39 | Self { current_dir: None } |
|
39 | Self { current_dir: None } | |
40 | } |
|
40 | } | |
41 |
|
41 | |||
42 | pub fn new_from_path(current_dir: &'a Path) -> Self { |
|
42 | pub fn new_from_path(current_dir: &'a Path) -> Self { | |
43 | Self { |
|
43 | Self { | |
44 | current_dir: Some(current_dir), |
|
44 | current_dir: Some(current_dir), | |
45 | } |
|
45 | } | |
46 | } |
|
46 | } | |
47 |
|
47 | |||
48 | pub fn run(&self) -> Result<PathBuf, FindRootError> { |
|
48 | pub fn run(&self) -> Result<PathBuf, FindRootError> { | |
49 | let current_dir = match self.current_dir { |
|
49 | let current_dir = match self.current_dir { | |
50 | None => std::env::current_dir().or_else(|e| { |
|
50 | None => std::env::current_dir().or_else(|e| { | |
51 | Err(FindRootError { |
|
51 | Err(FindRootError { | |
52 | kind: FindRootErrorKind::GetCurrentDirError(e), |
|
52 | kind: FindRootErrorKind::GetCurrentDirError(e), | |
53 | }) |
|
53 | }) | |
54 | })?, |
|
54 | })?, | |
55 | Some(path) => path.into(), |
|
55 | Some(path) => path.into(), | |
56 | }; |
|
56 | }; | |
57 |
|
57 | |||
58 | if current_dir.join(".hg").exists() { |
|
58 | if current_dir.join(".hg").exists() { | |
59 |
return Ok(current_dir |
|
59 | return Ok(current_dir); | |
60 | } |
|
60 | } | |
61 |
let |
|
61 | let ancestors = current_dir.ancestors(); | |
62 |
|
|
62 | for parent in ancestors { | |
63 | if parent.join(".hg").exists() { |
|
63 | if parent.join(".hg").exists() { | |
64 | return Ok(parent.into()); |
|
64 | return Ok(parent.into()); | |
65 | } |
|
65 | } | |
66 | } |
|
66 | } | |
67 | Err(FindRootError { |
|
67 | Err(FindRootError { | |
68 | kind: FindRootErrorKind::RootNotFound(current_dir.to_path_buf()), |
|
68 | kind: FindRootErrorKind::RootNotFound(current_dir.to_path_buf()), | |
69 | }) |
|
69 | }) | |
70 | } |
|
70 | } | |
71 | } |
|
71 | } | |
72 |
|
72 | |||
73 | #[cfg(test)] |
|
73 | #[cfg(test)] | |
74 | mod tests { |
|
74 | mod tests { | |
75 | use super::*; |
|
75 | use super::*; | |
76 | use std::fs; |
|
76 | use std::fs; | |
77 | use tempfile; |
|
77 | use tempfile; | |
78 |
|
78 | |||
79 | #[test] |
|
79 | #[test] | |
80 | fn dot_hg_not_found() { |
|
80 | fn dot_hg_not_found() { | |
81 | let tmp_dir = tempfile::tempdir().unwrap(); |
|
81 | let tmp_dir = tempfile::tempdir().unwrap(); | |
82 | let path = tmp_dir.path(); |
|
82 | let path = tmp_dir.path(); | |
83 |
|
83 | |||
84 | let err = FindRoot::new_from_path(&path).run().unwrap_err(); |
|
84 | let err = FindRoot::new_from_path(&path).run().unwrap_err(); | |
85 |
|
85 | |||
86 | // TODO do something better |
|
86 | // TODO do something better | |
87 | assert!(match err { |
|
87 | assert!(match err { | |
88 | FindRootError { kind } => match kind { |
|
88 | FindRootError { kind } => match kind { | |
89 | FindRootErrorKind::RootNotFound(p) => p == path.to_path_buf(), |
|
89 | FindRootErrorKind::RootNotFound(p) => p == path.to_path_buf(), | |
90 | _ => false, |
|
90 | _ => false, | |
91 | }, |
|
91 | }, | |
92 | }) |
|
92 | }) | |
93 | } |
|
93 | } | |
94 |
|
94 | |||
95 | #[test] |
|
95 | #[test] | |
96 | fn dot_hg_in_current_path() { |
|
96 | fn dot_hg_in_current_path() { | |
97 | let tmp_dir = tempfile::tempdir().unwrap(); |
|
97 | let tmp_dir = tempfile::tempdir().unwrap(); | |
98 | let root = tmp_dir.path(); |
|
98 | let root = tmp_dir.path(); | |
99 | fs::create_dir_all(root.join(".hg")).unwrap(); |
|
99 | fs::create_dir_all(root.join(".hg")).unwrap(); | |
100 |
|
100 | |||
101 | let result = FindRoot::new_from_path(&root).run().unwrap(); |
|
101 | let result = FindRoot::new_from_path(&root).run().unwrap(); | |
102 |
|
102 | |||
103 | assert_eq!(result, root) |
|
103 | assert_eq!(result, root) | |
104 | } |
|
104 | } | |
105 |
|
105 | |||
106 | #[test] |
|
106 | #[test] | |
107 | fn dot_hg_in_parent() { |
|
107 | fn dot_hg_in_parent() { | |
108 | let tmp_dir = tempfile::tempdir().unwrap(); |
|
108 | let tmp_dir = tempfile::tempdir().unwrap(); | |
109 | let root = tmp_dir.path(); |
|
109 | let root = tmp_dir.path(); | |
110 | fs::create_dir_all(root.join(".hg")).unwrap(); |
|
110 | fs::create_dir_all(root.join(".hg")).unwrap(); | |
111 |
|
111 | |||
112 | let result = |
|
112 | let result = | |
113 | FindRoot::new_from_path(&root.join("some/nested/directory")) |
|
113 | FindRoot::new_from_path(&root.join("some/nested/directory")) | |
114 | .run() |
|
114 | .run() | |
115 | .unwrap(); |
|
115 | .unwrap(); | |
116 |
|
116 | |||
117 | assert_eq!(result, root) |
|
117 | assert_eq!(result, root) | |
118 | } |
|
118 | } | |
119 | } /* tests */ |
|
119 | } /* tests */ |
General Comments 0
You need to be logged in to leave comments.
Login now