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 member_name = Path::new(s)
72 .file_name()
73 .and_then(|os| os.to_str())
74 .unwrap_or(s)
75 .to_string();
76 member_paths.push((member_name, member_manifest));
77 }
78 }
79 }
80 }
81
82 if member_paths.is_empty() {
83 None
84 } else {
85 Some(member_paths)
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use std::fs;
93 use tempfile::TempDir;
94
95 #[test]
96 fn test_workspace_member_manifest_paths_found() {
97 let temp_dir = TempDir::new().unwrap();
99
100 let workspace_manifest_path = temp_dir.path().join("Cargo.toml");
102 let workspace_manifest_content = r#"
103[workspace]
104members = ["cargo-e", "addendum/e_crate_version_checker"]
105 "#;
106 fs::write(&workspace_manifest_path, workspace_manifest_content).unwrap();
107
108 let cargo_e_dir = temp_dir.path().join("cargo-e");
110 fs::create_dir_all(&cargo_e_dir).unwrap();
111 fs::write(cargo_e_dir.join("Cargo.toml"), "dummy content").unwrap();
112
113 let e_crate_dir = temp_dir
115 .path()
116 .join("addendum")
117 .join("e_crate_version_checker");
118 fs::create_dir_all(&e_crate_dir).unwrap();
119 fs::write(e_crate_dir.join("Cargo.toml"), "dummy content").unwrap();
120
121 let result = get_workspace_member_manifest_paths(&workspace_manifest_path);
123 assert!(result.is_some());
124 let members = result.unwrap();
125 assert_eq!(members.len(), 2);
126
127 for (_, path) in members {
129 assert!(path.ends_with("Cargo.toml"));
130 }
131 }
132
133 #[test]
134 fn test_workspace_member_manifest_paths_not_found() {
135 let temp_dir = TempDir::new().unwrap();
137
138 let workspace_manifest_path = temp_dir.path().join("Cargo.toml");
140 let workspace_manifest_content = r#"
141[workspace]
142members = ["cargo-e", "addendum/e_crate_version_checker"]
143 "#;
144 fs::write(&workspace_manifest_path, workspace_manifest_content).unwrap();
145
146 let result = get_workspace_member_manifest_paths(&workspace_manifest_path);
150 assert!(result.is_none());
151 }
152}