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);