1use std::fs;
2use std::path::{Path, PathBuf};
3use toml::Value;
4
5pub fn is_workspace_manifest(manifest_path: &Path) -> bool {
8 if let Ok(content) = fs::read_to_string(manifest_path) {
9 for line in content.lines() {
11 if line.trim_start().starts_with("[workspace]") {
12 return true;
13 }
14 }
15 }
16 false
17}
18
19pub fn get_workspace_member_manifest_paths(manifest_path: &Path) -> Option<Vec<(String, PathBuf)>> {
24 let content = fs::read_to_string(manifest_path).ok()?;
26 let parsed: Value = content.parse().ok()?;
27
28 let workspace = parsed.get("workspace")?;
30 let members = workspace.get("members")?.as_array()?;
31
32 let workspace_root = manifest_path.parent()?;
34
35 let mut member_paths = Vec::new();
36
37 for member in members {
38 if let Some(s) = member.as_str() {
39 if s.ends_with("/*") {
40 let base = workspace_root.join(s.trim_end_matches("/*"));
42 if let Ok(entries) = fs::read_dir(&base) {
44 for entry in entries.flatten() {
45 let path = entry.path();
46 if path.is_dir() {
47 let cargo_toml = path.join("Cargo.toml");
48 if cargo_toml.exists() {
49 if let Some(member_name) =
51 path.file_name().and_then(|os| os.to_str())
52 {
53 member_paths.push((
54 format!(
55 "{}/{}",
56 s.trim_end_matches("/*"),
57 member_name.to_string()
58 ),
59 cargo_toml,
60 ));
61 }
62 }
63 }
64 }
65 }
66 } else {
67 let member_path = workspace_root.join(s);
69 let member_manifest = member_path.join("Cargo.toml");
70 if member_manifest.exists() {
71 let mut member_name = Path::new(s)
72 .file_name()
73 .and_then(|os| os.to_str())
74 .unwrap_or(s)
75 .to_string();
76 if member_name.eq("src-tauri") {
77 member_name = member_path
79 .parent()
80 .and_then(|p| p.file_name())
81 .and_then(|os| os.to_str())
82 .unwrap_or(s)
83 .to_string();
84 }
85 member_paths.push((member_name, member_manifest));
86 }
87 }
88 }
89 }
90
91 if member_paths.is_empty() {
92 None
93 } else {
94 Some(member_paths)
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use std::fs;
102 use tempfile::TempDir;
103
104 #[test]
105 fn test_workspace_member_manifest_paths_found() {
106 let temp_dir = TempDir::new().unwrap();
108
109 let workspace_manifest_path = temp_dir.path().join("Cargo.toml");
111 let workspace_manifest_content = r#"
112[workspace]
113members = ["cargo-e", "addendum/e_crate_version_checker"]
114 "#;
115 fs::write(&workspace_manifest_path, workspace_manifest_content).unwrap();
116
117 let cargo_e_dir = temp_dir.path().join("cargo-e");
119 fs::create_dir_all(&cargo_e_dir).unwrap();
120 fs::write(cargo_e_dir.join("Cargo.toml"), "dummy content").unwrap();
121
122 let e_crate_dir = temp_dir
124 .path()
125 .join("addendum")
126 .join("e_crate_version_checker");
127 fs::create_dir_all(&e_crate_dir).unwrap();
128 fs::write(e_crate_dir.join("Cargo.toml"), "dummy content").unwrap();
129
130 let workspace_manifest_content = r#"[workspace]\nmembers = [\n \"cargo-e\",\n \"addendum/e_crate_version_checker\"\n]\n".trim();
132 fs::write(&workspace_manifest_path, workspace_manifest_content).unwrap();
133
134 // Call the function under test.
135 let result = get_workspace_member_manifest_paths(&workspace_manifest_path);
136 assert!(result.is_some());
137 let members = result.unwrap();
138 assert_eq!(members.len(), 2);
139
140 // Verify that each returned path ends with "Cargo.toml".
141 for (_, path) in members {
142 assert!(path.ends_with("Cargo.toml"));
143 }
144 }
145
146 #[test]
147 fn test_workspace_member_manifest_paths_not_found() {
148 // Create a temporary directory to serve as the workspace root.
149 let temp_dir = TempDir::new().unwrap();
150
151 // Create a workspace manifest (Cargo.toml) in the workspace root.
152 let workspace_manifest_path = temp_dir.path().join("Cargo.toml");
153 let workspace_manifest_content = r#"
154[workspace]
155members = ["cargo-e", "addendum/e_crate_version_checker"]
156 "#;
157 fs::write(&workspace_manifest_path, workspace_manifest_content).unwrap();
158
159 let result = get_workspace_member_manifest_paths(&workspace_manifest_path);
163 assert!(result.is_none());
164 }
165}