use super::{Constraint, DepConstraint}; use crate::models::{CrateId, DepGraph}; use std::collections::BTreeSet; /// Execute a simple set query pub(crate) fn set(crates: &Vec, g: &DepGraph) -> Vec { crates .iter() .filter_map(|name| match g.find_crate(name) { None => { eprintln!("[ERROR]: Unable to find crate: `{}`", name); None } some => some, }) .collect() } /// Execute a search query on the dependency graph pub(crate) fn deps(mut deps: Vec, g: &DepGraph) -> Vec { // Parse the anchor point (first crate) let DepConstraint { ref _crate, ref constraint, } = deps.remove(0); let init_id = get_crate_error(_crate, g); // Get it's dependents let mut dependents: BTreeSet<_> = match constraint { Constraint::Initial(true) => g.get_dependents(init_id).into_iter().collect(), Constraint::Initial(false) => g .get_all() .iter() .filter(|c| c.has_dependency(init_id)) .map(|c| c.id) .collect(), _ => { eprintln!("Invalid initial constraint! Only `<` and `!<` are allowed!"); std::process::exit(2); } }; // Then loop over all other constraints and subtract crates from // the dependents set until all constraints are met. deps.reverse(); while let Some(dc) = deps.pop() { let DepConstraint { ref _crate, ref constraint, } = dc; let id = get_crate_error(_crate, g); let ldeps = g.get_dependents(id); dependents = apply_constraint(dependents, ldeps, constraint); } dependents.into_iter().collect() } fn get_crate_error(_crate: &String, g: &DepGraph) -> CrateId { match g.find_crate(&_crate.trim().to_string()) { Some(id) => id, None => { eprintln!("[ERROR]: Crate `{}` not found in workspace!", _crate); std::process::exit(2); } } } fn apply_constraint( init: BTreeSet, cmp: Vec, cnd: &Constraint, ) -> BTreeSet { let cmp: BTreeSet = cmp.into_iter().collect(); let init = init.into_iter(); match cnd { Constraint::And(true) => init.filter(|id| cmp.contains(id)).collect(), Constraint::And(false) => init.filter(|id| !cmp.contains(id)).collect(), Constraint::Or => init.chain(cmp.into_iter()).collect(), _ => todo!(), } }