workspacer_crate_interface/
interface.rs

1// ---------------- [ File: workspacer-crate-interface/src/interface.rs ]
2crate::ix!();
3
4pub trait CrateHandleInterface<P>
5: ValidateIntegrity<Error=CrateError>
6+ Send
7+ Sync
8+ Debug
9+ Named
10+ Versioned<Error=CrateError>
11+ IsPrivate<Error=CrateError>
12+ ReadFileString
13+ CheckIfSrcDirectoryContainsValidFiles
14+ CheckIfReadmeExists
15+ GetReadmePath
16+ GetSourceFilesWithExclusions
17+ GetTestFiles
18+ HasTestsDirectory
19+ GetFilesInDirectory
20+ GetFilesInDirectoryWithExclusions
21+ HasCargoToml
22+ RootDirPathBuf
23+ AsRef<Path>
24+ GatherBinTargetNames<Error=CrateError>
25+ AsyncTryFrom<P,Error=CrateError>
26+ GetInternalDependencies
27where
28    for<'async_trait> 
29    P
30    : HasCargoTomlPathBuf 
31    + HasCargoTomlPathBufSync
32    + AsRef<Path> 
33    + Send 
34    + Sync
35    + 'async_trait,
36
37    CrateError
38    : From<<P as HasCargoTomlPathBuf>::Error> 
39    + From<<P as HasCargoTomlPathBufSync>::Error>,
40{}
41
42/// A private trait for gathering local (path-based) dependencies from a crate’s Cargo.toml.
43/// We do NOT expose it publicly — it remains internal. 
44#[async_trait]
45pub trait GetInternalDependencies {
46    /// Gathers all `[dependencies]` entries that have `path = "../some-other-crate"`.
47    /// Returns their **names** as used in the Cargo.toml `[dependencies]` table key.
48    async fn internal_dependencies(&self) -> Result<Vec<String>, CrateError>;
49}
50
51pub trait HasCargoToml {
52
53    fn cargo_toml(&self) -> Arc<AsyncMutex<dyn CargoTomlInterface>>;
54}
55
56#[async_trait]
57pub trait IsPrivate {
58    type Error;
59    async fn is_private(&self) -> Result<bool,Self::Error>;
60}
61
62/// We add a new method to CrateHandleInterface so we can read file text from 
63/// an in-memory mock or from the real filesystem. For your real code, 
64/// you might implement it differently.
65#[async_trait]
66pub trait ReadFileString {
67    async fn read_file_string(&self, path: &Path) -> Result<String, CrateError>;
68}
69
70#[async_trait]
71pub trait GetTestFiles {
72
73    async fn test_files(&self) -> Result<Vec<PathBuf>, CrateError>;
74}
75
76#[async_trait]
77impl<P> GetTestFiles for Arc<AsyncMutex<P>>
78where
79    P: GetTestFiles + Send + Sync,
80{
81    async fn test_files(&self) -> Result<Vec<PathBuf>, CrateError> {
82        let guard = self.lock().await;
83        guard.test_files().await
84    }
85}
86
87pub trait HasTestsDirectory {
88
89    fn has_tests_directory(&self) -> bool;
90}
91
92impl<P> HasTestsDirectory for Arc<AsyncMutex<P>>
93where
94    P: HasTestsDirectory,
95{
96    fn has_tests_directory(&self) -> bool {
97        // We only need a synchronous lock here because HasTestsDirectory's method is sync,
98        // but our crate uses `tokio::sync::AsyncMutex`, so we do `.blocking_lock()`
99        // or we can do `.try_lock()`, depending on usage. If you want the async version,
100        // you might have to change the trait or store that state differently.
101        // For simplicity, we'll do `.try_lock()` and fallback to false if locked.
102        // Ideally, you'd define HasTestsDirectory as async, or
103        // use the feature "blocking" from `tokio`.
104        if let Ok(guard) = self.try_lock() {
105            guard.has_tests_directory()
106        } else {
107            // If for some reason it's locked, we might do something else. 
108            // For test usage, it's probably safe to do a separate approach:
109            panic!("Cannot lock Arc<AsyncMutex<P>> in has_tests_directory synchronously! Consider an async method or a blocking lock feature.")
110        }
111    }
112}
113
114pub trait CheckIfReadmeExists {
115
116    fn check_readme_exists(&self) -> Result<(), CrateError>;
117}
118
119#[async_trait]
120pub trait GetReadmePath {
121
122    async fn readme_path(&self) -> Result<Option<PathBuf>, CrateError>;
123}
124
125#[async_trait]
126pub trait HasCargoTomlPathBuf {
127
128    type Error;
129
130    async fn cargo_toml_path_buf(&self) -> Result<PathBuf, Self::Error>;
131}
132
133#[async_trait]
134impl<P> HasCargoTomlPathBuf for P 
135where for <'async_trait> P: AsRef<Path> + Send + Sync + 'async_trait
136{
137    type Error = CrateError;
138
139    /// Asynchronously returns the path to the `Cargo.toml`
140    async fn cargo_toml_path_buf(&self) -> Result<PathBuf, Self::Error> 
141    {
142        let cargo_path = self.as_ref().join("Cargo.toml");
143        if fs::metadata(&cargo_path).await.is_ok() {
144            Ok(cargo_path)
145        } else {
146            Err(CrateError::FileNotFound {
147                missing_file: cargo_path,
148            })
149        }
150    }
151}
152
153pub trait HasCargoTomlPathBufSync {
154
155    type Error;
156
157    fn cargo_toml_path_buf_sync(&self) -> Result<PathBuf, Self::Error>;
158}
159
160impl<P> HasCargoTomlPathBufSync for P 
161where P: AsRef<Path>
162{
163    type Error = CrateError;
164
165    /// Asynchronously returns the path to the `Cargo.toml`
166    fn cargo_toml_path_buf_sync(&self) -> Result<PathBuf, Self::Error> 
167    {
168        let cargo_path = self.as_ref().join("Cargo.toml");
169        if std::fs::metadata(&cargo_path).is_ok() {
170            Ok(cargo_path)
171        } else {
172            Err(CrateError::FileNotFound {
173                missing_file: cargo_path,
174            })
175        }
176    }
177}
178
179
180pub trait RootDirPathBuf {
181
182    fn root_dir_path_buf(&self) -> PathBuf;
183}
184
185impl<P> RootDirPathBuf for P 
186where P: AsRef<Path> + Send + Sync
187{
188    /// returns the path to the `Cargo.toml`
189    fn root_dir_path_buf(&self) -> PathBuf
190    {
191        self.as_ref().to_path_buf()
192    }
193}
194
195pub trait CheckIfSrcDirectoryContainsValidFiles {
196
197    fn check_src_directory_contains_valid_files(&self) -> Result<(), CrateError>;
198}
199
200#[async_trait]
201pub trait GetSourceFilesWithExclusions {
202
203    async fn source_files_excluding(&self, exclude_files: &[&str]) -> Result<Vec<PathBuf>, CrateError>;
204}
205
206#[async_trait]
207impl<P> GetSourceFilesWithExclusions for Arc<AsyncMutex<P>>
208where
209    P: GetSourceFilesWithExclusions + Send + Sync,
210{
211    async fn source_files_excluding(
212        &self,
213        exclude: &[&str],
214    ) -> Result<Vec<PathBuf>, CrateError> {
215        // Lock and forward
216        let guard = self.lock().await;
217        guard.source_files_excluding(exclude).await
218    }
219}
220
221#[async_trait]
222pub trait GetFilesInDirectory {
223
224    async fn get_files_in_dir(&self, dir_name: &str, extension: &str) 
225        -> Result<Vec<PathBuf>, CrateError>;
226}
227
228#[async_trait]
229pub trait GetFilesInDirectoryWithExclusions {
230
231    async fn get_files_in_dir_with_exclusions(
232        &self,
233        dir_name: &str,
234        extension: &str,
235        exclude_files: &[&str]
236    ) -> Result<Vec<PathBuf>, CrateError>;
237}