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}
35impl Default for CargoCommandBuilder {
36 fn default() -> Self {
37 Self::new()
38 }
39}
40impl CargoCommandBuilder {
41 pub fn new() -> Self {
43 CargoCommandBuilder { args: Vec::new() }
44 }
45
46 pub fn with_target(mut self, target: &CargoTarget) -> Self {
48 match target.kind {
49 TargetKind::Example => {
50 self.args.push("run".into());
51 self.args.push("--example".into());
52 self.args.push(target.name.clone());
53 }
54 TargetKind::Binary => {
55 self.args.push("run".into());
56 self.args.push("--bin".into());
57 self.args.push(target.name.clone());
58 }
59 TargetKind::Test => {
60 self.args.push("test".into());
61 self.args.push(target.name.clone());
62 }
63 TargetKind::Manifest => {
64 self.args.push("manifest".into());
67 }
68 }
69
70 if target.extended {
72 self.args.push("--manifest-path".into());
73 self.args.push(target.manifest_path.clone());
74 }
75
76 if let Some(TargetOrigin::SubProject(ref path)) = target.origin {
79 self.args.push("--manifest-path".into());
80 self.args.push(path.display().to_string());
81 }
82
83 self
84 }
85
86 pub fn with_extra_args(mut self, extra: &[String]) -> Self {
88 if !extra.is_empty() {
89 self.args.push("--".into());
91 self.args.extend(extra.iter().cloned());
92 }
93 self
94 }
95
96 pub fn build(self) -> Vec<String> {
98 self.args
99 }
100
101 pub fn build_command(self) -> Command {
103 let mut cmd = Command::new("cargo");
104 cmd.args(self.args);
105 cmd
106 }
107}
108
109#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_command_builder_example() {
116 let target = CargoTarget {
117 name: "my_example".to_string(),
118 display_name: "My Example".to_string(),
119 manifest_path: "Cargo.toml".to_string(),
120 kind: TargetKind::Example,
121 extended: true,
122 origin: Some(TargetOrigin::SingleFile(PathBuf::from(
123 "examples/my_example.rs",
124 ))),
125 };
126
127 let extra_args = vec!["--flag".to_string(), "value".to_string()];
128
129 let args = CargoCommandBuilder::new()
130 .with_target(&target)
131 .with_extra_args(&extra_args)
132 .build();
133
134 assert!(args.contains(&"run".to_string()));
137 assert!(args.contains(&"--example".to_string()));
138 assert!(args.contains(&"my_example".to_string()));
139 assert!(args.contains(&"--manifest-path".to_string()));
140 assert!(args.contains(&"Cargo.toml".to_string()));
141 assert!(args.contains(&"--".to_string()));
142 assert!(args.contains(&"--flag".to_string()));
143 assert!(args.contains(&"value".to_string()));
144 }
145}