use crate::error::Result;
use cargo_metadata::{Metadata, MetadataCommand};
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct PackageInfo {
pub name: String,
pub dependencies: Vec<String>,
}
#[allow(dead_code)]
pub(super) fn parse_cargo_metadata(workspace_path: &str) -> Result<(Metadata, Vec<PackageInfo>)> {
let mut cmd = MetadataCommand::new();
cmd.current_dir(PathBuf::from(workspace_path));
cmd.no_deps();
let metadata = cmd
.exec()
.map_err(|e| crate::error::Error::Config(format!("Failed to read cargo metadata: {e}")))?;
let workspace_members: Vec<_> = metadata
.workspace_members
.iter()
.map(std::string::ToString::to_string)
.collect();
let mut packages = Vec::new();
for pkg in &metadata.packages {
if workspace_members.contains(&pkg.id.to_string()) {
let deps: Vec<String> = pkg
.dependencies
.iter()
.filter(|d| {
d.path
.as_ref()
.is_some_and(|p| p.starts_with(&metadata.workspace_root))
})
.map(|d| d.name.clone())
.collect();
packages.push(PackageInfo {
name: pkg.name.clone(),
dependencies: deps,
});
}
}
Ok((metadata, packages))
}
#[allow(dead_code)]
pub(super) fn get_current_version(workspace_path: &str) -> Result<String> {
let cargo_toml_path = PathBuf::from(workspace_path).join("Cargo.toml");
let content = std::fs::read_to_string(&cargo_toml_path)
.map_err(|e| crate::error::Error::Io(format!("Failed to read Cargo.toml: {e}")))?;
let value: toml::Value = toml::from_str(&content)
.map_err(|e| crate::error::Error::Config(format!("Failed to parse Cargo.toml: {e}")))?;
let package = value
.get("workspace")
.and_then(|w| w.get("package"))
.or_else(|| value.get("package"));
package
.and_then(|p| p.get("version"))
.and_then(|v| v.as_str())
.map(String::from)
.ok_or_else(|| crate::error::Error::Config("No version found in Cargo.toml".to_string()))
}