use crate::component::{discover_from_portable, Component};
use crate::error::{Error, Result};
use crate::extension;
use crate::project;
use std::collections::HashSet;
pub fn inventory() -> Result<Vec<Component>> {
let projects = project::list().unwrap_or_default();
let mut components = Vec::new();
let mut seen = HashSet::new();
for project in &projects {
for attachment in &project.components {
if let Ok(component) = project::resolve_project_component(project, &attachment.id) {
if seen.insert(component.id.clone()) {
components.push(component);
}
}
}
}
if let Ok(cwd) = std::env::current_dir() {
if let Some(component) = discover_from_portable(&cwd) {
if seen.insert(component.id.clone()) {
components.push(component);
}
} else if let Some(git_root) = crate::component::resolution::detect_git_root(&cwd) {
if let Some(component) = discover_from_portable(&git_root) {
if seen.insert(component.id.clone()) {
components.push(component);
}
}
}
}
components.sort_by(|a, b| a.id.cmp(&b.id));
Ok(components)
}
pub fn extension_provides_artifact_pattern(component: &Component) -> bool {
component
.extensions
.as_ref()
.map(|extensions| {
extensions.keys().any(|extension_id| {
extension::load_extension(extension_id)
.ok()
.and_then(|m| m.build)
.and_then(|b| b.artifact_pattern)
.is_some()
})
})
.unwrap_or(false)
}
pub fn list() -> Result<Vec<Component>> {
inventory()
}
pub fn list_ids() -> Result<Vec<String>> {
Ok(inventory()?
.into_iter()
.map(|component| component.id)
.collect())
}
pub fn load(id: &str) -> Result<Component> {
if let Some(component) = inventory()?
.into_iter()
.find(|component| component.id == id)
{
return Ok(component);
}
let suggestions = list_ids().unwrap_or_default();
Err(Error::component_not_found(id.to_string(), suggestions))
}
pub fn exists(id: &str) -> bool {
load(id).is_ok()
}