Skip to content

Commit

Permalink
rustwasm#627 - create a custom error message when wasm-bindgen fails …
Browse files Browse the repository at this point in the history
…because --web isn't available

Change the return type of the child run commands so it can return a CommandError that also captures the stderr if the process fails.
See if the returned output contains the 'Unknown flag: --web' error message and if so provide an alternative error that suggests upgrading
  • Loading branch information
Kirk Turner committed Apr 21, 2019
1 parent 9423867 commit 97fdc94
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 28 deletions.
19 changes: 18 additions & 1 deletion src/bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,27 @@ pub fn wasm_bindgen_build(
cmd.arg("--keep-debug");
}

child::run(cmd, "wasm-bindgen").context("Running the wasm-bindgen CLI")?;
let result = child::run(cmd, "wasm-bindgen");
let result: Result<(), failure::Error> = match result {
Ok(r) => Ok(r),
Err(e) => process_error(e),
};
result.context("Running the wasm-bindgen CLI")?;
Ok(())
}

fn process_error(e: child::CommandError) -> Result<(), failure::Error> {
match &e.stderr {
Some(err) if err.trim().starts_with("Unknown flag: '--web'") =>
bail!("Failed to execute `wasm-bindgen`: --web is not supported. Upgrade wasm-bindgen to a more recent version."),
Some(err) => {
eprintln!("{}", err);
bail!("{}", e.to_string())
},
_ => bail!("{}", e.to_string()),
}
}

/// Check if the `wasm-bindgen` dependency is locally satisfied.
fn wasm_bindgen_version_check(bindgen_path: &PathBuf, dep_version: &str) -> bool {
let mut cmd = Command::new(bindgen_path);
Expand Down
94 changes: 67 additions & 27 deletions src/child.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
//! This module helps us ensure that all child processes that we spawn get
//! properly logged and their output is logged as well.

use failure::Error;
use log::info;
use std::process::{Command, Stdio};
use std::io::Error as StdError;
use std::process::{Command, ExitStatus, Stdio};

/// Return a new Command object
pub fn new_command(program: &str) -> Command {
Expand All @@ -23,39 +23,79 @@ pub fn new_command(program: &str) -> Command {
}
}

/// Run the given command and return its stdout.
pub fn run(mut command: Command, command_name: &str) -> Result<(), Error> {
info!("Running {:?}", command);
/// Error from running Command processes
/// This captures the standard error output
#[derive(Fail, Debug)]
#[fail(display = "failed to execute `{}`: {}", command_name, fail_reason)]
pub struct CommandError {
command_name: String,
fail_reason: String,
/// the output printed to stderr, if any
pub stderr: Option<String>,
}

let status = command.status()?;
impl CommandError {
fn from_status(command_name: &str, status: ExitStatus, stderr: Option<String>) -> CommandError {
CommandError {
command_name: command_name.to_string(),
fail_reason: format!("exited with {}", status),
stderr: stderr,
}
}

if status.success() {
Ok(())
} else {
bail!(
"failed to execute `{}`: exited with {}",
command_name,
status
)
fn from_error(command_name: &str, err: StdError) -> CommandError {
CommandError {
command_name: command_name.to_string(),
fail_reason: err.to_string(),
stderr: None,
}
}
}

/// Run the given command and return its stdout.
pub fn run_capture_stdout(mut command: Command, command_name: &str) -> Result<String, Error> {
/// Run the given command and return on success.
pub fn run(mut command: Command, command_name: &str) -> Result<(), CommandError> {
info!("Running {:?}", command);

let output = command
.stderr(Stdio::inherit())
let cmd_output = command
.stdin(Stdio::inherit())
.output()?;
.stdout(Stdio::inherit())
.output();
match cmd_output {
Ok(output) => {
if output.status.success() {
Ok(())
} else {
Err(CommandError::from_status(
command_name,
output.status,
Some(String::from_utf8_lossy(&output.stderr).into_owned()),
))
}
}
Err(e) => Err(CommandError::from_error(command_name, e)),
}
}

if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).into_owned())
} else {
bail!(
"failed to execute `{}`: exited with {}",
command_name,
output.status
)
/// Run the given command and return its stdout.
pub fn run_capture_stdout(
mut command: Command,
command_name: &str,
) -> Result<String, CommandError> {
info!("Running {:?}", command);

let cmd_output = command.stdin(Stdio::inherit()).output();
match cmd_output {
Ok(output) => {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).into_owned())
} else {
Err(CommandError::from_status(
command_name,
output.status,
Some(String::from_utf8_lossy(&output.stderr).into_owned()),
))
}
}
Err(e) => Err(CommandError::from_error(command_name, e)),
}
}

0 comments on commit 97fdc94

Please sign in to comment.