vertigo_cli/build/
cargo_workspace.rs1use serde::Deserialize;
2use std::path::PathBuf;
3
4use crate::commons::{command::CommandRun, ErrorCode};
5
6#[derive(Clone, Debug, Deserialize)]
7pub struct Workspace {
8 packages: Vec<Package>,
9 target_directory: String,
10 workspace_members: Vec<String>,
11 workspace_root: String,
12}
13
14#[derive(Clone, Debug, Deserialize)]
15pub struct Package {
16 id: String,
17 name: String,
18 manifest_path: String,
19 targets: Vec<Target>,
20}
21
22#[derive(Clone, Debug, Deserialize)]
23pub struct Target {
24 kind: Vec<String>,
25}
26
27impl Workspace {
28 pub fn infer_package_name(&self) -> Option<String> {
29 for member_id in &self.workspace_members {
30 if let Some(package) = self
31 .packages
32 .iter()
33 .find(|package| &package.id == member_id)
34 {
35 if package.is_cdylib() {
36 return Some(package.name.clone());
37 }
38 }
39 }
40 None
41 }
42
43 pub fn find_package_path(&self, package_name: &str) -> Option<PathBuf> {
44 self.packages
45 .iter()
46 .find(|package| package.name == package_name)
47 .map(|package| package.manifest_path.clone().into())
48 .and_then(|path: PathBuf| path.parent().map(|p| p.to_path_buf()))
49 }
50
51 pub fn get_target_dir(&self) -> PathBuf {
52 self.target_directory.clone().into()
53 }
54
55 pub fn get_root_dir(&self) -> &str {
56 &self.workspace_root
57 }
58}
59
60impl Package {
61 pub fn is_cdylib(&self) -> bool {
62 self.targets
63 .iter()
64 .any(|target| target.kind.iter().any(|kind| kind == "cdylib"))
65 }
66}
67
68pub fn get_workspace() -> Result<Workspace, ErrorCode> {
69 let metadata = CommandRun::new("cargo")
70 .add_param("metadata")
71 .add_param("--format-version=1")
72 .set_error_code(ErrorCode::CantOpenWorkspace)
73 .output()?;
74
75 match serde_json::from_str::<Workspace>(&metadata) {
76 Ok(mut ws) => {
77 ws.packages
79 .retain(|package| ws.workspace_members.contains(&package.id));
80 Ok(ws)
81 }
82 Err(err) => {
83 log::error!("Can't parse workspace: {err}");
84 Err(ErrorCode::CantParseWorkspace)
85 }
86 }
87}