use std::collections::{HashMap, HashSet};
use crate::command_add::models::{MyComponent, ResolvedComponent};
pub fn all_tree_resolved(
user_components: Vec<String>,
vec_components_from_index: &[MyComponent],
) -> HashMap<String, ResolvedComponent> {
let component_map: HashMap<String, MyComponent> = vec_components_from_index
.iter()
.map(|c| (c.name.clone(), c.clone()))
.collect();
let resolved = resolve_all_dependencies(&component_map, &user_components).unwrap();
resolved
}
fn resolve_all_dependencies(
component_map: &HashMap<String, MyComponent>,
user_components: &[String],
) -> Result<HashMap<String, ResolvedComponent>, Box<dyn std::error::Error>> {
let mut resolved_components: HashMap<String, ResolvedComponent> = HashMap::new();
for component_name in user_components {
if !component_map.contains_key(component_name) {
return Err(format!("Target component '{}' not found in index", component_name).into());
}
resolve_component_recursive(
component_name,
component_map,
&mut resolved_components,
&mut HashSet::new(),
)?;
}
Ok(resolved_components)
}
fn resolve_component_recursive(
component_name: &str,
component_map: &HashMap<String, MyComponent>,
resolved_components: &mut HashMap<String, ResolvedComponent>,
visited: &mut HashSet<String>,
) -> Result<(HashSet<String>, HashSet<String>), Box<dyn std::error::Error>> {
if let Some(resolved) = resolved_components.get(component_name) {
return Ok((
resolved.resolved_registry_dependencies.clone(),
resolved.resolved_cargo_dependencies.clone(),
));
}
if !visited.insert(component_name.to_string()) {
return Err(format!("Circular dependency detected involving '{}'", component_name).into());
}
let component = match component_map.get(component_name) {
Some(c) => c,
None => return Err(format!("Component '{}' not found", component_name).into()),
};
let mut resolved_registry_dependencies = HashSet::new();
let mut resolved_cargo_dependencies = HashSet::new();
for cargo_dep in &component.cargo_dependencies {
resolved_cargo_dependencies.insert(cargo_dep.clone());
}
for dep_name in &component.registry_dependencies {
resolved_registry_dependencies.insert(dep_name.clone());
let (transitive_registry_deps, transitive_cargo_deps) =
resolve_component_recursive(dep_name, component_map, resolved_components, visited)?;
for trans_dep in transitive_registry_deps {
resolved_registry_dependencies.insert(trans_dep);
}
for cargo_dep in transitive_cargo_deps {
resolved_cargo_dependencies.insert(cargo_dep);
}
}
visited.remove(component_name);
resolved_components.insert(
component_name.to_string(),
ResolvedComponent {
component: component.clone(),
resolved_registry_dependencies: resolved_registry_dependencies.clone(),
resolved_cargo_dependencies: resolved_cargo_dependencies.clone(),
},
);
Ok((resolved_registry_dependencies, resolved_cargo_dependencies))
}
pub fn get_all_resolved_components(resolved: &HashMap<String, ResolvedComponent>) -> Vec<String> {
let mut all_components = HashSet::new();
for name in resolved.keys() {
all_components.insert(name.clone());
}
for (_, component) in resolved {
for dep in &component.resolved_registry_dependencies {
all_components.insert(dep.clone());
}
}
let mut result: Vec<String> = all_components.into_iter().collect();
result.sort();
result
}
pub fn get_all_resolved_parent_dirs(resolved: &HashMap<String, ResolvedComponent>) -> Vec<String> {
let mut all_parent_dirs = HashSet::new();
for (_, component) in resolved {
all_parent_dirs.insert(component.component.parent_dir.clone());
}
let mut result: Vec<String> = all_parent_dirs.into_iter().collect();
result.sort();
result
}
pub fn get_all_resolved_cargo_dependencies(resolved: &HashMap<String, ResolvedComponent>) -> Vec<String> {
let mut all_cargo_deps = HashSet::new();
for (_, component) in resolved {
for dep in &component.resolved_cargo_dependencies {
all_cargo_deps.insert(dep.clone());
}
}
let mut result: Vec<String> = all_cargo_deps.into_iter().collect();
result.sort();
result
}