use crate::models::{CargoCrate, CrateId, DepGraph}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::{ cmp::{self, Eq, Ord, PartialEq, PartialOrd}, collections::BTreeSet, path::PathBuf, }; static ID_CTR: AtomicUsize = AtomicUsize::new(0); /// A crate in a cargo workspace /// /// Has a name, path (stored as the offset of the root), and set of /// dependencies inside the workspace. To get the dependents of this /// crate, query the dependency graph with the set of other crate IDs. #[derive(Clone, Debug)] pub struct Crate { /// Numeric Id of this crate pub id: CrateId, /// Package name, not the folder name pub name: String, /// Path offset of the workspace root pub cc: CargoCrate, /// List of dependencies this crate has inside this workspace pub dependencies: BTreeSet, } impl PartialEq for Crate { fn eq(&self, other: &Self) -> bool { self.id == other.id } } impl Eq for Crate {} impl Ord for Crate { fn cmp(&self, other: &Self) -> cmp::Ordering { self.id.cmp(&other.id) } } impl PartialOrd for Crate { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } /// Increment the monotonicly increasing Id fn incr_id() -> usize { ID_CTR.fetch_add(1, Ordering::Relaxed) } impl Crate { pub fn new(cc: CargoCrate) -> Self { Self { id: incr_id(), name: cc.name(), cc, dependencies: BTreeSet::default(), } } /// Call this function once all crates have been loaded into scope pub fn process(&mut self, g: &DepGraph) { let deps: Vec<_> = self .cc .dependencies .iter() .filter_map(|d| g.find_crate(&d.name)) .collect(); deps.into_iter().for_each(|cid| self.add_dependency(cid)); } /// Get the crate name pub fn name(&self) -> &String { &self.name } /// Get the crate path pub fn path(&self) -> &PathBuf { &self.cc.path } /// Get the current version pub fn version(&self) -> String { self.cc.version() } /// Add a dependency of this crate pub fn add_dependency(&mut self, id: CrateId) { self.dependencies.insert(id); } /// Check if this crate has a particular dependency pub fn has_dependency(&self, id: CrateId) -> bool { self.dependencies.contains(&id) } pub fn change_dependency(&mut self, dep: &String, new_ver: &String) { self.cc.change_dep(dep, new_ver); } /// Publish a new version of this crate pub fn publish(&mut self, new_version: String) { self.cc.set_version(new_version); } pub fn sync(&mut self) { self.cc.sync(); } }