Repository: google/comprehensive-rust
File: xtask/src/main.rs (Rust)

Code before:
        /// directory (or the book/xx directory if a language is provided).
        #[arg(short, long)]
        output: Option<PathBuf>,
    },
    /// Create a static version of the course.
    Build {
        /// ISO 639 language code (e.g. da for the Danish translation).
        #[arg(short, long)]
        language: Option<String>,

        /// Directory to place the build. If not provided, defaults to the book/
        /// directory (or the book/xx directory if a language is provided).
        #[arg(short, long)]
        output: Option<PathBuf>,
    },
}

fn execute_task() -> Result<()> {
    let cli = Cli::parse();
    match cli.task {
        Task::InstallTools => install_tools()?,
        Task::WebTests { dir } => run_web_tests(dir)?,
        Task::RustTests => run_rust_tests()?,
        Task::Serve { language, output } => start_web_server(language, output)?,
        Task::Build { language, output } => build(language, output)?,
    }
    Ok(())
}

fn install_tools() -> Result<()> {
    println!("Installing project tools...");

    const PINNED_NIGHTLY: &str = "nightly-2025-09-01";

    let rustup_steps = [
        ["toolchain", "install", "--profile", "minimal", PINNED_NIGHTLY],
        ["component", "add", "rustfmt", "--toolchain", PINNED_NIGHTLY],
    ];

    for args in rustup_steps {
        let status = std::process::Command::new("rustup").args(args).status()?;
        if !status.success() {
            return Err(anyhow!(
                "Command 'rustup {}' failed with status {:?}",
                args.join(" "),
                status.code()
            ));
        }
    }

    let path_to_mdbook_exerciser =

Review comment (suggestion):
I have a hunch that `run_command` should take `Command` instead of a reference: I don't think you have a case where you want to run the command twice. But you can also keep it like this if you find it more flexible.

Code after:
    /// Create a static version of the course.
    Build {
        /// ISO 639 language code (e.g. da for the Danish translation).
        #[arg(short, long)]
        language: Option<String>,

        /// Directory to place the build. If not provided, defaults to the book/
        /// directory (or the book/xx directory if a language is provided).
        #[arg(short, long)]
        output: Option<PathBuf>,
    },
}

fn execute_task() -> Result<()> {
    let cli = Cli::parse();
    match cli.task {
        Task::InstallTools => install_tools(),
        Task::WebTests { dir } => run_web_tests(dir),
        Task::RustTests => run_rust_tests(),
        Task::Serve { language, output } => start_web_server(language, output),
        Task::Build { language, output } => build(language, output),
    }
}

/// Executes a command and returns an error if it fails.
fn run_command(cmd: &mut Command) -> Result<()> {
    let command_display = format!("{cmd:?}");
    println!("> {command_display}");
    let status = cmd
        .status()
        .with_context(|| format!("Failed to execute command: {command_display}"))?;
    if !status.success() {
        let exit_description = if let Some(code) = status.code() {
            format!("exited with status code: {}", code)
        } else {
            "was terminated by a signal".to_string()
        };
        return Err(anyhow!("Command `{command_display}` {exit_description}"));
    }
    Ok(())
}

fn install_tools() -> Result<()> {
    println!("Installing project tools...");

    const PINNED_NIGHTLY: &str = "nightly-2025-09-01";

    // Install rustup components
    let rustup_steps = [
        ["toolchain", "install", "--profile", "minimal", PINNED_NIGHTLY],
        ["component", "add", "rustfmt", "--toolchain", PINNED_NIGHTLY],