diff --git a/src/build.rs b/src/build.rs index f539744..1de948e 100644 --- a/src/build.rs +++ b/src/build.rs @@ -4,6 +4,7 @@ use child; use emoji; use error::Error; use failure::ResultExt; +use manifest::Crate; use progressbar::Step; use slog::Logger; use std::path::Path; @@ -36,6 +37,26 @@ pub fn check_rustc_version(step: &Step) -> Result { } } +/// Checks if `wasm-pack` is updated to the latest version +pub fn check_wasm_pack_version(step: &Step) -> Result<(), failure::Error> { + let msg = format!("{}Checking `wasm-pack` version...", emoji::PACKAGE); + PBAR.step(step, &msg); + let wasm_pack_local_version = wasm_pack_local_version(); + let wasm_pack_latest_version = Crate::return_wasm_pack_latest_version(); + match wasm_pack_local_version { + Some(lv) => { + if !(lv == wasm_pack_latest_version) { + Ok(PBAR.info(&format!("There's a newer version of wasm-pack available, the new version is: {}, you are using: {}", wasm_pack_latest_version, lv))) + } else { + Ok(()) + } + }, + None => Err(Error::WasmPackMissing { + message: "We can't figure out what your wasm-pack version is, make sure the installation path is correct.".to_string(), + }.into()), + } +} + // from https://github.com/alexcrichton/proc-macro2/blob/79e40a113b51836f33214c6d00228934b41bd4ad/build.rs#L44-L61 fn rustc_minor_version() -> Option { macro_rules! otry { @@ -55,6 +76,29 @@ fn rustc_minor_version() -> Option { otry!(pieces.next()).parse().ok() } +fn wasm_pack_local_version() -> Option { + macro_rules! otry { + ($e:expr) => { + match $e { + Some(e) => e, + None => return None, + } + }; + } + + let output = otry!(Command::new("wasm-pack").arg("--version").output().ok()); + let version = otry!(str::from_utf8(&output.stdout).ok()); + let mut pieces = version.split(' '); + if pieces.next() != Some("wasm-pack") { + return None; + } + otry!(pieces.next()) + .to_string() + .trim() + .parse::() + .ok() +} + /// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for /// current toolchain pub fn rustup_add_wasm_target(log: &Logger, step: &Step) -> Result<(), failure::Error> { diff --git a/src/command/build.rs b/src/command/build.rs index be1de72..1de9538 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -160,6 +160,7 @@ impl Build { match &mode { BuildMode::Normal => steps![ step_check_rustc_version, + step_check_wasm_pack_version, step_check_crate_config, step_add_wasm_target, step_build_wasm, @@ -171,6 +172,7 @@ impl Build { ], BuildMode::Noinstall => steps![ step_check_rustc_version, + step_check_wasm_pack_version, step_check_crate_config, step_build_wasm, step_create_dir, @@ -200,6 +202,18 @@ impl Build { Ok(()) } + fn step_check_wasm_pack_version( + &mut self, + step: &Step, + log: &Logger, + ) -> Result<(), failure::Error> { + info!(&log, "Checking wasm-pack version..."); + let version = build::check_wasm_pack_version(step)?; + let msg = format!("wasm-pack version is: {:?}.", version); + info!(&log, "{}", &msg); + Ok(()) + } + fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { info!(&log, "Checking crate configuration..."); manifest::check_crate_config(&self.crate_path, step)?; diff --git a/src/error.rs b/src/error.rs index 4fcc513..c9bd808 100644 --- a/src/error.rs +++ b/src/error.rs @@ -46,6 +46,24 @@ pub enum Error { local_minor_version: String, }, + #[fail(display = "{}", _0)] + /// An error in parsing your wasm-pack version. + WasmPackMissing { + /// Error message + message: String, + }, + + #[fail(display = "{}", _0)] + /// An error from having an older wasm-pack version. + WasmPackVersion { + /// Error message + message: String, + /// Local version of wasm-pack + local_version: String, + /// Latest version of wasm-pack + latest_version: String, + }, + /// An error invoking another CLI tool. #[fail( display = "Process exited with {}: {}.\n\nstdout:{}\n\nstderr:\n\n{}", @@ -163,6 +181,14 @@ impl Error { message: _, local_minor_version: _, } => "Your rustc version is not supported. Please install version 1.30.0 or higher.", + Error::WasmPackMissing { + message: _, + } => "We can't figure out what your wasm-pack version is, make sure the installation path is correct.", + Error::WasmPackVersion { + message: _, + local_version: _, + latest_version: _, + } => "There's a newer version of wasm-pack available, the new version is: , you are using: ", Error::Cli { message: _, stdout: _, diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index f253b15..3f71fbf 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -10,14 +10,25 @@ use std::path::Path; use self::npm::{ repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage, }; +use curl::easy; use emoji; use error::Error; use failure; use progressbar::Step; use serde_json; use toml; + use PBAR; +struct Collector(Vec); + +impl easy::Handler for Collector { + fn write(&mut self, data: &[u8]) -> Result { + self.0.extend_from_slice(data); + Ok(data.len()) + } +} + #[derive(Debug, Deserialize)] struct CargoManifest { package: CargoPackage, @@ -77,6 +88,39 @@ struct CargoLib { crate_type: Option>, } +/// Struct for crates.io api, currently checking wasm-pack latest version +#[derive(Deserialize, Debug)] +pub struct Crate { + #[serde(rename = "crate")] + crt: CrateInformation, +} + +#[derive(Deserialize, Debug)] +struct CrateInformation { + max_version: String, +} + +impl Crate { + /// Call to the crates.io api and return the latest version of `wasm-pack` + pub fn return_wasm_pack_latest_version() -> String { + let crt = Crate::check_wasm_pack_latest_version(); + crt.crt.max_version + } + + fn check_wasm_pack_latest_version() -> Crate { + let mut easy = easy::Easy2::new(Collector(Vec::new())); + easy.get(true).unwrap(); + easy.url("https://crates.io/api/v1/crates/wasm-pack") + .unwrap(); + easy.perform().unwrap(); + + let contents = easy.get_ref(); + let result = String::from_utf8_lossy(&contents.0); + + serde_json::from_str(result.into_owned().as_str()).unwrap() + } +} + fn read_cargo_toml(path: &Path) -> Result { let manifest_path = path.join("Cargo.toml"); if !manifest_path.is_file() {