perseus_cli/
prepare.rs

1use crate::cmd::run_cmd_directly;
2use crate::errors::*;
3use crate::parse::Opts;
4use std::path::PathBuf;
5use std::process::Command;
6
7/// Checks if the user has the necessary prerequisites on their system (i.e.
8/// `cargo` and `wasm-pack`). These can all be checked by just trying to run
9/// their binaries and looking for errors. If the user has other paths for
10/// these, they can define them under the environment variables
11/// `PERSEUS_CARGO_PATH` and `PERSEUS_WASM_PACK_PATH`.
12///
13/// Checks if the user has `cargo` installed, and tries to install the
14/// `wasm32-unknown-unknown` target with `rustup` if it's available.
15pub fn check_env(global_opts: &Opts) -> Result<(), Error> {
16    #[cfg(unix)]
17    let shell_exec = "sh";
18    #[cfg(windows)]
19    let shell_exec = "powershell";
20    #[cfg(unix)]
21    let shell_param = "-c";
22    #[cfg(windows)]
23    let shell_param = "-command";
24
25    // Check for `cargo`
26    let cargo_cmd = global_opts.cargo_engine_path.to_string() + " --version";
27    let cargo_res = Command::new(shell_exec)
28        .args([shell_param, &cargo_cmd])
29        .output()
30        .map_err(|err| Error::CargoNotPresent { source: err })?;
31    let exit_code = match cargo_res.status.code() {
32        Some(exit_code) => exit_code,
33        None if cargo_res.status.success() => 0,
34        None => 1,
35    };
36    if exit_code != 0 {
37        return Err(Error::CargoNotPresent {
38            source: std::io::Error::new(std::io::ErrorKind::NotFound, "non-zero exit code"),
39        });
40    }
41    // If the user has `rustup`, make sure they have `wasm32-unknown-unknown`
42    // installed If they don'aren't using `rustup`, we won't worry about this
43    let rustup_cmd = global_opts.rustup_path.to_string() + " target list";
44    let rustup_res = Command::new(shell_exec)
45        .args([shell_param, &rustup_cmd])
46        .output();
47    if let Ok(rustup_res) = rustup_res {
48        let exit_code = match rustup_res.status.code() {
49            Some(exit_code) => exit_code,
50            None if rustup_res.status.success() => 0,
51            None => 1,
52        };
53        if exit_code == 0 {
54            let stdout = String::from_utf8_lossy(&rustup_res.stdout);
55            let has_wasm_target = stdout.contains("wasm32-unknown-unknown (installed)");
56            if !has_wasm_target {
57                let exit_code = run_cmd_directly(
58                    "rustup target add wasm32-unknown-unknown".to_string(),
59                    &PathBuf::from("."),
60                    vec![],
61                )?;
62                if exit_code != 0 {
63                    return Err(Error::RustupTargetAddFailed { code: exit_code });
64                }
65            }
66        }
67    }
68
69    Ok(())
70}