cargo_e/
e_command_builder.rs1use std::ffi::OsString;
2use std::path::PathBuf;
3use std::process::Command;
4
5#[derive(Debug, Clone)]
6pub enum TargetOrigin {
7 SingleFile(PathBuf),
8 MultiFile(PathBuf),
9 SubProject(PathBuf),
10 Named(OsString),
11}
12
13#[derive(Debug, Clone)]
14pub enum TargetKind {
15 Example,
16 Binary,
17 Test,
18 Manifest, }
20
21#[derive(Debug, Clone)]
22pub struct CargoTarget {
23 pub name: String,
24 pub display_name: String,
25 pub manifest_path: String,
26 pub kind: TargetKind,
27 pub extended: bool,
28 pub origin: Option<TargetOrigin>, }
30
31pub struct CargoCommandBuilder {
33 args: Vec<String>,
34}
35
36impl CargoCommandBuilder {
37 pub fn new() -> Self {
39 CargoCommandBuilder { args: Vec::new() }
40 }
41
42 pub fn with_target(mut self, target: &CargoTarget) -> Self {
44 match target.kind {
45 TargetKind::Example => {
46 self.args.push("run".into());
47 self.args.push("--example".into());
48 self.args.push(target.name.clone());
49 }
50 TargetKind::Binary => {
51 self.args.push("run".into());
52 self.args.push("--bin".into());
53 self.args.push(target.name.clone());
54 }
55 TargetKind::Test => {
56 self.args.push("test".into());
57 self.args.push(target.name.clone());
58 }
59 TargetKind::Manifest => {
60 self.args.push("manifest".into());
63 }
64 }
65
66 if target.extended {
68 self.args.push("--manifest-path".into());
69 self.args.push(target.manifest_path.clone());
70 }
71
72 if let Some(ref origin) = target.origin {
74 match origin {
75 TargetOrigin::SubProject(path) => {
77 self.args.push("--manifest-path".into());
78 self.args.push(path.to_string_lossy().to_string());
79 }
80 _ => { }
82 }
83 }
84
85 self
86 }
87
88 pub fn with_extra_args(mut self, extra: &[String]) -> Self {
90 if !extra.is_empty() {
91 self.args.push("--".into());
93 self.args.extend(extra.iter().cloned());
94 }
95 self
96 }
97
98 pub fn build(self) -> Vec<String> {
100 self.args
101 }
102
103 pub fn build_command(self) -> Command {
105 let mut cmd = Command::new("cargo");
106 cmd.args(self.args);
107 cmd
108 }
109}
110
111#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn test_command_builder_example() {
118 let target = CargoTarget {
119 name: "my_example".to_string(),
120 display_name: "My Example".to_string(),
121 manifest_path: "Cargo.toml".to_string(),
122 kind: TargetKind::Example,
123 extended: true,
124 origin: Some(TargetOrigin::SingleFile(PathBuf::from(
125 "examples/my_example.rs",
126 ))),
127 };
128
129 let extra_args = vec!["--flag".to_string(), "value".to_string()];
130
131 let args = CargoCommandBuilder::new()
132 .with_target(&target)
133 .with_extra_args(&extra_args)
134 .build();
135
136 assert!(args.contains(&"run".to_string()));
139 assert!(args.contains(&"--example".to_string()));
140 assert!(args.contains(&"my_example".to_string()));
141 assert!(args.contains(&"--manifest-path".to_string()));
142 assert!(args.contains(&"Cargo.toml".to_string()));
143 assert!(args.contains(&"--".to_string()));
144 assert!(args.contains(&"--flag".to_string()));
145 assert!(args.contains(&"value".to_string()));
146 }
147}