My personal project and infrastructure archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nomicon/development/tools/cargo-workspace2/src/models/cargo.rs

132 lines
3.9 KiB

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(),
})
}
}