#![allow(clippy::print_stderr, clippy::print_stdout)]
use std::path::Path;
use std::process::Command;
#[derive(clap::Args)]
pub struct RunArgs {
#[arg(short, long)]
package: Option<String>,
#[arg(last = true)]
app_args: Vec<String>,
#[arg(short, long)]
verbose: bool,
#[arg(long)]
release: bool,
#[arg(long, value_delimiter = ',')]
features: Vec<String>,
}
pub fn execute(args: &RunArgs) -> Result<(), String> {
if args.verbose {
eprintln!("Running pre-flight checks...");
}
let check_input = if let Some(ref pkg) = args.package {
crate::commands::check::resolve_package_ui_path(pkg)
.map(|p| p.to_string_lossy().to_string())
} else {
None
};
if let Err(e) = crate::commands::check::run_checks(check_input, false, args.verbose) {
return Err(format!("Pre-flight check failed: {}", e));
}
if !Path::new("Cargo.toml").exists() {
return Err("Cargo.toml not found. Are you in a Rust project directory?".to_string());
}
let mode = if args.release {
"codegen"
} else {
"interpreted"
};
if args.verbose {
eprintln!("Running in {} mode...", mode);
eprintln!(
"Profile: {}",
if args.release { "release" } else { "debug" }
);
}
if args.release {
let build_rs_exists = Path::new("build.rs").exists()
|| args
.package
.as_ref()
.is_some_and(|pkg| Path::new("examples").join(pkg).join("build.rs").exists());
if !build_rs_exists {
return Err(
"build.rs not found. Codegen mode requires build.rs for code generation.\n\
Tip: Use 'dampen run' (without --release) for interpreted mode,\n\
or ensure you're in the correct project directory."
.to_string(),
);
}
let mut build_cmd = Command::new("cargo");
build_cmd.arg("build");
if let Some(ref package) = args.package {
build_cmd.arg("-p").arg(package);
}
if args.verbose {
build_cmd.arg("--verbose");
}
build_cmd.arg("--release");
build_cmd.arg("--no-default-features");
let mut features = vec!["codegen".to_string()];
features.extend(args.features.clone());
build_cmd.arg("--features").arg(features.join(","));
if args.verbose {
let features_str = features.join(",");
eprintln!(
"Building: cargo build --release --no-default-features --features {}",
features_str
);
}
let build_status = build_cmd
.status()
.map_err(|e| format!("Failed to execute cargo build: {}", e))?;
if !build_status.success() {
return Err("Build failed".to_string());
}
if args.verbose {
eprintln!("Build successful! Now running application...");
}
let mut run_cmd = Command::new("cargo");
run_cmd.arg("run");
if let Some(ref package) = args.package {
run_cmd.arg("-p").arg(package);
}
if args.verbose {
run_cmd.arg("--verbose");
}
run_cmd.arg("--release");
if !args.app_args.is_empty() {
run_cmd.arg("--");
run_cmd.args(&args.app_args);
}
if args.verbose {
eprintln!("Running: cargo run --release");
if !args.app_args.is_empty() {
eprintln!("Application args: {:?}", args.app_args);
}
}
let run_status = run_cmd
.status()
.map_err(|e| format!("Failed to execute cargo run: {}", e))?;
if !run_status.success() {
return Err("Run command failed".to_string());
}
Ok(())
} else {
let mut cmd = Command::new("cargo");
cmd.arg("run");
if let Some(ref package) = args.package {
cmd.arg("-p").arg(package);
}
if args.verbose {
cmd.arg("--verbose");
}
let mut features = vec!["interpreted".to_string()];
features.extend(args.features.clone());
cmd.arg("--features").arg(features.join(","));
if !args.app_args.is_empty() {
cmd.arg("--");
cmd.args(&args.app_args);
}
if args.verbose {
let features_str = features.join(",");
eprintln!("Executing: cargo run --features {}", features_str);
if !args.app_args.is_empty() {
eprintln!("Application args: {:?}", args.app_args);
}
}
let status = cmd
.status()
.map_err(|e| format!("Failed to execute cargo: {}", e))?;
if !status.success() {
return Err("Run command failed".to_string());
}
Ok(())
}
}