diff options
Diffstat (limited to 'development/tools/cargo-workspace2/src/models/cargo.rs')
-rw-r--r-- | development/tools/cargo-workspace2/src/models/cargo.rs | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/development/tools/cargo-workspace2/src/models/cargo.rs b/development/tools/cargo-workspace2/src/models/cargo.rs new file mode 100644 index 000000000000..b020e82e418d --- /dev/null +++ b/development/tools/cargo-workspace2/src/models/cargo.rs @@ -0,0 +1,132 @@ +use crate::cargo::{self, Dependency, Result}; +use std::{fmt, path::PathBuf}; +use toml_edit::{value, Document, Item, Value}; + +/// Initial representation of a crate, before being parsed +#[derive(Clone)] +pub struct CargoCrate { + pub doc: Document, + pub path: PathBuf, + pub dependencies: Vec<Dependency>, +} + +impl fmt::Debug for CargoCrate { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.path.as_path().display()) + } +} + +impl CargoCrate { + /// Get the crate name from the inner document + pub fn name(&self) -> String { + match &self.doc["package"]["name"] { + Item::Value(Value::String(ref name)) => { + name.to_string().replace("\"", "").as_str().trim().into() + } + _ => panic!(format!("Invalid Cargo.toml: {:?}", self.path)), + } + } + + /// Get the current version + pub fn version(&self) -> String { + match &self.doc["package"]["version"] { + Item::Value(Value::String(ref name)) => { + name.to_string().replace("\"", "").as_str().trim().into() + } + _ => panic!(format!("Invalid Cargo.toml: {:?}", self.path)), + } + } + + /// Find a cargo dependency by name + pub fn dep_by_name(&self, name: &String) -> &Dependency { + self.dependencies + .iter() + .find(|c| &c.name == name) + .as_ref() + .unwrap() + } + + pub fn change_dep(&mut self, dep: &String, ver: &String) { + let dep = self + .dep_by_name(dep) + .alias() + .unwrap_or(dep.to_string()) + .clone(); + cargo::update_dependency(&mut self.doc, &dep, ver); + } + + pub fn all_deps_mut(&mut self) -> Vec<&mut Dependency> { + self.dependencies.iter_mut().collect() + } + + /// Check if this crate depends on a specific version of another + pub fn has_version(&self, name: &String) -> bool { + self.dep_by_name(name).has_version() + } + + /// Check if this crate depends on a specific path of another + pub fn has_path(&self, name: &String) -> bool { + self.dep_by_name(name).has_version() + } + + /// Set a new version for this crate + pub fn set_version(&mut self, version: String) { + self.doc["package"]["version"] = value(version); + } + + /// Sync any changes made to the document to disk + pub fn sync(&mut self) { + cargo::sync(&mut self.doc, self.path.join("Cargo.toml")).unwrap(); + } +} + +/// Initial representation of the workspate, before getting parsed +pub struct CargoWorkspace { + pub root: PathBuf, + pub crates: Vec<CargoCrate>, +} + +impl CargoWorkspace { + /// Open a workspace and parse dependency graph + /// + /// Point this to the root of the workspace, do the root + /// `Cargo.toml` file. + pub fn open(p: impl Into<PathBuf>) -> Result<Self> { + let path = p.into(); + + let root_cfg = cargo::parse_root_toml(path.join("Cargo.toml"))?; + let members = cargo::get_members(&root_cfg)?; + + let m_cfg: Vec<_> = members + .into_iter() + .filter_map( + |name| match cargo::parse_toml(path.join(&name).join("Cargo.toml")) { + Ok(doc) => Some(( + PathBuf::new().join(name), + cargo::parse_dependencies(&doc), + doc, + )), + Err(e) => { + eprintln!( + "Error occured while parsing member `{}`/`Cargo.toml`: {:?}", + name, e + ); + None + } + }, + ) + .collect(); + + Ok(Self { + root: path, + crates: m_cfg + .into_iter() + .map(|(path, dependencies, doc)| CargoCrate { + path, + dependencies, + doc, + }) + .collect(), + }) + } +} |