feat(refactor/early abort): Exit early on failure

This commit does quite a few things in order to get this to work:

1. We move all of the code dealing with knowing which command to run
   into it's own function. This wrapper command allows us to always
   close out PBAR before dumping error output. This fixes a problem
   where stderr and stdout were borked and not printing out error
   messages correctly.
2. We then refactor the code that has a panic to return early with that
   error message.
3. If the command we ran errored, we print out with PBAR that there was
   an error with the program we ran (not wasm-pack itself) then dump the
   stderr from the command to the actual stderr

This means we can abort early on without continuing any of the other
parts of wasm-pack and let the user know what the error was rather than
just saying "There's an error"
master
Michael Gattozzi 7 years ago
parent c8d4221c05
commit d043c384e7
  1. 29
      src/bindgen.rs
  2. 31
      src/build.rs
  3. 42
      src/command.rs
  4. 1
      src/lib.rs
  5. 14
      src/main.rs
  6. 27
      src/npm.rs
  7. 176
      tests/fixtures/no-compile/Cargo.lock
  8. 13
      tests/fixtures/no-compile/Cargo.toml
  9. 2
      tests/fixtures/no-compile/README.md
  10. 15
      tests/fixtures/no-compile/src/lib.rs

@ -1,24 +1,31 @@
use console::style;
use emoji;
use failure::Error;
use std::process::Command;
use PBAR;
pub fn cargo_install_wasm_bindgen() {
pub fn cargo_install_wasm_bindgen() -> Result<(), Error> {
let step = format!(
"{} {}Installing WASM-bindgen...",
style("[6/7]").bold().dim(),
emoji::DOWN_ARROW
);
let pb = PBAR.message(&step);
let _output = Command::new("cargo")
let output = Command::new("cargo")
.arg("install")
.arg("wasm-bindgen")
.output()
.unwrap_or_else(|e| panic!("{} failed to execute process: {}", emoji::ERROR, e));
.output()?;
pb.finish();
if !output.status.success() {
let s = String::from_utf8_lossy(&output.stderr);
PBAR.error("npm_publish failed");
bail!(format!("stderr was {}", s));
} else {
Ok(())
}
}
pub fn wasm_bindgen_build(path: &str, name: &str) {
pub fn wasm_bindgen_build(path: &str, name: &str) -> Result<(), Error> {
let step = format!(
"{} {}Running WASM-bindgen...",
style("[7/7]").bold().dim(),
@ -27,12 +34,18 @@ pub fn wasm_bindgen_build(path: &str, name: &str) {
let pb = PBAR.message(&step);
let binary_name = name.replace("-", "_");
let wasm_path = format!("target/wasm32-unknown-unknown/release/{}.wasm", binary_name);
let _output = Command::new("wasm-bindgen")
let output = Command::new("wasm-bindgen")
.current_dir(path)
.arg(&wasm_path)
.arg("--out-dir")
.arg("./pkg")
.output()
.unwrap_or_else(|e| panic!("{} failed to execute process: {}", emoji::ERROR, e));
.output()?;
pb.finish();
if !output.status.success() {
let s = String::from_utf8_lossy(&output.stderr);
PBAR.error("npm_publish failed");
bail!(format!("stderr was {}", s));
} else {
Ok(())
}
}

@ -1,9 +1,10 @@
use console::style;
use emoji;
use failure::Error;
use std::process::Command;
use PBAR;
pub fn rustup_add_wasm_target() {
pub fn rustup_add_wasm_target() -> Result<(), Error> {
let step = format!(
"{} {}Adding WASM target...",
style("[1/7]").bold().dim(),
@ -14,21 +15,18 @@ pub fn rustup_add_wasm_target() {
.arg("target")
.arg("add")
.arg("wasm32-unknown-unknown")
.output()
.unwrap_or_else(|e| panic!("{} failed to execute process: {}", emoji::ERROR, e));
.output()?;
pb.finish();
if !output.status.success() {
let s = String::from_utf8_lossy(&output.stderr);
print!(
"{} rustup_add_wasm_target failed and stderr was:\n{}",
emoji::ERROR,
s
);
PBAR.error("rustup_add_wasm_target failed");
bail!(format!("stderr was {}", s));
} else {
Ok(())
}
}
pub fn cargo_build_wasm(path: &str) {
pub fn cargo_build_wasm(path: &str) -> Result<(), Error> {
let step = format!(
"{} {}Compiling to WASM...",
style("[2/7]").bold().dim(),
@ -41,16 +39,13 @@ pub fn cargo_build_wasm(path: &str) {
.arg("--release")
.arg("--target")
.arg("wasm32-unknown-unknown")
.output()
.unwrap_or_else(|e| panic!("{} failed to execute process: {}", emoji::ERROR, e));
.output()?;
pb.finish();
if !output.status.success() {
let s = String::from_utf8_lossy(&output.stderr);
print!(
"{} cargo_build_wasm failed and stderr was:\n{}",
emoji::ERROR,
s
);
PBAR.error("cargo_build_wasm failed");
bail!(format!("stderr was {}", s));
} else {
Ok(())
}
}

@ -6,6 +6,7 @@ use failure::Error;
use indicatif::HumanDuration;
use manifest;
use npm;
#[allow(unused)]
use quicli::prelude::*;
use readme;
use std::fs;
@ -30,6 +31,24 @@ pub enum Command {
Publish { path: Option<String> },
}
pub fn run_wasm_pack(command: Command) -> result::Result<(), Error> {
// Run the correct command based off input and store the result of it so that we can clear
// the progress bar then return it
let status = match command {
Command::Init { path, scope } => init(path, scope),
Command::Pack { path } => pack(path),
Command::Publish { path } => publish(path),
};
// Make sure we always clear the progress bar before we abort the program otherwise
// stderr and stdout output get eaten up and nothing will work. If this part fails
// to work and clear the progress bars then you're really having a bad day with your tools.
PBAR.done()?;
// Return the actual status of the program to the main function
status
}
// quicli::prelude::* imports a different result struct which gets
// precedence over the std::result::Result, so have had to specify
// the correct type here.
@ -46,19 +65,19 @@ pub fn create_pkg_dir(path: &str) -> result::Result<(), Error> {
Ok(())
}
pub fn init(path: Option<String>, scope: Option<String>) -> result::Result<(), Error> {
fn init(path: Option<String>, scope: Option<String>) -> result::Result<(), Error> {
let started = Instant::now();
let crate_path = set_crate_path(path);
build::rustup_add_wasm_target();
build::cargo_build_wasm(&crate_path);
build::rustup_add_wasm_target()?;
build::cargo_build_wasm(&crate_path)?;
create_pkg_dir(&crate_path)?;
manifest::write_package_json(&crate_path, scope)?;
readme::copy_from_crate(&crate_path)?;
bindgen::cargo_install_wasm_bindgen();
bindgen::cargo_install_wasm_bindgen()?;
let name = manifest::get_crate_name(&crate_path)?;
bindgen::wasm_bindgen_build(&crate_path, &name);
bindgen::wasm_bindgen_build(&crate_path, &name)?;
PBAR.one_off_message(&format!(
"{} Done in {}",
emoji::SPARKLE,
@ -69,23 +88,22 @@ pub fn init(path: Option<String>, scope: Option<String>) -> result::Result<(), E
emoji::PACKAGE,
&crate_path
));
PBAR.done()?;
Ok(())
}
pub fn pack(path: Option<String>) -> result::Result<(), Error> {
fn pack(path: Option<String>) -> result::Result<(), Error> {
let crate_path = set_crate_path(path);
npm::npm_pack(&crate_path);
println!("🎒 packed up your package!");
npm::npm_pack(&crate_path)?;
PBAR.one_off_message("🎒 packed up your package!");
Ok(())
}
pub fn publish(path: Option<String>) -> result::Result<(), Error> {
fn publish(path: Option<String>) -> result::Result<(), Error> {
let crate_path = set_crate_path(path);
npm::npm_publish(&crate_path);
println!("💥 published your package!");
npm::npm_publish(&crate_path)?;
PBAR.one_off_message("💥 published your package!");
Ok(())
}

@ -1,4 +1,5 @@
extern crate console;
#[macro_use]
extern crate failure;
extern crate indicatif;
#[macro_use]

@ -5,17 +5,9 @@ extern crate indicatif;
extern crate quicli;
use quicli::prelude::*;
use wasm_pack::command::{init, pack, publish, Command};
use wasm_pack::command::run_wasm_pack;
use wasm_pack::Cli;
main!(|args: Cli, log_level: verbosity| match args.cmd {
Command::Init { path, scope } => {
init(path, scope)?;
}
Command::Pack { path } => {
pack(path)?;
}
Command::Publish { path } => {
publish(path)?;
}
main!(|args: Cli, log_level: verbosity| {
run_wasm_pack(args.cmd)?;
});

@ -1,32 +1,33 @@
use emoji;
use failure::Error;
use std::process::Command;
use PBAR;
pub fn npm_pack(path: &str) {
pub fn npm_pack(path: &str) -> Result<(), Error> {
let pkg_file_path = format!("{}/pkg", path);
let output = Command::new("npm")
.current_dir(pkg_file_path)
.arg("pack")
.output()
.unwrap_or_else(|e| panic!("{} failed to execute process: {}", emoji::ERROR, e));
.output()?;
if !output.status.success() {
let s = String::from_utf8_lossy(&output.stderr);
print!("{} npm_pack failed and stderr was:\n{}", emoji::ERROR, s);
PBAR.error("npm_pack failed");
bail!(format!("stderr was {}", s));
} else {
Ok(())
}
}
pub fn npm_publish(path: &str) {
pub fn npm_publish(path: &str) -> Result<(), Error> {
let pkg_file_path = format!("{}/pkg", path);
let output = Command::new("npm")
.current_dir(pkg_file_path)
.arg("publish")
.output()
.unwrap_or_else(|e| panic!("{} failed to execute process: {}", emoji::ERROR, e));
.output()?;
if !output.status.success() {
let s = String::from_utf8_lossy(&output.stderr);
print!(
"{} npm_publish failed and stderr was:\n{}",
emoji::ERROR,
s
);
PBAR.error("npm_publish failed");
bail!(format!("stderr was {}", s));
} else {
Ok(())
}
}

@ -0,0 +1,176 @@
[[package]]
name = "dtoa"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itoa"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "no-compile"
version = "0.1.0"
dependencies = [
"wasm-bindgen 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive_internals"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.12.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasm-bindgen"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"wasm-bindgen-macro 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-backend 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
"checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3"
"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a"
"checksum serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c73f63e08b33f6e59dfb3365b009897ebc3a3edc4af6e4f3ce8e483cf3d80ce7"
"checksum serde_derive 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9cd9e89b8be5b611971734eaf887f1da0ce1a5b51491f04b09fe855649a84f3b"
"checksum serde_derive_internals 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a79b781fe5c4a7037a10a485249a499ea02927046360afe7e04885aad2f9c10c"
"checksum serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fab6c4d75bedcf880711c85e39ebf8ccc70d0eba259899047ec5d7436643ee17"
"checksum syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5bc2d6ff27891209efa5f63e9de78648d7801f085e4653701a692ce938d6fd"
"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum wasm-bindgen 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3d40bb360252b92b57cf5ee800c92d30ae842e41d3d84bcc4fc1d3deb72d5b02"
"checksum wasm-bindgen-backend 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1a0ad26bc8fac6cbf68097e3dd4ffa40a288dda34e83bfaa7ff4626b69085d"
"checksum wasm-bindgen-macro 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3a600fa1ce92e2e8db8f89a15baf679e5bac39561e55e750cda9fb6a317e64c3"
"checksum wasm-bindgen-shared 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "aba2057a4e843cb2d754a923d46bb62aeab1531c58a78160f392e7ded8de3637"

@ -0,0 +1,13 @@
[package]
name = "no-compile"
description = "an example rust->wasm crate that can't compile"
version = "0.1.0"
authors = ["Michael Gattozzi <mgattozzi@gmail.com>"]
license = "WTFPL"
repository = "https://github.com/ashleygwilliams/wasm-pack"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.4"

@ -0,0 +1,2 @@
# no-compile
> an example rust -> wasm project that won't compile!

@ -0,0 +1,15 @@
#![feature(proc_macro, wasm_import_module, wasm_custom_section)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
fn alert(s: &str
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
Loading…
Cancel
Save