tracel_xtask/utils/
workspace.rs1use serde_json::Value;
2use std::{path::Path, process::Command};
3
4const MEMBER_PATH_PREFIX: &str = if cfg!(target_os = "windows") {
5 "path+file:///"
6} else {
7 "path+file://"
8};
9
10pub enum WorkspaceMemberType {
11 Crate,
12 Example,
13}
14
15#[derive(Debug)]
16#[allow(dead_code)]
17pub struct WorkspaceMember {
18 pub name: String,
19 pub path: String,
20}
21
22impl WorkspaceMember {
23 fn new(name: String, path: String) -> Self {
24 Self { name, path }
25 }
26}
27
28pub fn get_workspace_members(w_type: WorkspaceMemberType) -> Vec<WorkspaceMember> {
30 let output = Command::new("cargo")
32 .arg("metadata")
33 .output()
34 .expect("Failed to execute command");
35 let metadata: Value = serde_json::from_slice(&output.stdout).expect("Failed to parse JSON");
37 metadata["workspace_members"]
40 .as_array()
41 .expect("Expected an array of workspace members")
42 .iter()
43 .filter_map(|member| {
44 let member_str = member.as_str()?;
45 let has_whitespace = member_str.chars().any(|c| c.is_whitespace());
46 let (name, path) = if has_whitespace {
47 parse_workspace_member0(member_str)?
48 } else {
49 parse_workspace_member1(member_str)?
50 };
51 match w_type {
52 WorkspaceMemberType::Crate if !path.contains("examples/") => {
53 Some(WorkspaceMember::new(name.to_string(), path.to_string()))
54 }
55 WorkspaceMemberType::Example if path.contains("examples/") => {
56 Some(WorkspaceMember::new(name.to_string(), path.to_string()))
57 }
58 _ => None,
59 }
60 })
61 .collect()
62}
63
64fn parse_workspace_member0(specs: &str) -> Option<(String, String)> {
68 let parts: Vec<_> = specs.split_whitespace().collect();
69 let (name, path) = (parts.first()?.to_owned(), parts.last()?.to_owned());
70 let path = path
72 .chars()
73 .skip(1)
74 .collect::<String>()
75 .replace(MEMBER_PATH_PREFIX, "")
76 .replace(')', "");
77 Some((name.to_string(), path.to_string()))
78}
79
80fn parse_workspace_member1(specs: &str) -> Option<(String, String)> {
84 let no_prefix = specs.replace(MEMBER_PATH_PREFIX, "").replace(')', "");
85 let path = Path::new(no_prefix.split_once('#')?.0);
86 let name = path.file_name()?.to_str()?;
87 let path = path.to_str()?;
88 Some((name.to_string(), path.to_string()))
89}