use crate::paths;
use anyhow::{Context, Result};
use std::path::Path;
pub async fn add_workspace_member(project_root: &Path, member_path: &str) -> Result<()> {
let cargo_path = project_root.join(paths::rust::CARGO_TOML);
let content = tokio::fs::read_to_string(&cargo_path)
.await
.context("Failed to read Cargo.toml")?;
let mut doc: toml::Value = toml::from_str(&content).context("Failed to parse Cargo.toml")?;
let member_path = member_path.to_string();
if let Some(workspace) = doc.get_mut("workspace") {
if let Some(members) = workspace.get_mut("members") {
if let Some(arr) = members.as_array_mut() {
let exists = arr.iter().any(|m| m.as_str() == Some(&member_path));
if !exists {
arr.push(toml::Value::String(member_path));
}
}
} else {
workspace.as_table_mut().unwrap().insert(
"members".to_string(),
toml::Value::Array(vec![toml::Value::String(member_path)]),
);
}
} else {
let mut workspace_table = toml::map::Map::new();
workspace_table.insert(
"members".to_string(),
toml::Value::Array(vec![toml::Value::String(member_path)]),
);
doc.as_table_mut()
.unwrap()
.insert("workspace".to_string(), toml::Value::Table(workspace_table));
}
let updated_content = toml::to_string_pretty(&doc)?;
tokio::fs::write(&cargo_path, updated_content).await?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[tokio::test]
async fn add_workspace_member_creates_workspace_section_when_absent() {
let temp = TempDir::new().unwrap();
tokio::fs::write(temp.path().join("Cargo.toml"), "[package]\nname = \"proj\"\n")
.await
.unwrap();
add_workspace_member(temp.path(), "drivers/my-driver").await.unwrap();
let content = tokio::fs::read_to_string(temp.path().join("Cargo.toml")).await.unwrap();
let doc: toml::Value = toml::from_str(&content).unwrap();
let members = doc["workspace"]["members"].as_array().unwrap();
assert!(members.iter().any(|m| m.as_str() == Some("drivers/my-driver")));
}
#[tokio::test]
async fn add_workspace_member_is_idempotent() {
let temp = TempDir::new().unwrap();
tokio::fs::write(
temp.path().join("Cargo.toml"),
"[workspace]\nmembers = [\"drivers/my-driver\"]\n",
)
.await
.unwrap();
add_workspace_member(temp.path(), "drivers/my-driver").await.unwrap();
let content = tokio::fs::read_to_string(temp.path().join("Cargo.toml")).await.unwrap();
let doc: toml::Value = toml::from_str(&content).unwrap();
let members = doc["workspace"]["members"].as_array().unwrap();
assert_eq!(
members
.iter()
.filter(|m| m.as_str() == Some("drivers/my-driver"))
.count(),
1
);
}
}