diff --git a/Cargo.lock b/Cargo.lock index 001ef1e..4ef603c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,7 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "is_executable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "zip 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -443,6 +444,14 @@ dependencies = [ "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "is_executable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.3" @@ -1401,6 +1410,7 @@ dependencies = [ "checksum human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21638c5955a6daf3ecc42cae702335fc37a72a4abcc6959ce457b31a7d43bbdd" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum indicatif 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a29b2fa6f00010c268bface64c18bb0310aaa70d46a195d5382d288c477fb016" +"checksum is_executable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "302d553b8abc8187beb7d663e34c065ac4570b273bc9511a50e940e99409c577" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" diff --git a/binary-install/Cargo.toml b/binary-install/Cargo.toml index a14b484..b735cea 100644 --- a/binary-install/Cargo.toml +++ b/binary-install/Cargo.toml @@ -14,6 +14,7 @@ dirs = "1.0.4" failure = "0.1.2" flate2 = "1.0.2" hex = "0.3" +is_executable = "0.1.2" siphasher = "0.2.3" tar = "0.4.16" zip = "0.5.0" diff --git a/binary-install/src/lib.rs b/binary-install/src/lib.rs index c2dcf2c..eac1c98 100644 --- a/binary-install/src/lib.rs +++ b/binary-install/src/lib.rs @@ -6,6 +6,7 @@ extern crate failure; extern crate dirs; extern crate flate2; extern crate hex; +extern crate is_executable; extern crate siphasher; extern crate tar; extern crate zip; @@ -223,13 +224,22 @@ impl Download { } /// Returns the path to the binary `name` within this download - pub fn binary(&self, name: &str) -> PathBuf { + pub fn binary(&self, name: &str) -> Result { + use is_executable::IsExecutable; + let ret = self .root .join(name) .with_extension(env::consts::EXE_EXTENSION); - assert!(ret.exists(), "binary {} doesn't exist", ret.display()); - return ret; + + if !ret.is_file() { + bail!("{} binary does not exist", ret.display()); + } + if !ret.is_executable() { + bail!("{} is not executable", ret.display()); + } + + Ok(ret) } } diff --git a/src/bindgen.rs b/src/bindgen.rs index 5263a75..3bc2946 100644 --- a/src/bindgen.rs +++ b/src/bindgen.rs @@ -9,6 +9,7 @@ use log::debug; use log::{info, warn}; use manifest::CrateData; use progressbar::Step; +use std::env; use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; @@ -101,9 +102,19 @@ pub fn cargo_install_wasm_bindgen( version: &str, install_permitted: bool, ) -> Result { + debug!( + "Attempting to use a `cargo install`ed version of `wasm-bindgen={}`", + version + ); + let dirname = format!("wasm-bindgen-cargo-install-{}", version); let destination = cache.join(dirname.as_ref()); if destination.exists() { + debug!( + "`cargo install`ed `wasm-bindgen={}` already exists at {}", + version, + destination.display() + ); return Ok(Download::at(&destination)); } @@ -115,7 +126,12 @@ pub fn cargo_install_wasm_bindgen( // and ensure we don't accidentally use stale files in the future let tmp = cache.join(format!(".{}", dirname).as_ref()); drop(fs::remove_dir_all(&tmp)); - fs::create_dir_all(&tmp)?; + debug!( + "cargo installing wasm-bindgen to tempdir: {}", + tmp.display() + ); + fs::create_dir_all(&tmp) + .context("failed to create temp dir for `cargo install wasm-bindgen`")?; let mut cmd = Command::new("cargo"); cmd.arg("install") @@ -128,7 +144,28 @@ pub fn cargo_install_wasm_bindgen( child::run(cmd, "cargo install").context("Installing wasm-bindgen with cargo")?; + // `cargo install` will put the installed binaries in `$root/bin/*`, but we + // just want them in `$root/*` directly (which matches how the tarballs are + // laid out, and where the rest of our code expects them to be). So we do a + // little renaming here. + for f in ["wasm-bindgen", "wasm-bindgen-test-runner"].iter().cloned() { + let from = tmp + .join("bin") + .join(f) + .with_extension(env::consts::EXE_EXTENSION); + let to = tmp.join(from.file_name().unwrap()); + fs::rename(&from, &to).with_context(|_| { + format!( + "failed to move {} to {} for `cargo install`ed `wasm-bindgen`", + from.display(), + to.display() + ) + })?; + } + + // Finally, move the `tmp` directory into our binary cache. fs::rename(&tmp, &destination)?; + Ok(Download::at(&destination)) } @@ -170,7 +207,7 @@ pub fn wasm_bindgen_build( "no-modules" => "--no-modules", _ => "--browser", }; - let bindgen_path = bindgen.binary("wasm-bindgen"); + let bindgen_path = bindgen.binary("wasm-bindgen")?; let mut cmd = Command::new(bindgen_path); cmd.arg(&wasm_path) .arg("--out-dir") diff --git a/src/command/test.rs b/src/command/test.rs index 71f3f21..e0837b1 100644 --- a/src/command/test.rs +++ b/src/command/test.rs @@ -288,7 +288,7 @@ impl Test { let dl = bindgen::install_wasm_bindgen(&self.cache, &bindgen_version, install_permitted, step)?; - self.test_runner_path = Some(dl.binary("wasm-bindgen-test-runner")); + self.test_runner_path = Some(dl.binary("wasm-bindgen-test-runner")?); info!("Getting wasm-bindgen-cli was successful."); Ok(()) diff --git a/src/test/webdriver.rs b/src/test/webdriver.rs index 9fc3c56..54e2968 100644 --- a/src/test/webdriver.rs +++ b/src/test/webdriver.rs @@ -47,7 +47,7 @@ pub fn install_chromedriver( &["chromedriver"], &url, )? { - Some(dl) => Ok(dl.binary("chromedriver")), + Some(dl) => Ok(dl.binary("chromedriver")?), None => bail!( "No cached `chromedriver` binary found, and could not find a global \ `chromedriver` on the `$PATH`. Not installing `chromedriver` because of noinstall \ @@ -97,7 +97,7 @@ pub fn install_geckodriver( ext, ); match cache.download(installation_allowed, "geckodriver", &["geckodriver"], &url)? { - Some(dl) => Ok(dl.binary("geckodriver")), + Some(dl) => Ok(dl.binary("geckodriver")?), None => bail!( "No cached `geckodriver` binary found, and could not find a global `geckodriver` \ on the `$PATH`. Not installing `geckodriver` because of noinstall mode." diff --git a/tests/all/bindgen.rs b/tests/all/bindgen.rs index e935b8a..3f04450 100644 --- a/tests/all/bindgen.rs +++ b/tests/all/bindgen.rs @@ -12,8 +12,8 @@ fn can_download_prebuilt_wasm_bindgen() { let dir = tempfile::TempDir::new().unwrap(); let cache = Cache::at(dir.path()); let dl = bindgen::download_prebuilt_wasm_bindgen(&cache, "0.2.21", true).unwrap(); - assert!(dl.binary("wasm-bindgen").is_file()); - assert!(dl.binary("wasm-bindgen-test-runner").is_file()) + assert!(dl.binary("wasm-bindgen").unwrap().is_file()); + assert!(dl.binary("wasm-bindgen-test-runner").unwrap().is_file()) } #[test] diff --git a/tests/all/utils/fixture.rs b/tests/all/utils/fixture.rs index f98b2e2..def8e8c 100644 --- a/tests/all/utils/fixture.rs +++ b/tests/all/utils/fixture.rs @@ -185,7 +185,7 @@ impl Fixture { INSTALL_WASM_BINDGEN.call_once(|| { download().unwrap(); }); - download().unwrap().binary("wasm-bindgen") + download().unwrap().binary("wasm-bindgen").unwrap() } /// Download `geckodriver` and return its path.