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

Code before:
        return Err(anyhow!(error_message));
    }

    Ok(())
}

fn start_web_server(language: Option<String>, output: Option<String>) -> Result<()> {
    println!("Starting web server ...");
    let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));

    let mut command = Command::new("mdbook");
    command.current_dir(path_to_workspace_root.to_str().unwrap());
    command.arg("serve");

    if let Some(language) = &language {
        println!("Language: {}", &language);
        command.env("MDBOOK_BOOK__LANGUAGE", &language);
    }

    // If the 'output' arg is specified by the caller, use that, otherwise output to the 'book/' directory
    // (or the 'book/xx' directory if a language was specified).
    command.arg("-d");
    if let Some(d) = output {
        command.arg(d);
    } else {
        command.arg(format!("book/{}", language.unwrap_or("".to_string())));
    }

    let status = command.status().expect("Failed to execute mdbook serve");

    if !status.success() {
        let error_message = format!(
            "Command 'cargo xtask serve' exited with status code: {}",
            status.code().unwrap()
        );
        return Err(anyhow!(error_message));
    }
    Ok(())
}

fn build(language: Option<String>, output: Option<String>) -> Result<()> {
    println!("Building course...");
    let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));

    let mut command = Command::new("mdbook");
    command.current_dir(path_to_workspace_root.to_str().unwrap());
    command.arg("build");

    if let Some(language) = &language {
        println!("Language: {}", &language);
        command.env("MDBOOK_BOOK__LANGUAGE", language);

Review comment (suggestion):
This is a good candidate for a `Path` otherwise we have directory separator issues e.g. with Windows

Code after:
        return Err(anyhow!(error_message));
    }

    Ok(())
}

fn start_web_server(
    language: Option<String>,
    output_arg: Option<PathBuf>,
) -> Result<()> {
    println!("Starting web server ...");
    let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));

    let mut command = Command::new("mdbook");
    command.current_dir(path_to_workspace_root.to_str().unwrap());
    command.arg("serve");

    if let Some(language) = &language {
        println!("Language: {}", &language);
        command.env("MDBOOK_BOOK__LANGUAGE", &language);
    }

    command.arg("-d");
    command.arg(get_output_dir(language, output_arg));

    let status = command.status().expect("Failed to execute mdbook serve");

    if !status.success() {
        let error_message = format!(
            "Command 'cargo xtask serve' exited with status code: {}",
            status.code().unwrap()
        );
        return Err(anyhow!(error_message));
    }
    Ok(())
}

fn build(language: Option<String>, output_arg: Option<PathBuf>) -> Result<()> {
    println!("Building course...");
    let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));

    let mut command = Command::new("mdbook");
    command.current_dir(path_to_workspace_root.to_str().unwrap());
    command.arg("build");

    if let Some(language) = &language {
        println!("Language: {}", &language);
        command.env("MDBOOK_BOOK__LANGUAGE", language);
    }

    command.arg("-d");