grass/dev/strategy/path.rs
1mod local;
2mod mock;
3
4use std::path::PathBuf;
5
6use thiserror::Error;
7
8use crate::{dev::RepositoryLocation, support_strategy};
9
10pub use local::LocalPathStrategy;
11pub use mock::MockPathStrategy;
12
13#[derive(Error, Debug, PartialEq, Eq, Hash)]
14pub enum PathStrategyError {
15 #[error("Cannot find repository:\nContext: {context}\nReason: {reason}")]
16 RepositoryNotFound { context: String, reason: String },
17
18 #[error("A file does not exist:\nContext: {context}\nReason: {reason}")]
19 FileDoesNotExist { context: String, reason: String },
20
21 #[error("There is a problem:\nContext: {context}\nReason: {reason}")]
22 Unknown { context: String, reason: String },
23}
24
25pub type Result<T> = std::result::Result<T, PathStrategyError>;
26
27pub trait PathStrategy {
28 /// Get the containing directory for a repository
29 ///
30 /// This can work even when the repository doesn't exist (yet).
31 /// So this can be used to get the directory to move into, for example.
32 ///
33 /// Grass makes no guarentees that all repositories will be contained in the same directory.
34 /// You cannot assume that other repositories in the same category are contained in the same
35 /// directory.
36 ///
37 /// # Example
38 ///
39 /// ```rust
40 /// use grass::dev::strategy::path::{MockPathStrategy, PathStrategy, PathStrategyError};
41 /// use std::path::PathBuf;
42 /// let strategy = MockPathStrategy;
43 /// fn test_strategy<T: PathStrategy>(strategy: &T) {
44 /// assert_eq!(
45 /// strategy.get_containing_directory(("all_good", "first")),
46 /// Ok(PathBuf::from("/home/example/repositories/all_good"))
47 /// );
48 ///
49 /// assert_eq!(
50 /// strategy.get_containing_directory(("with_changes", "does_not_exist")),
51 /// Ok(PathBuf::from("/home/example/repositories/with_changes"))
52 /// );
53 ///
54 /// assert!(matches!(
55 /// strategy.get_containing_directory(("does_not_exist", "third")),
56 /// Err(PathStrategyError::RepositoryNotFound { .. })
57 /// ));
58 /// }
59 ///
60 /// test_strategy(&strategy);
61 /// ```
62 fn get_containing_directory<T>(&self, repository: T) -> Result<PathBuf>
63 where
64 T: Into<RepositoryLocation>;
65
66 /// Get the directory for a repository
67 ///
68 /// This will also work if the path doesn't exist
69 ///
70 /// # Example
71 ///
72 /// ```rust
73 /// use grass::dev::strategy::path::{MockPathStrategy, PathStrategy, PathStrategyError};
74 /// use std::path::PathBuf;
75 /// let strategy = MockPathStrategy;
76 /// fn test_strategy<T: PathStrategy>(strategy: &T) {
77 /// assert_eq!(
78 /// strategy.get_directory(("all_good", "first")),
79 /// Ok(PathBuf::from("/home/example/repositories/all_good/first"))
80 /// );
81 ///
82 /// assert!(matches!(
83 /// strategy.get_directory(("all_good", "does_not_exist")),
84 /// Err(PathStrategyError::RepositoryNotFound { .. })
85 /// ));
86 ///
87 /// assert!(matches!(
88 /// strategy.get_directory(("does_not_exist", "third")),
89 /// Err(PathStrategyError::RepositoryNotFound { .. })
90 /// ));
91 /// }
92 /// test_strategy(&strategy);
93 /// ```
94 fn get_directory<T>(&self, repository: T) -> Result<PathBuf>
95 where
96 T: Into<RepositoryLocation>;
97}
98
99support_strategy!(SupportsPath, get_path_strategy, PathStrategy);