1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
use super::{Constraint, DepConstraint};
use crate::models::{CrateId, DepGraph};
use std::collections::BTreeSet;
/// Execute a simple set query
pub(crate) fn set(crates: &Vec<String>, g: &DepGraph) -> Vec<CrateId> {
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<DepConstraint>, g: &DepGraph) -> Vec<CrateId> {
// 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<CrateId>,
cmp: Vec<CrateId>,
cnd: &Constraint,
) -> BTreeSet<CrateId> {
let cmp: BTreeSet<CrateId> = 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!(),
}
}
|