1use std::ops::{Deref, DerefMut};
2use std::path::PathBuf;
3use std::process::{self, Command};
4
5use anyhow::{Context, Result};
6use clap::Parser;
7
8use crate::Zig;
9
10#[derive(Clone, Debug, Default, Parser)]
12#[command(
13 display_order = 1,
14 after_help = "Run `cargo help run` for more detailed information."
15)]
16pub struct Run {
17 #[arg(skip)]
19 pub disable_zig_linker: bool,
20
21 #[arg(skip)]
23 pub enable_zig_ar: bool,
24
25 #[command(flatten)]
26 pub cargo: cargo_options::Run,
27}
28
29impl Run {
30 #[allow(clippy::field_reassign_with_default)]
32 pub fn new(manifest_path: Option<PathBuf>) -> Self {
33 let mut build = Self::default();
34 build.manifest_path = manifest_path;
35 build
36 }
37
38 pub fn execute(&self) -> Result<()> {
40 let mut run = self.build_command()?;
41
42 let mut child = run.spawn().context("Failed to run cargo run")?;
43 let status = child.wait().expect("Failed to wait on cargo run process");
44 if !status.success() {
45 process::exit(status.code().unwrap_or(1));
46 }
47 Ok(())
48 }
49
50 pub fn build_command(&self) -> Result<Command> {
52 let mut build = self.cargo.command();
53 if !self.disable_zig_linker {
54 Zig::apply_command_env(
55 self.manifest_path.as_deref(),
56 self.release,
57 &self.cargo.common,
58 &mut build,
59 self.enable_zig_ar,
60 )?;
61 }
62
63 Ok(build)
64 }
65}
66
67impl Deref for Run {
68 type Target = cargo_options::Run;
69
70 fn deref(&self) -> &Self::Target {
71 &self.cargo
72 }
73}
74
75impl DerefMut for Run {
76 fn deref_mut(&mut self) -> &mut Self::Target {
77 &mut self.cargo
78 }
79}
80
81impl From<cargo_options::Run> for Run {
82 fn from(cargo: cargo_options::Run) -> Self {
83 Self {
84 cargo,
85 ..Default::default()
86 }
87 }
88}