Skip to main content

cli_xtask/subcommand/
exec.rs

1use std::process::Command;
2
3use crate::{
4    Result, Run,
5    args::{EnvArgs, WorkspaceArgs},
6    config::Config,
7    process::CommandExt,
8};
9
10/// Arguments definition of the `exec` subcommand.
11#[cfg_attr(doc, doc = include_str!("../../doc/cargo-xtask-exec.md"))]
12#[derive(Debug, Clone, Default, clap::Args)]
13#[non_exhaustive]
14pub struct Exec {
15    /// Environment variables to set for the command.
16    #[clap(flatten)]
17    pub env_args: EnvArgs,
18    /// Workspaces where the the command runs on.
19    #[clap(flatten)]
20    pub workspace_args: WorkspaceArgs,
21    /// Command to execute
22    pub command: String,
23    /// Arguments to pass to the command
24    pub command_options: Vec<String>,
25}
26
27impl Run for Exec {
28    fn run(&self, config: &Config) -> Result<()> {
29        self.run(config)
30    }
31}
32
33impl Exec {
34    /// Runs the `exec` subcommand.
35    #[tracing::instrument(name = "exec", skip_all, err)]
36    pub fn run(&self, _config: &Config) -> Result<()> {
37        let Self {
38            env_args,
39            workspace_args,
40            command,
41            command_options,
42        } = self;
43
44        let is_cargo_llvm_cov =
45            command == "cargo" && command_options.first().is_some_and(|arg| arg == "llvm-cov");
46
47        for workspace in workspace_args.workspaces() {
48            let mut cmd = Command::new(command);
49            cmd.args(command_options).envs(env_args.env.clone());
50
51            if is_cargo_llvm_cov {
52                // Avoid cargo-llvm-cov recursion when running under llvm-cov.
53                cmd.env_remove("RUSTC_WRAPPER")
54                    .env_remove("RUSTC_WORKSPACE_WRAPPER");
55            }
56
57            cmd.workspace_spawn(workspace)?;
58        }
59
60        Ok(())
61    }
62}