aboutsummaryrefslogtreecommitdiff
path: root/development/tools/cargo-workspace2/src/query/executor.rs
blob: da67324de4c0127e50c42e290349d6928a77abb7 (plain)
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!(),
    }
}