dampen_cli/commands/
run.rs1#![allow(clippy::print_stderr, clippy::print_stdout)]
2
3use std::path::Path;
9use std::process::Command;
10
11#[derive(clap::Args)]
13pub struct RunArgs {
14 #[arg(short, long)]
16 package: Option<String>,
17
18 #[arg(last = true)]
20 app_args: Vec<String>,
21
22 #[arg(short, long)]
24 verbose: bool,
25
26 #[arg(long)]
28 release: bool,
29
30 #[arg(long, value_delimiter = ',')]
32 features: Vec<String>,
33}
34
35pub fn execute(args: &RunArgs) -> Result<(), String> {
65 if args.verbose {
67 eprintln!("Running pre-flight checks...");
68 }
69
70 let check_input = if let Some(ref pkg) = args.package {
72 crate::commands::check::resolve_package_ui_path(pkg)
73 .map(|p| p.to_string_lossy().to_string())
74 } else {
75 None
76 };
77
78 if let Err(e) = crate::commands::check::run_checks(check_input, false, args.verbose) {
79 return Err(format!("Pre-flight check failed: {}", e));
80 }
81
82 if !Path::new("Cargo.toml").exists() {
85 return Err("Cargo.toml not found. Are you in a Rust project directory?".to_string());
86 }
87
88 let mode = if args.release {
89 "codegen"
90 } else {
91 "interpreted"
92 };
93
94 if args.verbose {
95 eprintln!("Running in {} mode...", mode);
96 eprintln!(
97 "Profile: {}",
98 if args.release { "release" } else { "debug" }
99 );
100 }
101
102 if args.release {
104 let build_rs_exists = Path::new("build.rs").exists()
107 || args
108 .package
109 .as_ref()
110 .is_some_and(|pkg| Path::new("examples").join(pkg).join("build.rs").exists());
111
112 if !build_rs_exists {
113 return Err(
114 "build.rs not found. Codegen mode requires build.rs for code generation.\n\
115 Tip: Use 'dampen run' (without --release) for interpreted mode,\n\
116 or ensure you're in the correct project directory."
117 .to_string(),
118 );
119 }
120
121 let mut build_cmd = Command::new("cargo");
123 build_cmd.arg("build");
124
125 if let Some(ref package) = args.package {
126 build_cmd.arg("-p").arg(package);
127 }
128
129 if args.verbose {
130 build_cmd.arg("--verbose");
131 }
132
133 build_cmd.arg("--release");
135 build_cmd.arg("--no-default-features");
136
137 let mut features = vec!["codegen".to_string()];
138 features.extend(args.features.clone());
139
140 build_cmd.arg("--features").arg(features.join(","));
141
142 if args.verbose {
143 let features_str = features.join(",");
144 eprintln!(
145 "Building: cargo build --release --no-default-features --features {}",
146 features_str
147 );
148 }
149
150 let build_status = build_cmd
151 .status()
152 .map_err(|e| format!("Failed to execute cargo build: {}", e))?;
153
154 if !build_status.success() {
155 return Err("Build failed".to_string());
156 }
157
158 if args.verbose {
159 eprintln!("Build successful! Now running application...");
160 }
161
162 let mut run_cmd = Command::new("cargo");
164 run_cmd.arg("run");
165
166 if let Some(ref package) = args.package {
167 run_cmd.arg("-p").arg(package);
168 }
169
170 if args.verbose {
171 run_cmd.arg("--verbose");
172 }
173
174 run_cmd.arg("--release");
176
177 if !args.app_args.is_empty() {
179 run_cmd.arg("--");
180 run_cmd.args(&args.app_args);
181 }
182
183 if args.verbose {
184 eprintln!("Running: cargo run --release");
185 if !args.app_args.is_empty() {
186 eprintln!("Application args: {:?}", args.app_args);
187 }
188 }
189
190 let run_status = run_cmd
191 .status()
192 .map_err(|e| format!("Failed to execute cargo run: {}", e))?;
193
194 if !run_status.success() {
195 return Err("Run command failed".to_string());
196 }
197
198 Ok(())
199 } else {
200 let mut cmd = Command::new("cargo");
202 cmd.arg("run");
203
204 if let Some(ref package) = args.package {
205 cmd.arg("-p").arg(package);
206 }
207
208 if args.verbose {
209 cmd.arg("--verbose");
210 }
211
212 let mut features = vec!["interpreted".to_string()];
214 features.extend(args.features.clone());
215
216 cmd.arg("--features").arg(features.join(","));
217
218 if !args.app_args.is_empty() {
220 cmd.arg("--");
221 cmd.args(&args.app_args);
222 }
223
224 if args.verbose {
226 let features_str = features.join(",");
227 eprintln!("Executing: cargo run --features {}", features_str);
228 if !args.app_args.is_empty() {
229 eprintln!("Application args: {:?}", args.app_args);
230 }
231 }
232
233 let status = cmd
234 .status()
235 .map_err(|e| format!("Failed to execute cargo: {}", e))?;
236
237 if !status.success() {
238 return Err("Run command failed".to_string());
239 }
240
241 Ok(())
242 }
243}