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.
132 lines
3.9 KiB
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(),
|
|
})
|
|
}
|
|
}
|
|
|