Skip to main content

cargo_workspace2/models/
graph.rs

1use crate::models::{CargoCrate, Crate, CrateId};
2use std::collections::{BTreeMap, BTreeSet};
3use std::path::PathBuf;
4
5/// Dependency graph in a workspace
6pub struct DepGraph {
7    /// Mapping of crates in the workspace
8    members: BTreeMap<CrateId, Crate>,
9    /// Map of crates and the members that depend on them
10    dependents: BTreeMap<CrateId, BTreeSet<CrateId>>,
11}
12
13impl DepGraph {
14    /// Create a new, empty dependency graph
15    pub fn new() -> Self {
16        Self {
17            members: Default::default(),
18            dependents: Default::default(),
19        }
20    }
21
22    pub fn add_crate(&mut self, cc: CargoCrate) {
23        let cc = Crate::new(cc);
24        self.members.insert(cc.id, cc);
25    }
26
27    /// Cache the dependents graph for all crates
28    pub fn finalise(&mut self) {
29        let mut members = self.members.clone();
30        members.iter_mut().for_each(|(_, c)| c.process(&self));
31
32        members.iter().for_each(|(id, _crate)| {
33            _crate.dependencies.iter().for_each(|dep_id| {
34                self.dependents.entry(*dep_id).or_default().insert(*id);
35            });
36        });
37        let _ = std::mem::replace(&mut self.members, members);
38    }
39
40    /// Get a crate by ID
41    pub fn get_crate(&self, id: CrateId) -> &Crate {
42        self.members.get(&id).as_ref().unwrap()
43    }
44
45    /// Get mutable access to a crate by ID
46    pub fn mut_crate(&mut self, id: CrateId) -> &mut Crate {
47        self.members.get_mut(&id).unwrap()
48    }
49
50    /// Find a crate via it's name
51    pub fn find_crate(&self, name: &String) -> Option<CrateId> {
52        self.members
53            .iter()
54            .find(|(_, c)| c.name() == name)
55            .map(|(id, _)| *id)
56    }
57
58    /// Find a crate by it's path-offset in the workspace
59    pub fn find_crate_by_path(&self, name: &String) -> Option<CrateId> {
60        self.members
61            .iter()
62            .find(|(_, c)| c.path() == &PathBuf::new().join(name))
63            .map(|(id, _)| *id)
64    }
65
66    /// Get a crate's dependents
67    pub fn get_dependents(&self, id: CrateId) -> Vec<CrateId> {
68        self.dependents
69            .get(&id)
70            .as_ref()
71            .map(|set| set.iter().cloned().collect())
72            .unwrap_or(vec![])
73    }
74
75    pub fn get_all(&self) -> Vec<&Crate> {
76        self.members.iter().map(|(_, c)| c).collect()
77    }
78}