cargo_workspace2/models/
cargo.rs1use crate::cargo::{self, Dependency, Result};
2use std::{fmt, path::PathBuf};
3use toml_edit::{value, Document, Item, Value};
4
5#[derive(Clone)]
7pub struct CargoCrate {
8 pub doc: Document,
9 pub path: PathBuf,
10 pub dependencies: Vec<Dependency>,
11}
12
13impl fmt::Debug for CargoCrate {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 write!(f, "{}", self.path.as_path().display())
16 }
17}
18
19impl CargoCrate {
20 pub fn name(&self) -> String {
22 match &self.doc["package"]["name"] {
23 Item::Value(Value::String(ref name)) => {
24 name.to_string().replace("\"", "").as_str().trim().into()
25 }
26 _ => panic!(format!("Invalid Cargo.toml: {:?}", self.path)),
27 }
28 }
29
30 pub fn version(&self) -> String {
32 match &self.doc["package"]["version"] {
33 Item::Value(Value::String(ref name)) => {
34 name.to_string().replace("\"", "").as_str().trim().into()
35 }
36 _ => panic!(format!("Invalid Cargo.toml: {:?}", self.path)),
37 }
38 }
39
40 pub fn dep_by_name(&self, name: &String) -> &Dependency {
42 self.dependencies
43 .iter()
44 .find(|c| &c.name == name)
45 .as_ref()
46 .unwrap()
47 }
48
49 pub fn change_dep(&mut self, dep: &String, ver: &String) {
50 let dep = self
51 .dep_by_name(dep)
52 .alias()
53 .unwrap_or(dep.to_string())
54 .clone();
55 cargo::update_dependency(&mut self.doc, &dep, ver);
56 }
57
58 pub fn all_deps_mut(&mut self) -> Vec<&mut Dependency> {
59 self.dependencies.iter_mut().collect()
60 }
61
62 pub fn has_version(&self, name: &String) -> bool {
64 self.dep_by_name(name).has_version()
65 }
66
67 pub fn has_path(&self, name: &String) -> bool {
69 self.dep_by_name(name).has_version()
70 }
71
72 pub fn set_version(&mut self, version: String) {
74 self.doc["package"]["version"] = value(version);
75 }
76
77 pub fn sync(&mut self) {
79 cargo::sync(&mut self.doc, self.path.join("Cargo.toml")).unwrap();
80 }
81}
82
83pub struct CargoWorkspace {
85 pub root: PathBuf,
86 pub crates: Vec<CargoCrate>,
87}
88
89impl CargoWorkspace {
90 pub fn open(p: impl Into<PathBuf>) -> Result<Self> {
95 let path = p.into();
96
97 let root_cfg = cargo::parse_root_toml(path.join("Cargo.toml"))?;
98 let members = cargo::get_members(&root_cfg)?;
99
100 let m_cfg: Vec<_> = members
101 .into_iter()
102 .filter_map(
103 |name| match cargo::parse_toml(path.join(&name).join("Cargo.toml")) {
104 Ok(doc) => Some((
105 PathBuf::new().join(name),
106 cargo::parse_dependencies(&doc),
107 doc,
108 )),
109 Err(e) => {
110 eprintln!(
111 "Error occured while parsing member `{}`/`Cargo.toml`: {:?}",
112 name, e
113 );
114 None
115 }
116 },
117 )
118 .collect();
119
120 Ok(Self {
121 root: path,
122 crates: m_cfg
123 .into_iter()
124 .map(|(path, dependencies, doc)| CargoCrate {
125 path,
126 dependencies,
127 doc,
128 })
129 .collect(),
130 })
131 }
132}