You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.9 KiB
Rust
146 lines
3.9 KiB
Rust
use crate::unit::{UnitHandle, Unit};
|
|
use std::collections::{HashMap, VecDeque, HashSet};
|
|
use crate::config::loader::Loader;
|
|
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct DependencyTree {
|
|
known: HashSet<String>,
|
|
dependents: HashMap<String, HashSet<String>>,
|
|
dependencies: HashMap<String, HashSet<String>>,
|
|
}
|
|
|
|
impl DependencyTree {
|
|
pub fn add_owner(&mut self, owner: String) {
|
|
self.known.insert(owner);
|
|
}
|
|
|
|
pub fn add_dependency(&mut self, owner: String, dependency: String) {
|
|
if owner == dependency {
|
|
return;
|
|
}
|
|
|
|
self.dependencies
|
|
.entry(owner.clone())
|
|
.or_default()
|
|
.insert(dependency.clone());
|
|
|
|
self.dependents
|
|
.entry(dependency.clone())
|
|
.or_default()
|
|
.insert(owner.clone());
|
|
|
|
self.known.insert(dependency);
|
|
self.known.insert(owner);
|
|
}
|
|
|
|
/// Gets the bottom of the dependency tree
|
|
/// These are the items -without- dependencies
|
|
pub fn get_bottom(&self) -> Vec<String> {
|
|
self
|
|
.known
|
|
.iter()
|
|
.filter(|item| !self.dependencies.get(*item).map(|l| l.len() == 0).unwrap_or(true))
|
|
.map(|item| item.clone())
|
|
.collect()
|
|
}
|
|
|
|
/// Gets the top of the dependency tree
|
|
/// These are the items -without- dependents
|
|
pub fn get_top(&self) -> Vec<String> {
|
|
self
|
|
.known
|
|
.iter()
|
|
.filter(|item| self.dependents.get(*item).map(|l| l.len() == 0).unwrap_or(true))
|
|
.map(|item| item.clone())
|
|
.collect()
|
|
}
|
|
|
|
pub fn get_dependencies(&self, item: &str) -> Vec<String> {
|
|
self
|
|
.dependencies
|
|
.get(item)
|
|
.map(|set| set.iter().map(|x| x.clone()).collect::<Vec<_>>())
|
|
.unwrap_or(Vec::new())
|
|
}
|
|
|
|
pub fn get_depedents(&self, item: &str) -> Vec<String> {
|
|
self
|
|
.dependents
|
|
.get(item)
|
|
.map(|set| set.iter().map(|x| x.clone()).collect::<Vec<_>>())
|
|
.unwrap_or(Vec::new())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct Registry {
|
|
loader: Loader,
|
|
units: HashMap<String, UnitHandle>,
|
|
}
|
|
|
|
impl Registry {
|
|
pub fn with_loader(loader: Loader) -> Registry {
|
|
Registry {
|
|
loader,
|
|
units: Default::default(),
|
|
}
|
|
}
|
|
|
|
pub async fn get_dependency_tree(&mut self, unit_name: &str) -> DependencyTree {
|
|
let mut queue = VecDeque::new();
|
|
let mut done = HashSet::new();
|
|
let mut dependencies: DependencyTree = Default::default();
|
|
|
|
queue.push_back(unit_name.to_string());
|
|
|
|
while let Some(item) = queue.pop_front() {
|
|
let unit = if let Some(unit) = self.load_unit(&item).await {
|
|
unit
|
|
} else {
|
|
done.insert(item);
|
|
continue;
|
|
};
|
|
|
|
for dep in &unit.wants {
|
|
if done.contains(dep) {
|
|
continue;
|
|
}
|
|
|
|
queue.push_back(dep.clone());
|
|
}
|
|
|
|
for dep in &unit.requires {
|
|
if done.contains(dep) {
|
|
continue;
|
|
}
|
|
|
|
queue.push_back(dep.clone());
|
|
}
|
|
|
|
for before in &unit.before {
|
|
dependencies.add_dependency(before.clone(), unit.name.clone());
|
|
}
|
|
|
|
for after in &unit.after {
|
|
dependencies.add_dependency(unit.name.clone(), after.clone());
|
|
}
|
|
}
|
|
|
|
dependencies
|
|
}
|
|
|
|
pub async fn load_unit(&mut self, unit_name: &str) -> Option<&Unit> {
|
|
let config = self
|
|
.units
|
|
.entry(unit_name.to_string())
|
|
.or_insert_with(|| UnitHandle::unloaded(unit_name));
|
|
|
|
if !config.is_loaded() {
|
|
if let Some(unit) = self.loader.load_unit(unit_name).await {
|
|
config.update(unit);
|
|
}
|
|
}
|
|
|
|
config.get_config()
|
|
}
|
|
} |