workspacer_workspace/
workspace.rs1crate::ix!();
3
4#[derive(Builder,MutGetters,Getters,Debug)]
5#[getset(get="pub",get_mut="pub")]
6#[builder(setter(into))]
7pub struct Workspace<P,H:CrateHandleInterface<P>>
8where for<'async_trait> P: From<PathBuf> + AsRef<Path> + Send + Sync + 'async_trait
9{
10 path: P,
11 crates: Vec<Arc<AsyncMutex<H>>>,
12}
13
14impl<P,H:CrateHandleInterface<P>> WorkspaceInterface<P,H> for Workspace<P,H>
15where for<'async_trait> P: From<PathBuf> + AsRef<Path> + Clone + Send + Sync + 'async_trait
16{ }
17
18impl<P,H:CrateHandleInterface<P>> AsRef<Path> for Workspace<P,H>
19where for<'async_trait> P: From<PathBuf> + AsRef<Path> + Send + Sync + 'async_trait
20{
21 fn as_ref(&self) -> &Path {
23 self.path.as_ref()
24 }
25}
26
27impl<P,H:CrateHandleInterface<P>> GetCrates<P,H> for Workspace<P,H>
28where for<'async_trait> P: From<PathBuf> + AsRef<Path> + Send + Sync + 'async_trait
29{
30 fn crates(&self) -> &[Arc<AsyncMutex<H>>] {
31 &self.crates
32 }
33}
34
35impl<P,H:CrateHandleInterface<P>> GetCratesMut<P,H> for Workspace<P,H>
36where for<'async_trait> P: From<PathBuf> + AsRef<Path> + Send + Sync + 'async_trait
37{
38 fn crates_mut(&mut self) -> &mut Vec<Arc<AsyncMutex<H>>> {
39 &mut self.crates
40 }
41}
42
43#[async_trait]
44impl<P,H:CrateHandleInterface<P>> FindCrateByName<P,H> for Workspace<P,H>
45where for<'async_trait> P: From<PathBuf> + AsRef<Path> + Send + Sync + 'async_trait
46{
47 async fn find_crate_by_name(&self, name: &str) -> Option<Arc<AsyncMutex<H>>> {
48 for item in self.crates() {
49 let crate_guard = item.lock().await;
50 if crate_guard.name() == name {
51 return Some(item.clone());
52 }
53 }
54 None
55 }
56}
57
58#[async_trait]
59impl<P,H:CrateHandleInterface<P>> GetAllCrateNames for Workspace<P,H>
60where for<'async_trait> P: From<PathBuf> + AsRef<Path> + Send + Sync + 'async_trait
61{
62 async fn get_all_crate_names(&self) -> Vec<String> {
63 let mut names = Vec::new();
64 for item in self.crates() {
65 let crate_guard = item.lock().await;
66 names.push(crate_guard.name().to_string());
67 }
68 names
69 }
70}
71
72#[async_trait]
73impl<P,H:CrateHandleInterface<P>> AsyncTryFrom<P> for Workspace<P,H>
74where
75 for<'async_trait> P: From<PathBuf> + AsRef<Path> + Clone + Send + Sync + 'async_trait,
77{
78 type Error = WorkspaceError;
79
80 async fn new(path: &P) -> Result<Self, Self::Error> {
84 let path_buf = path.as_ref().to_path_buf();
86 let cargo_toml = path_buf.join("Cargo.toml");
87 if !cargo_toml.exists() {
88 return Err(WorkspaceError::InvalidWorkspace {
89 invalid_workspace_path: path_buf,
90 });
91 }
92
93 let cargo_toml_str = tokio::fs::read_to_string(&cargo_toml).await.map_err(|e| {
95 WorkspaceError::IoError {
96 io_error: e.into(),
97 context: format!("Failed to read {:?}", cargo_toml),
98 }
99 })?;
100
101 let parsed: toml::Value = toml::from_str(&cargo_toml_str).map_err(|_e| {
103 WorkspaceError::InvalidWorkspace {
104 invalid_workspace_path: path_buf.clone(),
105 }
106 })?;
107
108 let is_workspace = parsed
109 .as_table()
110 .map_or(false, |tbl| tbl.contains_key("workspace"));
111 if !is_workspace {
112 return Err(WorkspaceError::ActuallyInSingleCrate {
114 path: path_buf,
115 });
116 }
117
118 if !Self::is_valid(&path_buf).await {
121 return Err(WorkspaceError::InvalidWorkspace {
122 invalid_workspace_path: path_buf,
123 });
124 }
125
126 let crates = Self::find_items(&path_buf).await?;
127 Ok(Self { path: path.clone(), crates })
128 }
129}