diff --git a/.appveyor.yml b/.appveyor.yml index b14e7e6..58bb395 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -5,17 +5,18 @@ environment: install: - ps: Install-Product node 10 - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly + - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain stable - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - set RUST_BACKTRACE=1 - - rustup target add wasm32-unknown-unknown --toolchain nightly + - rustup target add wasm32-unknown-unknown --toolchain stable - rustc -V - cargo -V build: false test_script: - - cargo test --release --locked + - cargo test --release --tests --locked + - cargo test --release --doc before_deploy: - ps: | diff --git a/.travis.yml b/.travis.yml index 2a4804e..09576fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,8 +38,8 @@ DEPLOY_TO_GITHUB: &DEPLOY_TO_GITHUB matrix: include: - # tests pass - - env: JOB=test RUST_BACKTRACE=1 + - name: Tests + env: RUST_BACKTRACE=1 rust: nightly addons: firefox: latest @@ -49,14 +49,14 @@ matrix: script: - cargo test --locked - rustup component add rustfmt-preview + - cargo fmt --version - cargo fmt --all -- --check - # book - - env: JOB=book + - name: Book rust: stable before_script: - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - - (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.1" mdbook) + - (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.2" mdbook) - cargo install-update -a script: - (cd docs && mdbook build) @@ -71,8 +71,8 @@ matrix: on: branch: master - # dist linux binary - - env: JOB=dist-linux TARGET=x86_64-unknown-linux-musl + - name: Linux Binary + env: TARGET=x86_64-unknown-linux-musl rust: nightly before_script: rustup target add $TARGET script: cargo build --release --target $TARGET --locked --features vendored-openssl @@ -82,8 +82,8 @@ matrix: - musl-tools <<: *DEPLOY_TO_GITHUB - # dist OSX binary - - env: JOB=dist-osx MACOSX_DEPLOYMENT_TARGET=10.7 TARGET=x86_64-apple-darwin + - name: macOS Binary + env: MACOSX_DEPLOYMENT_TARGET=10.7 TARGET=x86_64-apple-darwin os: osx rust: nightly script: cargo build --release --target $TARGET --locked diff --git a/Cargo.lock b/Cargo.lock index 2494756..2279393 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,10 +5,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -19,6 +19,23 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "argon2rs" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayvec" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.11" @@ -35,7 +52,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -55,6 +72,15 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "build_const" version = "0.2.1" @@ -62,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.6" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -85,13 +111,13 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -102,7 +128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -155,15 +181,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "clicolors-control 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "crc" version = "1.8.1" @@ -174,14 +205,14 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.36 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -189,18 +220,28 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.12.0" @@ -211,42 +252,42 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "filetime" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "flate2" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -276,16 +317,29 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "heck" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "human-panic" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "os_type 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -308,7 +362,7 @@ name = "isatty" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -335,11 +389,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "libc" @@ -348,7 +399,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libz-sys" -version = "1.0.23" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -368,17 +419,17 @@ dependencies = [ [[package]] name = "memchr" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz-sys" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -387,22 +438,21 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz_oxide_c_api" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -414,6 +464,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nodrop" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num-integer" version = "0.1.39" @@ -429,15 +484,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.12" +version = "0.10.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.36 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -447,7 +502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-src" -version = "110.0.7+1.1.0i" +version = "111.0.1+1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -455,12 +510,12 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.36" +version = "0.9.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-src 111.0.1+1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -470,7 +525,7 @@ name = "os_type" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -514,7 +569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.20" +version = "0.4.21" 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)", @@ -522,10 +577,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -576,28 +631,39 @@ dependencies = [ "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_users" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -605,15 +671,15 @@ name = "regex-syntax" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -647,10 +713,15 @@ name = "schannel" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scopeguard" version = "0.3.3" @@ -662,7 +733,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -672,17 +743,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -692,9 +763,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "slog" version = "2.4.1" @@ -735,7 +811,7 @@ name = "socket2" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -753,51 +829,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.14.9" +version = "0.15.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (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.15.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (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 = "synstructure" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -808,10 +875,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "tar" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -831,7 +898,7 @@ name = "tempfile" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -844,7 +911,7 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -887,7 +954,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -905,12 +972,17 @@ name = "toml" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ucd-util" -version = "0.1.1" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -933,7 +1005,7 @@ dependencies = [ [[package]] name = "utf8-ranges" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -941,7 +1013,7 @@ name = "uuid" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -970,24 +1042,27 @@ name = "wasm-pack" version = "0.5.1" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "console 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "indicatif 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.12 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-term 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "which 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -999,7 +1074,7 @@ name = "which" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1054,7 +1129,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1062,86 +1137,97 @@ dependencies = [ [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" +"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" +"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" "checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b" -"checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" +"checksum cargo_metadata 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1aaa1a9856ae2d188340526d0986feb6899c9ad11c5dfd73453c784fed6e373d" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" -"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum clicolors-control 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f84dec9bc083ce2503908cd305af98bd363da6f54bf8d4bf0ac14ee749ad5d1" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd48adf136733979b49e15bc3b4c43cc0d3c85ece7bd08e6daa414c6fcb13e6" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a9e5285b49b44401518c947d3b808d14d99a538a6c9ffb3ec0205c11f9fc4389" -"checksum curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08459503c415173da1ce6b41036a37b8bfdd86af46d45abb9964d4c61fe670ef" +"checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16" +"checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870" +"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" -"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" -"checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f" -"checksum flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4af030962d89d62aa52cd9492083b1cd9b2d1a77764878102a6c0f86b4d5444d" +"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" +"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" +"checksum filetime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f57e64bf5eae62efd4efed005ae81a7115012a61f522bba54542e1a556af921" +"checksum flate2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3b0c7353385f92079524de3b7116cf99d73947c08a7472774e9b3b04bff3b901" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21638c5955a6daf3ecc42cae702335fc37a72a4abcc6959ce457b31a7d43bbdd" "checksum indicatif 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a29b2fa6f00010c268bface64c18bb0310aaa70d46a195d5382d288c477fb016" "checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" "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" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" -"checksum libz-sys 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c7bdca442aa002a930e6eb2a71916cabe46d91ffec8df66db0abfb1bc83469ab" +"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" -"checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" -"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" -"checksum miniz_oxide 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba430291c9d6cedae28bcd2d49d1c32fc57d60cd49086646c5dd5673a870eb5" -"checksum miniz_oxide_c_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5a5b8234d6103ebfba71e29786da4608540f862de5ce980a1c94f86a40ca0d51" +"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" +"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" +"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" +"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729" +"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum openssl 0.10.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2e79eede055813a3ac52fb3915caf8e1c9da2dec1587871aec9f6f7b48508d" +"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)" = "c02d15268b7d1b3f0c83a2358f3d981139b54079440f1e2a29c60c1818ad5516" -"checksum openssl-sys 0.9.36 (registry+https://github.com/rust-lang/crates.io-index)" = "409d77eeb492a1aebd6eb322b2ee72ff7c7496b4434d98b3bf8be038755de65e" +"checksum openssl-src 111.0.1+1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d1edaed888fd85a54a2646bf02992931ddefdda3b1a748fc79f088a8db27fcbe" +"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" "checksum os_type 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7edc011af0ae98b7f88cf7e4a83b70a54a75d2b8cb013d6efd02e5956207e9eb" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" -"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" -"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" +"checksum proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ab2fc21ba78ac73e4ff6b3818ece00be4e175ffbef4d0a717d978b48b24150c4" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" +"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" +"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" +"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" -"checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" +"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" +"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" +"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" "checksum slog-term 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5951a808c40f419922ee014c15b6ae1cd34d963538b57d8a4778b9ca3fff1e0b" @@ -1149,13 +1235,12 @@ dependencies = [ "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ca85f2c9a5a1e2d5ac686fc0be48e40f8ad803f5bbe31f692ff71eb2dd8aad45" -"checksum structopt-derive 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "1383e5db585da799a5c4acc496c5c868e18bf82e658c00c75cc91038fa26b55f" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b10ee269228fb723234fce98e9aac0eaed2bd5f1ad2f6930e8d5b93f04445a1a" -"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" +"checksum structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "41c4a2479a078509940d82773d90ff824a8c89533ab3b59cd3ce8b0c0e369c02" +"checksum structopt-derive 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5352090cfae7a2c85e1a31146268b53396106c88ca5d6ccee2e3fae83b6e35c2" +"checksum syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)" = "90c39a061e2f412a9f869540471ab679e85e50c6b05604daf28bc3060f75c430" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" -"checksum tar 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "83b0d14b53dbfd62681933fadd651e815f99e6084b649e049ab99296e05ab3de" +"checksum tar 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "89b518542272d9c12195e72885c7a4c142b89226f681bb129e4a922ba1b1ee74" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "55c1195ef8513f3273d55ff59fe5da6940287a0d7a98331254397f464833675b" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" @@ -1166,11 +1251,12 @@ dependencies = [ "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4a2ecc31b0351ea18b3fe11274b8db6e4d82bce861bbb22e6dbed40417902c65" -"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f8bfa9ff0cadcd210129ad9d2c5f145c13e9ced3d3e5d948a6213487d52444" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" diff --git a/Cargo.toml b/Cargo.toml index 56392cf..3c210d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,10 @@ atty = "0.2.11" cargo_metadata = "0.6.0" console = "0.6.1" curl = "0.4.13" +dirs = "1.0.4" failure = "0.1.2" flate2 = "1.0.2" +hex = "0.3" human-panic = "1.0.1" indicatif = "0.9.0" lazy_static = "1.1.0" @@ -24,6 +26,7 @@ parking_lot = "0.6" serde = "1.0.74" serde_derive = "1.0.74" serde_json = "1.0.26" +siphasher = "0.2.3" slog = "2.3" slog-term = "2.4" slog-async = "2.3" @@ -32,6 +35,7 @@ tar = "0.4.16" toml = "0.4" which = "2.0.0" zip = "0.4.2" +chrono = "0.4.6" [dev-dependencies] tempfile = "3" diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 69795d3..8471174 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -18,4 +18,5 @@ - [`src/utils.rs`](./tutorial/template-deep-dive/src-utils-rs.md) - [Packaging and Publishing](./tutorial/packaging-and-publishing.md) - [Using your Library](./tutorial/using-your-library.md) +- [`Cargo.toml` Configuration](./cargo-toml-configuration.md) - [Contributing](./contributing.md) diff --git a/docs/src/cargo-toml-configuration.md b/docs/src/cargo-toml-configuration.md new file mode 100644 index 0000000..5515ecb --- /dev/null +++ b/docs/src/cargo-toml-configuration.md @@ -0,0 +1,29 @@ +# `Cargo.toml` Configuration + +`wasm-pack` can be configured via the `package.metadata.wasm-pack` key in +`Cargo.toml`. Every option has a default, and is not required. + +There are three profiles: `dev`, `profiling`, and `release`. These correspond to +the `--dev`, `--profiling`, and `--release` flags passed to `wasm-pack build`. + +The available configuration options and their default values are shown below: + +```toml +[package.metadata.wasm-pack.profile.dev.wasm-bindgen] +# Should we enable wasm-bindgen's debug assertions in its generated JS glue? +debug-js-glue = true +# Should wasm-bindgen demangle the symbols in the "name" custom section? +demangle-name-section = true +# Should we emit the DWARF debug info custom sections? +dwarf-debug-info = false + +[package.metadata.wasm-pack.profile.profiling.wasm-bindgen] +debug-js-glue = false +demangle-name-section = true +dwarf-debug-info = false + +[package.metadata.wasm-pack.profile.release.wasm-bindgen] +debug-js-glue = false +demangle-name-section = true +dwarf-debug-info = false +``` diff --git a/docs/src/commands/build.md b/docs/src/commands/build.md index 028632b..884963b 100644 --- a/docs/src/commands/build.md +++ b/docs/src/commands/build.md @@ -16,15 +16,28 @@ wasm-pack build examples/js-hello-world This path should point to a directory that contains a `Cargo.toml` file. If no path is given, the `build` command will run in the current directory. -## Debug +## Profile -The init command accepts an optional `--debug` argument. This will build the -output package using cargo's -[default non-release profile][cargo-profile-sections-documentation]. Building -this way is faster but applies few optimizations to the output, and enables -debug assertions and other runtime correctness checks. +The `build` command accepts an optional profile argument: one of `--dev`, +`--profiling`, or `--release`. If none is supplied, then `--release` is used. -The exact meaning of this flag may evolve as the platform matures. +Th controls whether debug assertions are enabled, debug info is generated, and +which (if any) optimizations are enabled. + +| Profile | Debug Assertions | Debug Info | Optimizations | Notes | +|---------------|------------------|------------|---------------|---------------------------------------| +| `--dev` | Yes | Yes | No | Useful for development and debugging. | +| `--profiling` | No | Yes | Yes | Useful when profiling and investigating performance issues. | +| `--release` | No | No | Yes | Useful for shipping to production. | + +The `--dev` profile will build the output package using cargo's [default +non-release profile][cargo-profile-sections-documentation]. Building this way is +faster but applies few optimizations to the output, and enables debug assertions +and other runtime correctness checks. The `--profiling` and `--release` profiles +use cargo's release profile, but the former enables debug info as well, which +helps when investigating performance issues in a profiler. + +The exact meaning of the profile flags may evolve as the platform matures. [cargo-profile-sections-documentation]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-profile-sections diff --git a/src/binaries.rs b/src/binaries.rs index ba7a1ec..a34c872 100644 --- a/src/binaries.rs +++ b/src/binaries.rs @@ -1,247 +1,257 @@ //! Utilities for finding and installing binaries that we depend on. use curl; -use error::Error; -use failure; +use dirs; +use failure::{Error, ResultExt}; use flate2; -use slog::Logger; +use hex; +use siphasher::sip::SipHasher13; use std::collections::HashSet; +use std::env; use std::ffi; use std::fs; +use std::hash::{Hash, Hasher}; use std::io; use std::path::{Path, PathBuf}; use tar; -use target; -use which::which; use zip; -/// Get the path for a crate's directory of locally-installed binaries. -/// -/// This does not check whether or ensure that the directory exists. -pub fn local_bin_dir(crate_path: &Path) -> PathBuf { - crate_path.join("bin") +/// Global cache for wasm-pack, currently containing binaries downloaded from +/// urls like wasm-bindgen and such. +pub struct Cache { + destination: PathBuf, } -/// Ensure that the crate's directory for locally-installed binaries exists. -pub fn ensure_local_bin_dir(crate_path: &Path) -> io::Result<()> { - fs::create_dir_all(local_bin_dir(crate_path)) +/// Representation of a downloaded tarball/zip +pub struct Download { + root: PathBuf, } -/// Get the path for where `bin` would be if we have a crate-local install for -/// it. -/// -/// This does *not* check whether there is a file at that path or not. -/// -/// This will automatically add the `.exe` extension for windows. -pub fn local_bin_path(crate_path: &Path, bin: &str) -> PathBuf { - let mut p = local_bin_dir(crate_path).join(bin); - if target::WINDOWS { - p.set_extension("exe"); +impl Cache { + /// Returns the global cache directory, as inferred from env vars and such. + /// + /// This function may return an error if a cache directory cannot be + /// determined. + pub fn new() -> Result { + let destination = dirs::cache_dir() + .map(|p| p.join("wasm-pack")) + .or_else(|| { + let home = dirs::home_dir()?; + Some(home.join(".wasm-pack")) + }) + .ok_or_else(|| format_err!("couldn't find your home directory, is $HOME not set?"))?; + Ok(Cache::at(&destination)) } - p -} -/// Get the local (at `$CRATE/bin/$BIN`; preferred) or global (on `$PATH`) path -/// for the given binary. -/// -/// If this function returns `Some(path)`, then a file at that path exists (or -/// at least existed when we checked! In general, we aren't really worried about -/// racing with an uninstall of a tool that we rely on.) -pub fn bin_path(log: &Logger, crate_path: &Path, bin: &str) -> Option { - assert!(!bin.ends_with(".exe")); - debug!(log, "Searching for {} binary...", bin); - - // Return the path to the local binary, if it exists. - let local_path = |crate_path: &Path| -> Option { - let p = local_bin_path(crate_path, bin); - debug!(log, "Checking for local {} binary at {}", bin, p.display()); - if p.is_file() { - Some(p) - } else { - None + /// Creates a new cache specifically at a particular directory, useful in + /// testing and such. + pub fn at(path: &Path) -> Cache { + Cache { + destination: path.to_path_buf(), } - }; + } - // Return the path to the global binary, if it exists. - let global_path = || -> Option { - debug!(log, "Looking for global {} binary on $PATH", bin); - if let Ok(p) = which(bin) { - Some(p) - } else { - None + /// Joins a path to the destination of this cache, returning the result + pub fn join(&self, path: &Path) -> PathBuf { + self.destination.join(path) + } + + /// Downloads a tarball or zip file from the specified url, extracting it + /// locally and returning the directory that the contents were extracted + /// into. + /// + /// Note that this function requries that the contents of `url` never change + /// as the contents of the url are globally cached on the system and never + /// invalidated. + /// + /// The `name` is a human-readable name used to go into the folder name of + /// the destination, and `binaries` is a list of binaries expected to be at + /// the url. If the URL's extraction doesn't contain all the binaries this + /// function will return an error. + pub fn download( + &self, + install_permitted: bool, + name: &str, + binaries: &[&str], + url: &str, + ) -> Result, Error> { + let mut hasher = SipHasher13::new(); + url.hash(&mut hasher); + let result = hasher.finish(); + let hex = hex::encode(&[ + (result >> 0) as u8, + (result >> 8) as u8, + (result >> 16) as u8, + (result >> 24) as u8, + (result >> 32) as u8, + (result >> 40) as u8, + (result >> 48) as u8, + (result >> 56) as u8, + ]); + let dirname = format!("{}-{}", name, hex); + + let destination = self.destination.join(&dirname); + if destination.exists() { + return Ok(Some(Download { root: destination })); } - }; - - local_path(crate_path) - .or_else(global_path) - .map(|p| { - let p = p.canonicalize().unwrap_or(p); - debug!(log, "Using {} binary at {}", bin, p.display()); - p - }) - .or_else(|| { - debug!(log, "Could not find {} binary.", bin); - None - }) -} -fn with_url_context(url: &str, r: Result) -> Result -where - Result: failure::ResultExt, -{ - use failure::ResultExt; - r.with_context(|_| format!("when requesting {}", url)) -} + if !install_permitted { + return Ok(None); + } -fn transfer( - url: &str, - easy: &mut curl::easy::Easy, - data: &mut Vec, -) -> Result<(), failure::Error> { - let mut transfer = easy.transfer(); - with_url_context( - url, - transfer.write_function(|part| { - data.extend_from_slice(part); - Ok(part.len()) - }), - )?; - with_url_context(url, transfer.perform())?; - Ok(()) -} + let data = curl(&url).with_context(|_| format!("failed to download from {}", url))?; -fn curl(url: &str) -> Result, failure::Error> { - let mut data = Vec::new(); + // Extract everything in a temporary directory in case we're ctrl-c'd. + // Don't want to leave around corrupted data! + let temp = self.destination.join(&format!(".{}", dirname)); + drop(fs::remove_dir_all(&temp)); + fs::create_dir_all(&temp)?; - let mut easy = curl::easy::Easy::new(); - with_url_context(url, easy.follow_location(true))?; - with_url_context(url, easy.url(url))?; - transfer(url, &mut easy, &mut data)?; + if url.ends_with(".tar.gz") { + self.extract_tarball(&data, &temp, binaries) + .with_context(|_| format!("failed to extract tarball from {}", url))?; + } else if url.ends_with(".zip") { + self.extract_zip(&data, &temp, binaries) + .with_context(|_| format!("failed to extract zip from {}", url))?; + } else { + // panic instead of runtime error as it's a static violation to + // download a different kind of url, all urls should be encoded into + // the binary anyway + panic!("don't know how to extract {}", url) + } - let status_code = with_url_context(url, easy.response_code())?; - if 200 <= status_code && status_code < 300 { - Ok(data) - } else { - Err(Error::http(&format!( - "received a bad HTTP status code ({}) when requesting {}", - status_code, url - )) - .into()) + // Now that everything is ready move this over to our destination and + // we're good to go. + fs::rename(&temp, &destination)?; + Ok(Some(Download { root: destination })) } -} -/// Download the `.tar.gz` file at the given URL and unpack the given binaries -/// from it into the given crate. -/// -/// Upon success, every `$BIN` in `binaries` will be at `$CRATE/bin/$BIN`. -pub fn install_binaries_from_targz_at_url<'a, I>( - crate_path: &Path, - url: &str, - binaries: I, -) -> Result<(), failure::Error> -where - I: IntoIterator, -{ - let mut binaries: HashSet<_> = binaries.into_iter().map(ffi::OsStr::new).collect(); - - let tarball = curl(&url).map_err(|e| Error::http(&e.to_string()))?; - let mut archive = tar::Archive::new(flate2::read::GzDecoder::new(&tarball[..])); - - ensure_local_bin_dir(crate_path)?; - let bin = local_bin_dir(crate_path); - - for entry in archive.entries()? { - let mut entry = entry?; - - let dest = match entry.path()?.file_stem() { - Some(f) if binaries.contains(f) => { - binaries.remove(f); - bin.join(entry.path()?.file_name().unwrap()) - } - _ => continue, - }; - - entry.unpack(dest)?; - } + fn extract_tarball(&self, tarball: &[u8], dst: &Path, binaries: &[&str]) -> Result<(), Error> { + let mut binaries: HashSet<_> = binaries.into_iter().map(ffi::OsStr::new).collect(); + let mut archive = tar::Archive::new(flate2::read::GzDecoder::new(tarball)); + + for entry in archive.entries()? { + let mut entry = entry?; + + let dest = match entry.path()?.file_stem() { + Some(f) if binaries.contains(f) => { + binaries.remove(f); + dst.join(entry.path()?.file_name().unwrap()) + } + _ => continue, + }; + + entry.unpack(dest)?; + } + + if !binaries.is_empty() { + bail!( + "the tarball was missing expected executables: {}", + binaries + .into_iter() + .map(|s| s.to_string_lossy()) + .collect::>() + .join(", "), + ) + } - if binaries.is_empty() { Ok(()) - } else { - Err(Error::archive(&format!( - "the tarball at {} was missing expected executables: {}", - url, - binaries - .into_iter() - .map(|s| s.to_string_lossy()) - .collect::>() - .join(", "), - )) - .into()) + } + + fn extract_zip(&self, zip: &[u8], dst: &Path, binaries: &[&str]) -> Result<(), Error> { + let mut binaries: HashSet<_> = binaries.into_iter().map(ffi::OsStr::new).collect(); + + let data = io::Cursor::new(zip); + let mut zip = zip::ZipArchive::new(data)?; + + for i in 0..zip.len() { + let mut entry = zip.by_index(i).unwrap(); + let entry_path = entry.sanitized_name(); + match entry_path.file_stem() { + Some(f) if binaries.contains(f) => { + binaries.remove(f); + let mut dest = bin_open_options() + .write(true) + .create_new(true) + .open(dst.join(entry_path.file_name().unwrap()))?; + io::copy(&mut entry, &mut dest)?; + } + _ => continue, + }; + } + + if !binaries.is_empty() { + bail!( + "the zip was missing expected executables: {}", + binaries + .into_iter() + .map(|s| s.to_string_lossy()) + .collect::>() + .join(", "), + ) + } + + return Ok(()); + + #[cfg(unix)] + fn bin_open_options() -> fs::OpenOptions { + use std::os::unix::fs::OpenOptionsExt; + + let mut opts = fs::OpenOptions::new(); + opts.mode(0o755); + opts + } + + #[cfg(not(unix))] + fn bin_open_options() -> fs::OpenOptions { + fs::OpenOptions::new() + } } } -/// Install binaries from within the given zip at the given URL. -/// -/// Upon success, the binaries will be at the `$CRATE/bin/$BIN` path. -pub fn install_binaries_from_zip_at_url<'a, I>( - crate_path: &Path, - url: &str, - binaries: I, -) -> Result<(), failure::Error> -where - I: IntoIterator, -{ - let mut binaries: HashSet<_> = binaries.into_iter().map(ffi::OsStr::new).collect(); - - let data = curl(&url).map_err(|e| Error::http(&e.to_string()))?; - let data = io::Cursor::new(data); - let mut zip = zip::ZipArchive::new(data)?; - - ensure_local_bin_dir(crate_path)?; - let bin = local_bin_dir(crate_path); - - for i in 0..zip.len() { - let mut entry = zip.by_index(i).unwrap(); - let entry_path = entry.sanitized_name(); - match entry_path.file_stem() { - Some(f) if binaries.contains(f) => { - binaries.remove(f); - let mut dest = bin_open_options() - .write(true) - .create_new(true) - .open(bin.join(entry_path.file_name().unwrap()))?; - io::copy(&mut entry, &mut dest)?; - } - _ => continue, - }; +impl Download { + /// Manually constructs a download at the specified path + pub fn at(path: &Path) -> Download { + Download { + root: path.to_path_buf(), + } } - if binaries.is_empty() { - Ok(()) - } else { - Err(Error::archive(&format!( - "the zip at {} was missing expected executables: {}", - url, - binaries - .into_iter() - .map(|s| s.to_string_lossy()) - .collect::>() - .join(", "), - )) - .into()) + /// Returns the path to the binary `name` within this download + pub fn binary(&self, name: &str) -> PathBuf { + let ret = self + .root + .join(name) + .with_extension(env::consts::EXE_EXTENSION); + assert!(ret.exists(), "binary {} doesn't exist", ret.display()); + return ret; } } -#[cfg(unix)] -fn bin_open_options() -> fs::OpenOptions { - use std::os::unix::fs::OpenOptionsExt; +fn curl(url: &str) -> Result, Error> { + let mut data = Vec::new(); - let mut opts = fs::OpenOptions::new(); - opts.mode(0o755); - opts -} + let mut easy = curl::easy::Easy::new(); + easy.follow_location(true)?; + easy.url(url)?; + easy.get(true)?; + { + let mut transfer = easy.transfer(); + transfer.write_function(|part| { + data.extend_from_slice(part); + Ok(part.len()) + })?; + transfer.perform()?; + } -#[cfg(not(unix))] -fn bin_open_options() -> fs::OpenOptions { - fs::OpenOptions::new() + let status_code = easy.response_code()?; + if 200 <= status_code && status_code < 300 { + Ok(data) + } else { + bail!( + "received a bad HTTP status code ({}) when requesting {}", + status_code, + url + ) + } } diff --git a/src/bindgen.rs b/src/bindgen.rs index 68e9b60..8282f6b 100644 --- a/src/bindgen.rs +++ b/src/bindgen.rs @@ -1,15 +1,18 @@ //! Functionality related to installing and running `wasm-bindgen`. -use binaries::{self, bin_path, install_binaries_from_targz_at_url}; +use binaries::{Cache, Download}; use child; +use command::build::BuildProfile; use emoji; -use error::Error; use failure::{self, ResultExt}; +use manifest::CrateData; use progressbar::Step; use slog::Logger; +use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; use target; +use which::which; use PBAR; /// Install the `wasm-bindgen` CLI. @@ -19,46 +22,66 @@ use PBAR; /// tarball from the GitHub releases page, if this target has prebuilt /// binaries. Finally, falls back to `cargo install`. pub fn install_wasm_bindgen( - root_path: &Path, + cache: &Cache, version: &str, install_permitted: bool, step: &Step, log: &Logger, -) -> Result<(), failure::Error> { - // If the `wasm-bindgen` dependency is already met, print a message and return. - if wasm_bindgen_path(log, root_path) - .map(|bindgen_path| wasm_bindgen_version_check(&bindgen_path, version, log)) - .unwrap_or(false) - { - let msg = format!("{}wasm-bindgen already installed...", emoji::DOWN_ARROW); - PBAR.step(step, &msg); - return Ok(()); - } - - // If the `wasm-bindgen` dependency was not met, and installs are not - // permitted, return a configuration error. - if !install_permitted { - let msg = format!("wasm-bindgen v{} is not installed!", version); - return Err(Error::crate_config(&msg).into()); +) -> Result { + // If `wasm-bindgen` is installed globally and it has the right version, use + // that. Assume that other tools are installed next to it. + // + // This situation can arise if `wasm-bindgen` is already installed via + // `cargo install`, for example. + if let Ok(path) = which("wasm-bindgen") { + debug!( + log, + "found global wasm-bindgen binary at: {}", + path.display() + ); + if wasm_bindgen_version_check(&path, version, log) { + return Ok(Download::at(path.parent().unwrap())); + } } let msg = format!("{}Installing wasm-bindgen...", emoji::DOWN_ARROW); PBAR.step(step, &msg); - download_prebuilt_wasm_bindgen(root_path, version).or_else(|e| { - warn!( - log, - "could not download pre-built `wasm-bindgen`: {}. Falling back to `cargo install`.", e - ); - cargo_install_wasm_bindgen(log, root_path, version) - }) + let dl = download_prebuilt_wasm_bindgen(&cache, version, install_permitted); + match dl { + Ok(dl) => return Ok(dl), + Err(e) => { + warn!( + log, + "could not download pre-built `wasm-bindgen`: {}. Falling back to `cargo install`.", + e + ); + } + } + + cargo_install_wasm_bindgen(log, &cache, version, install_permitted) } -/// Download a tarball containing a pre-built `wasm-bindgen` binary. +/// Downloads a precompiled copy of wasm-bindgen, if available. pub fn download_prebuilt_wasm_bindgen( - root_path: &Path, + cache: &Cache, version: &str, -) -> Result<(), failure::Error> { + install_permitted: bool, +) -> Result { + let url = match prebuilt_url(version) { + Some(url) => url, + None => bail!("no prebuilt wasm-bindgen binaries are available for this platform"), + }; + let binaries = &["wasm-bindgen", "wasm-bindgen-test-runner"]; + match cache.download(install_permitted, "wasm-bindgen", binaries, &url)? { + Some(download) => Ok(download), + None => bail!("wasm-bindgen v{} is not installed!", version), + } +} + +/// Returns the URL of a precompiled version of wasm-bindgen, if we have one +/// available for our host platform. +fn prebuilt_url(version: &str) -> Option { let target = if target::LINUX && target::x86_64 { "x86_64-unknown-linux-musl" } else if target::MACOS && target::x86_64 { @@ -66,32 +89,40 @@ pub fn download_prebuilt_wasm_bindgen( } else if target::WINDOWS && target::x86_64 { "x86_64-pc-windows-msvc" } else { - return Err(Error::unsupported( - "there are no pre-built `wasm-bindgen` binaries for this target", - ) - .into()); + return None; }; - let url = format!( + Some(format!( "https://github.com/rustwasm/wasm-bindgen/releases/download/{0}/wasm-bindgen-{0}-{1}.tar.gz", version, target - ); - - install_binaries_from_targz_at_url( - root_path, - &url, - vec!["wasm-bindgen", "wasm-bindgen-test-runner"], - ) + )) } /// Use `cargo install` to install the `wasm-bindgen` CLI locally into the given /// crate. pub fn cargo_install_wasm_bindgen( logger: &Logger, - crate_path: &Path, + cache: &Cache, version: &str, -) -> Result<(), failure::Error> { + install_permitted: bool, +) -> Result { + let dirname = format!("wasm-bindgen-cargo-install-{}", version); + let destination = cache.join(dirname.as_ref()); + if destination.exists() { + return Ok(Download::at(&destination)); + } + + if !install_permitted { + bail!("wasm-bindgen v{} is not installed!", version) + } + + // Run `cargo install` to a temporary location to handle ctrl-c gracefully + // 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)?; + let mut cmd = Command::new("cargo"); cmd.arg("install") .arg("--force") @@ -99,66 +130,74 @@ pub fn cargo_install_wasm_bindgen( .arg("--version") .arg(version) .arg("--root") - .arg(crate_path); + .arg(&tmp); child::run(logger, cmd, "cargo install").context("Installing wasm-bindgen with cargo")?; - assert!(binaries::local_bin_path(crate_path, "wasm-bindgen").is_file()); - Ok(()) + + fs::rename(&tmp, &destination)?; + Ok(Download::at(&destination)) } /// Run the `wasm-bindgen` CLI to generate bindings for the current crate's /// `.wasm`. pub fn wasm_bindgen_build( - path: &Path, + data: &CrateData, + bindgen: &Download, out_dir: &Path, - name: &str, disable_dts: bool, target: &str, - debug: bool, + profile: BuildProfile, step: &Step, log: &Logger, ) -> Result<(), failure::Error> { let msg = format!("{}Running WASM-bindgen...", emoji::RUNNER); PBAR.step(step, &msg); - let binary_name = name.replace("-", "_"); - let release_or_debug = if debug { "debug" } else { "release" }; + let release_or_debug = match profile { + BuildProfile::Release | BuildProfile::Profiling => "release", + BuildProfile::Dev => "debug", + }; let out_dir = out_dir.to_str().unwrap(); - if let Some(wasm_bindgen_path) = wasm_bindgen_path(log, path) { - let wasm_path = format!( - "target/wasm32-unknown-unknown/{}/{}.wasm", - release_or_debug, binary_name - ); - let dts_arg = if disable_dts { - "--no-typescript" - } else { - "--typescript" - }; - let target_arg = match target { - "nodejs" => "--nodejs", - "no-modules" => "--no-modules", - _ => "--browser", - }; - let bindgen_path = Path::new(&wasm_bindgen_path); - let mut cmd = Command::new(bindgen_path); - cmd.current_dir(path) - .arg(&wasm_path) - .arg("--out-dir") - .arg(out_dir) - .arg(dts_arg) - .arg(target_arg); - - if debug { - cmd.arg("--debug"); - } + let wasm_path = data + .target_directory() + .join("wasm32-unknown-unknown") + .join(release_or_debug) + .join(data.crate_name()) + .with_extension("wasm"); - child::run(log, cmd, "wasm-bindgen").context("Running the wasm-bindgen CLI")?; - Ok(()) + let dts_arg = if disable_dts { + "--no-typescript" } else { - Err(Error::crate_config("Could not find `wasm-bindgen`").into()) + "--typescript" + }; + let target_arg = match target { + "nodejs" => "--nodejs", + "no-modules" => "--no-modules", + _ => "--browser", + }; + let bindgen_path = bindgen.binary("wasm-bindgen"); + let mut cmd = Command::new(bindgen_path); + cmd.arg(&wasm_path) + .arg("--out-dir") + .arg(out_dir) + .arg(dts_arg) + .arg(target_arg); + + let profile = data.configured_profile(profile); + if profile.wasm_bindgen_debug_js_glue() { + cmd.arg("--debug"); } + if !profile.wasm_bindgen_demangle_name_section() { + cmd.arg("--no-demangle"); + } + if profile.wasm_bindgen_dwarf_debug_info() { + cmd.arg("--keep-debug"); + } + + child::run(log, cmd, "wasm-bindgen").context("Running the wasm-bindgen CLI")?; + Ok(()) } /// Check if the `wasm-bindgen` dependency is locally satisfied. @@ -184,16 +223,3 @@ fn wasm_bindgen_version_check(bindgen_path: &PathBuf, dep_version: &str, log: &L }) .unwrap_or(false) } - -/// Return a `PathBuf` containing the path to either the local wasm-bindgen -/// version, or the globally installed version if there is no local version. -fn wasm_bindgen_path(log: &Logger, crate_path: &Path) -> Option { - bin_path(log, crate_path, "wasm-bindgen") -} - -/// Return a `PathBuf` containing the path to either the local -/// wasm-bindgen-test-runner version, or the globally installed version if there -/// is no local version. -pub fn wasm_bindgen_test_runner_path(log: &Logger, crate_path: &Path) -> Option { - bin_path(log, crate_path, "wasm-bindgen-test-runner") -} diff --git a/src/build.rs b/src/build.rs index 1de948e..faef62b 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,9 +1,9 @@ //! Building a Rust crate into a `.wasm` binary. use child; +use command::build::BuildProfile; use emoji; -use error::Error; -use failure::ResultExt; +use failure::{Error, ResultExt}; use manifest::Crate; use progressbar::Step; use slog::Logger; @@ -13,47 +13,35 @@ use std::str; use PBAR; /// Ensure that `rustc` is present and that it is >= 1.30.0 -pub fn check_rustc_version(step: &Step) -> Result { +pub fn check_rustc_version(step: &Step) -> Result { let msg = format!("{}Checking `rustc` version...", emoji::CRAB); PBAR.step(step, &msg); let local_minor_version = rustc_minor_version(); match local_minor_version { Some(mv) => { if mv < 30 { - return Err(Error::RustcVersion { - message: format!( - "Your version of Rust, '1.{}', is not supported. Please install Rust version 1.30.0 or higher.", - mv.to_string() - ), - local_minor_version: mv.to_string(), - }.into()) + bail!( + "Your version of Rust, '1.{}', is not supported. Please install Rust version 1.30.0 or higher.", + mv.to_string() + ) } else { - Ok(mv.to_string()) + Ok(mv.to_string()) } - }, - None => Err(Error::RustcMissing { - message: "We can't figure out what your Rust version is- which means you might not have Rust installed. Please install Rust version 1.30.0 or higher.".to_string(), - }.into()), + }, + None => bail!("We can't figure out what your Rust version is- which means you might not have Rust installed. Please install Rust version 1.30.0 or higher."), } } /// 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(()) +pub fn check_wasm_pack_versions() -> Result<(String, String), Error> { + match wasm_pack_local_version() { + Some(local) => { + match Crate::return_wasm_pack_latest_version() { + Some(latest) => Ok((local, latest)), + None => Ok((local, "".to_string())) } }, - 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()), + None => bail!("We can't figure out what your wasm-pack version is, make sure the installation path is correct.") } } @@ -101,7 +89,7 @@ fn wasm_pack_local_version() -> Option { /// 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> { +pub fn rustup_add_wasm_target(log: &Logger, step: &Step) -> Result<(), Error> { let msg = format!("{}Adding WASM target...", emoji::TARGET); PBAR.step(step, &msg); let mut cmd = Command::new("rustup"); @@ -115,27 +103,37 @@ pub fn rustup_add_wasm_target(log: &Logger, step: &Step) -> Result<(), failure:: pub fn cargo_build_wasm( log: &Logger, path: &Path, - debug: bool, + profile: BuildProfile, step: &Step, -) -> Result<(), failure::Error> { +) -> Result<(), Error> { let msg = format!("{}Compiling to WASM...", emoji::CYCLONE); PBAR.step(step, &msg); let mut cmd = Command::new("cargo"); cmd.current_dir(path).arg("build").arg("--lib"); - if !debug { - cmd.arg("--release"); + match profile { + BuildProfile::Profiling => { + // Once there are DWARF debug info consumers, force enable debug + // info, because builds that use the release cargo profile disables + // debug info. + // + // cmd.env("RUSTFLAGS", "-g"); + cmd.arg("--release"); + } + BuildProfile::Release => { + cmd.arg("--release"); + } + BuildProfile::Dev => { + // Plain cargo builds use the dev cargo profile, which includes + // debug info by default. + } } cmd.arg("--target").arg("wasm32-unknown-unknown"); - child::run(log, cmd, "cargo build").context("Compiling your crate to WebAssembly")?; + child::run(log, cmd, "cargo build").context("Compiling your crate to WebAssembly failed")?; Ok(()) } /// Run `cargo build --tests` targetting `wasm32-unknown-unknown`. -pub fn cargo_build_wasm_tests( - log: &Logger, - path: &Path, - debug: bool, -) -> Result<(), failure::Error> { +pub fn cargo_build_wasm_tests(log: &Logger, path: &Path, debug: bool) -> Result<(), Error> { let mut cmd = Command::new("cargo"); cmd.current_dir(path).arg("build").arg("--tests"); if !debug { diff --git a/src/child.rs b/src/child.rs index 9b45d70..e312c20 100644 --- a/src/child.rs +++ b/src/child.rs @@ -3,8 +3,7 @@ //! This module helps us ensure that all child processes that we spawn get //! properly logged and their output is logged as well. -use error::Error; -use failure; +use failure::Error; use slog::Logger; use std::{ io::{self, Read}, @@ -120,7 +119,7 @@ pub fn run( logger: &Logger, mut command: process::Command, command_name: &str, -) -> Result { +) -> Result { info!(logger, "Running {:?}", command); let mut child = command @@ -171,7 +170,7 @@ pub fn run( if exit.success() { return Ok(stdout); } else { - let msg = format!("`{}` did not exit successfully", command_name); - return Err(Error::cli(&msg, stdout.into(), stderr.into(), exit).into()); + drop((stdout, stderr)); + bail!("failed to execute `{}`: exited with {}", command_name, exit) } } diff --git a/src/command/build.rs b/src/command/build.rs index 1de9538..701901a 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -1,10 +1,11 @@ //! Implementation of the `wasm-pack build` command. +use binaries::{Cache, Download}; use bindgen; use build; use command::utils::{create_pkg_dir, set_crate_path}; use emoji; -use error::Error; +use failure::Error; use indicatif::HumanDuration; use lockfile::Lockfile; use manifest; @@ -17,16 +18,18 @@ use std::time::Instant; use PBAR; /// Everything required to configure and run the `wasm-pack init` command. -pub(crate) struct Build { +#[allow(missing_docs)] +pub struct Build { pub crate_path: PathBuf, + pub crate_data: manifest::CrateData, pub scope: Option, pub disable_dts: bool, pub target: String, - pub debug: bool, + pub profile: BuildProfile, pub mode: BuildMode, - // build_config: Option, - pub crate_name: String, pub out_dir: PathBuf, + pub bindgen: Option, + pub cache: Cache, } /// The `BuildMode` determines which mode of initialization we are running, and @@ -55,11 +58,23 @@ impl FromStr for BuildMode { "no-install" => Ok(BuildMode::Noinstall), "normal" => Ok(BuildMode::Normal), "force" => Ok(BuildMode::Force), - _ => Err(Error::crate_config(&format!("Unknown build mode: {}", s))), + _ => bail!("Unknown build mode: {}", s), } } } +/// The build profile controls whether optimizations, debug info, and assertions +/// are enabled or disabled. +#[derive(Clone, Copy, Debug)] +pub enum BuildProfile { + /// Enable assertions and debug info. Disable optimizations. + Dev, + /// Enable optimizations. Disable assertions and debug info. + Release, + /// Enable optimizations and debug info. Disable assertions. + Profiling, +} + /// Everything required to configure and run the `wasm-pack build` command. #[derive(Debug, StructOpt)] pub struct BuildOptions { @@ -81,43 +96,71 @@ pub struct BuildOptions { pub disable_dts: bool, #[structopt(long = "target", short = "t", default_value = "browser")] - /// Sets the target environment. [possible values: browser, nodejs] + /// Sets the target environment. [possible values: browser, nodejs, no-modules] pub target: String, #[structopt(long = "debug")] - /// Build without --release. + /// Deprecated. Renamed to `--dev`. debug: bool, - // build config from manifest - // build_config: Option, + + #[structopt(long = "dev")] + /// Create a development build. Enable debug info, and disable + /// optimizations. + dev: bool, + + #[structopt(long = "release")] + /// Create a release build. Enable optimizations and disable debug info. + release: bool, + + #[structopt(long = "profiling")] + /// Create a profiling build. Enable optimizations and debug info. + profiling: bool, + #[structopt(long = "out-dir", short = "d", default_value = "pkg")] /// Sets the output directory with a relative path. pub out_dir: String, } -type BuildStep = fn(&mut Build, &Step, &Logger) -> Result<(), failure::Error>; +type BuildStep = fn(&mut Build, &Step, &Logger) -> Result<(), Error>; impl Build { /// Construct a build command from the given options. - pub fn try_from_opts(build_opts: BuildOptions) -> Result { + pub fn try_from_opts(build_opts: BuildOptions) -> Result { let crate_path = set_crate_path(build_opts.path)?; - let crate_name = manifest::get_crate_name(&crate_path)?; + let crate_data = manifest::CrateData::new(&crate_path)?; let out_dir = crate_path.join(PathBuf::from(build_opts.out_dir)); - // let build_config = manifest::xxx(&crate_path).xxx(); + + let dev = build_opts.dev || build_opts.debug; + let profile = match (dev, build_opts.release, build_opts.profiling) { + (false, false, false) | (false, true, false) => BuildProfile::Release, + (true, false, false) => BuildProfile::Dev, + (false, false, true) => BuildProfile::Profiling, + // Unfortunately, `structopt` doesn't expose clap's `conflicts_with` + // functionality yet, so we have to implement it ourselves. + _ => bail!("Can only supply one of the --dev, --release, or --profiling flags"), + }; + Ok(Build { crate_path, + crate_data, scope: build_opts.scope, disable_dts: build_opts.disable_dts, target: build_opts.target, - debug: build_opts.debug, + profile, mode: build_opts.mode, - // build_config, - crate_name, out_dir, + bindgen: None, + cache: Cache::new()?, }) } + /// Configures the global binary cache used for this build + pub fn set_cache(&mut self, cache: Cache) { + self.cache = cache; + } + /// Execute this `Build` command. - pub fn run(&mut self, log: &Logger) -> Result<(), failure::Error> { + pub fn run(&mut self, log: &Logger) -> Result<(), Error> { let process_steps = Build::get_process_steps(&self.mode); let mut step_counter = Step::new(process_steps.len()); @@ -160,7 +203,6 @@ 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, @@ -172,7 +214,6 @@ impl Build { ], BuildMode::Noinstall => steps![ step_check_rustc_version, - step_check_wasm_pack_version, step_check_crate_config, step_build_wasm, step_create_dir, @@ -190,11 +231,13 @@ impl Build { } } - fn step_check_rustc_version( - &mut self, - step: &Step, - log: &Logger, - ) -> Result<(), failure::Error> { + /// Returns local and latest versions of wasm-pack + pub fn return_wasm_pack_versions() -> Result<(String, String), Error> { + let (local, latest) = build::check_wasm_pack_versions()?; + Ok((local, latest)) + } + + fn step_check_rustc_version(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Checking rustc version..."); let version = build::check_rustc_version(step)?; let msg = format!("rustc version is {}.", version); @@ -202,35 +245,23 @@ 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> { + fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Checking crate configuration..."); - manifest::check_crate_config(&self.crate_path, step)?; + self.crate_data.check_crate_config(step)?; info!(&log, "Crate is correctly configured."); Ok(()) } - fn step_add_wasm_target(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_add_wasm_target(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Adding wasm-target..."); build::rustup_add_wasm_target(log, step)?; info!(&log, "Adding wasm-target was successful."); Ok(()) } - fn step_build_wasm(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_build_wasm(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Building wasm..."); - build::cargo_build_wasm(log, &self.crate_path, self.debug, step)?; + build::cargo_build_wasm(log, &self.crate_path, self.profile, step)?; info!( &log, @@ -244,17 +275,16 @@ impl Build { Ok(()) } - fn step_create_dir(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_create_dir(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Creating a pkg directory..."); create_pkg_dir(&self.out_dir, step)?; info!(&log, "Created a pkg directory at {:#?}.", &self.crate_path); Ok(()) } - fn step_create_json(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_create_json(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Writing a package.json..."); - manifest::write_package_json( - &self.crate_path, + self.crate_data.write_package_json( &self.out_dir, &self.scope, self.disable_dts, @@ -269,20 +299,16 @@ impl Build { Ok(()) } - fn step_copy_readme(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_copy_readme(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Copying readme from crate..."); readme::copy_from_crate(&self.crate_path, &self.out_dir, step)?; info!(&log, "Copied readme from crate to {:#?}.", &self.out_dir); Ok(()) } - fn step_install_wasm_bindgen( - &mut self, - step: &Step, - log: &Logger, - ) -> Result<(), failure::Error> { + fn step_install_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Identifying wasm-bindgen dependency..."); - let lockfile = Lockfile::new(&self.crate_path)?; + let lockfile = Lockfile::new(&self.crate_data)?; let bindgen_version = lockfile.require_wasm_bindgen()?; info!(&log, "Installing wasm-bindgen-cli..."); let install_permitted = match self.mode { @@ -290,35 +316,27 @@ impl Build { BuildMode::Force => true, BuildMode::Noinstall => false, }; - bindgen::install_wasm_bindgen( - &self.crate_path, + let bindgen = bindgen::install_wasm_bindgen( + &self.cache, &bindgen_version, install_permitted, step, log, )?; + self.bindgen = Some(bindgen); info!(&log, "Installing wasm-bindgen-cli was successful."); - - info!(&log, "Getting the crate name from the manifest..."); - self.crate_name = manifest::get_crate_name(&self.crate_path)?; - info!( - &log, - "Got crate name {:#?} from the manifest at {:#?}.", - &self.crate_name, - &self.crate_path.join("Cargo.toml") - ); Ok(()) } - fn step_run_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_run_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Building the wasm bindings..."); bindgen::wasm_bindgen_build( - &self.crate_path, + &self.crate_data, + self.bindgen.as_ref().unwrap(), &self.out_dir, - &self.crate_name, self.disable_dts, &self.target, - self.debug, + self.profile, step, log, )?; diff --git a/src/command/mod.rs b/src/command/mod.rs index ee418da..9da3aa0 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -13,11 +13,12 @@ use self::login::login; use self::pack::pack; use self::publish::{access::Access, publish}; use self::test::{Test, TestOptions}; -use error::Error; +use failure::Error; use slog::Logger; use std::path::PathBuf; use std::result; -use PBAR; +use std::sync::mpsc; +use std::thread; /// The various kinds of commands that `wasm-pack` can execute. #[derive(Debug, StructOpt)] @@ -83,10 +84,27 @@ pub enum Command { Test(TestOptions), } +/// Spawn a thread for wasm-pack version check +fn background_check_for_updates() -> mpsc::Receiver<(String, String)> { + let (sender, receiver) = mpsc::channel(); + let _detached_thread = thread::spawn(move || { + if let Ok((local, latest)) = Build::return_wasm_pack_versions() { + if !local.is_empty() && !latest.is_empty() && local != latest { + sender.send((local, latest)).unwrap(); + } + } + }); + + receiver +} + /// Run a command with the given logger! -pub fn run_wasm_pack(command: Command, log: &Logger) -> result::Result<(), failure::Error> { +pub fn run_wasm_pack(command: Command, log: &Logger) -> 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 update_available = background_check_for_updates(); + let status = match command { Command::Build(build_opts) => { info!(&log, "Running build command..."); @@ -125,17 +143,8 @@ pub fn run_wasm_pack(command: Command, log: &Logger) -> result::Result<(), failu } }; - match status { - Ok(_) => {} - Err(ref e) => { - error!(&log, "{}", e); - for c in e.iter_chain() { - if let Some(e) = c.downcast_ref::() { - PBAR.error(e.error_type()); - break; - } - } - } + if let Ok(update_available) = update_available.try_recv() { + println!("There's a newer version of wasm-pack available, the new version is: {}, you are using: {}", update_available.1, update_available.0); } // Return the actual status of the program to the main function diff --git a/src/command/pack.rs b/src/command/pack.rs index f4820fc..d9f7055 100644 --- a/src/command/pack.rs +++ b/src/command/pack.rs @@ -1,5 +1,5 @@ use command::utils::{find_pkg_directory, set_crate_path}; -use error::Error; +use failure::Error; use npm; use slog::Logger; use std::path::PathBuf; @@ -8,15 +8,16 @@ use PBAR; /// Executes the 'npm pack' command on the 'pkg' directory /// which creates a tarball that can be published to the NPM registry -pub fn pack(path: Option, log: &Logger) -> result::Result<(), failure::Error> { +pub fn pack(path: Option, log: &Logger) -> result::Result<(), Error> { let crate_path = set_crate_path(path)?; info!(&log, "Packing up the npm package..."); - let pkg_directory = find_pkg_directory(&crate_path).ok_or(Error::PkgNotFound { - message: format!( + let pkg_directory = find_pkg_directory(&crate_path).ok_or_else(|| { + format_err!( "Unable to find the pkg directory at path {:#?}, or in a child directory of {:#?}", - &crate_path, &crate_path - ), + &crate_path, + &crate_path + ) })?; npm::npm_pack(log, &pkg_directory.to_string_lossy())?; info!( diff --git a/src/command/publish/access.rs b/src/command/publish/access.rs index 980a9e0..6562e96 100644 --- a/src/command/publish/access.rs +++ b/src/command/publish/access.rs @@ -1,4 +1,4 @@ -use error::Error; +use failure::Error; use std::fmt; use std::str::FromStr; @@ -19,7 +19,7 @@ impl FromStr for Access { "public" => Ok(Access::Public), "restricted" => Ok(Access::Restricted), "private" => Ok(Access::Restricted), - _ => Err(Error::Unsupported { message: format!("{} is not a supported access level. See https://docs.npmjs.com/cli/access for more information on npm package access levels.", s)}), + _ => bail!("{} is not a supported access level. See https://docs.npmjs.com/cli/access for more information on npm package access levels.", s), } } } diff --git a/src/command/publish/mod.rs b/src/command/publish/mod.rs index 8e1acb6..8b2c564 100644 --- a/src/command/publish/mod.rs +++ b/src/command/publish/mod.rs @@ -3,7 +3,7 @@ pub mod access; use self::access::Access; use command::utils::{find_pkg_directory, set_crate_path}; -use error::Error; +use failure::Error; use npm; use slog::Logger; use std::path::PathBuf; @@ -16,16 +16,17 @@ pub fn publish( path: Option, access: Option, log: &Logger, -) -> result::Result<(), failure::Error> { +) -> result::Result<(), Error> { let crate_path = set_crate_path(path)?; info!(&log, "Publishing the npm package..."); info!(&log, "npm info located in the npm debug log"); - let pkg_directory = find_pkg_directory(&crate_path).ok_or(Error::PkgNotFound { - message: format!( + let pkg_directory = find_pkg_directory(&crate_path).ok_or_else(|| { + format_err!( "Unable to find the pkg directory at path '{:#?}', or in a child directory of '{:#?}'", - &crate_path, &crate_path - ), + &crate_path, + &crate_path + ) })?; npm::npm_publish(log, &pkg_directory.to_string_lossy(), access)?; diff --git a/src/command/test.rs b/src/command/test.rs index 507bd18..92633dd 100644 --- a/src/command/test.rs +++ b/src/command/test.rs @@ -1,12 +1,13 @@ //! Implementation of the `wasm-pack test` command. use super::build::BuildMode; +use binaries::Cache; use bindgen; use build; use command::utils::set_crate_path; use console::style; use emoji; -use error::Error; +use failure::Error; use indicatif::HumanDuration; use lockfile::Lockfile; use manifest; @@ -81,6 +82,8 @@ pub struct TestOptions { /// A configured `wasm-pack test` command. pub struct Test { crate_path: PathBuf, + crate_data: manifest::CrateData, + cache: Cache, node: bool, mode: BuildMode, firefox: bool, @@ -94,11 +97,11 @@ pub struct Test { test_runner_path: Option, } -type TestStep = fn(&mut Test, &Step, &Logger) -> Result<(), failure::Error>; +type TestStep = fn(&mut Test, &Step, &Logger) -> Result<(), Error>; impl Test { /// Construct a test command from the given options. - pub fn try_from_opts(test_opts: TestOptions) -> Result { + pub fn try_from_opts(test_opts: TestOptions) -> Result { let TestOptions { path, node, @@ -114,32 +117,24 @@ impl Test { } = test_opts; let crate_path = set_crate_path(path)?; - - // let geckodriver = get_web_driver("geckodriver", test_opts.geckodriver, test_opts.firefox)?; - // let chromedriver = - // get_web_driver("chromedriver", test_opts.chromedriver, test_opts.chrome)?; - // let safaridriver = - // get_web_driver("safaridriver", test_opts.safaridriver, test_opts.safari)?; - + let crate_data = manifest::CrateData::new(&crate_path)?; let any_browser = chrome || firefox || safari; if !node && !any_browser { - return Err(Error::crate_config( - "Must specify at least one of `--node`, `--chrome`, `--firefox`, or `--safari`", - ) - .into()); + bail!("Must specify at least one of `--node`, `--chrome`, `--firefox`, or `--safari`") } if headless && !any_browser { - return Err(Error::crate_config( + bail!( "The `--headless` flag only applies to browser tests. Node does not provide a UI, \ - so it doesn't make sense to talk about a headless version of Node tests.", + so it doesn't make sense to talk about a headless version of Node tests." ) - .into()); } Ok(Test { + cache: Cache::new()?, crate_path, + crate_data, node, mode, chrome, @@ -154,8 +149,13 @@ impl Test { }) } + /// Configures the cache that this test command uses + pub fn set_cache(&mut self, cache: Cache) { + self.cache = cache; + } + /// Execute this test command. - pub fn run(mut self, log: &Logger) -> Result<(), failure::Error> { + pub fn run(mut self, log: &Logger) -> Result<(), Error> { let process_steps = self.get_process_steps(); let mut step_counter = Step::new(process_steps.len()); @@ -188,7 +188,6 @@ impl Test { match self.mode { BuildMode::Normal => steps![ step_check_rustc_version, - step_check_crate_config, step_add_wasm_target, step_build_tests, step_install_wasm_bindgen, @@ -213,7 +212,6 @@ impl Test { step_test_safari if self.safari, ], BuildMode::Noinstall => steps![ - step_check_crate_config, step_build_tests, step_install_wasm_bindgen, step_test_node if self.node, @@ -227,32 +225,21 @@ impl Test { } } - fn step_check_rustc_version( - &mut self, - step: &Step, - log: &Logger, - ) -> Result<(), failure::Error> { + fn step_check_rustc_version(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(log, "Checking rustc version..."); let _ = build::check_rustc_version(step)?; info!(log, "Rustc version is correct."); 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)?; - info!(log, "Crate is correctly configured."); - Ok(()) - } - - fn step_add_wasm_target(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_add_wasm_target(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Adding wasm-target..."); build::rustup_add_wasm_target(log, step)?; info!(&log, "Adding wasm-target was successful."); Ok(()) } - fn step_build_tests(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_build_tests(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(log, "Compiling tests to wasm..."); let msg = format!("{}Compiling tests to WASM...", emoji::CYCLONE); @@ -264,13 +251,9 @@ impl Test { Ok(()) } - fn step_install_wasm_bindgen( - &mut self, - step: &Step, - log: &Logger, - ) -> Result<(), failure::Error> { + fn step_install_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Identifying wasm-bindgen dependency..."); - let lockfile = Lockfile::new(&self.crate_path)?; + let lockfile = Lockfile::new(&self.crate_data)?; let bindgen_version = lockfile.require_wasm_bindgen()?; // Unlike `wasm-bindgen` and `wasm-bindgen-cli`, `wasm-bindgen-test` @@ -279,13 +262,12 @@ impl Test { // `wasm32-unkown-unknown`. Don't enforce that it is the same version as // `wasm-bindgen`. if lockfile.wasm_bindgen_test_version().is_none() { - let message = format!( + bail!( "Ensure that you have \"{}\" as a dependency in your Cargo.toml file:\n\ [dev-dependencies]\n\ wasm-bindgen-test = \"0.2\"", style("wasm-bindgen-test").bold().dim(), - ); - return Err(Error::CrateConfig { message }.into()); + ) } let install_permitted = match self.mode { @@ -303,22 +285,21 @@ impl Test { } }; - bindgen::install_wasm_bindgen( - &self.crate_path, + let dl = bindgen::install_wasm_bindgen( + &self.cache, &bindgen_version, install_permitted, step, log, )?; - self.test_runner_path = Some(bindgen::wasm_bindgen_test_runner_path(log, &self.crate_path) - .expect("if installing wasm-bindgen succeeded, then we should have wasm-bindgen-test-runner too")); + self.test_runner_path = Some(dl.binary("wasm-bindgen-test-runner")); info!(&log, "Getting wasm-bindgen-cli was successful."); Ok(()) } - fn step_test_node(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_test_node(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { assert!(self.node); info!(log, "Running tests in node..."); PBAR.step(step, "Running tests in node..."); @@ -335,19 +316,18 @@ impl Test { Ok(()) } - fn step_get_chromedriver(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_get_chromedriver(&mut self, step: &Step, _log: &Logger) -> Result<(), Error> { PBAR.step(step, "Getting chromedriver..."); assert!(self.chrome && self.chromedriver.is_none()); self.chromedriver = Some(webdriver::get_or_install_chromedriver( - log, - &self.crate_path, + &self.cache, self.mode, )?); Ok(()) } - fn step_test_chrome(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_test_chrome(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { PBAR.step(step, "Running tests in Chrome..."); let chromedriver = self.chromedriver.as_ref().unwrap().display().to_string(); @@ -378,19 +358,18 @@ impl Test { Ok(()) } - fn step_get_geckodriver(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_get_geckodriver(&mut self, step: &Step, _log: &Logger) -> Result<(), Error> { PBAR.step(step, "Getting geckodriver..."); assert!(self.firefox && self.geckodriver.is_none()); self.geckodriver = Some(webdriver::get_or_install_geckodriver( - log, - &self.crate_path, + &self.cache, self.mode, )?); Ok(()) } - fn step_test_firefox(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_test_firefox(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { PBAR.step(step, "Running tests in Firefox..."); let geckodriver = self.geckodriver.as_ref().unwrap().display().to_string(); @@ -421,15 +400,15 @@ impl Test { Ok(()) } - fn step_get_safaridriver(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_get_safaridriver(&mut self, step: &Step, _log: &Logger) -> Result<(), Error> { PBAR.step(step, "Getting safaridriver..."); assert!(self.safari && self.safaridriver.is_none()); - self.safaridriver = Some(webdriver::get_safaridriver(log, &self.crate_path)?); + self.safaridriver = Some(webdriver::get_safaridriver()?); Ok(()) } - fn step_test_safari(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { + fn step_test_safari(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { PBAR.step(step, "Running tests in Safari..."); let safaridriver = self.safaridriver.as_ref().unwrap().display().to_string(); diff --git a/src/command/utils.rs b/src/command/utils.rs index 1e49d85..fee4d4f 100644 --- a/src/command/utils.rs +++ b/src/command/utils.rs @@ -4,19 +4,13 @@ use emoji; use failure; use progressbar::Step; use std::fs; -use std::io; use std::path::{Path, PathBuf}; use PBAR; /// If an explicit path is given, then use it, otherwise assume the current /// directory is the crate path. -pub fn set_crate_path(path: Option) -> io::Result { - let crate_path = match path { - Some(p) => p, - None => PathBuf::from("."), - }; - - crate_path.canonicalize() +pub fn set_crate_path(path: Option) -> Result { + Ok(path.unwrap_or(PathBuf::from("."))) } /// Construct our `pkg` directory in the crate. diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index c9bd808..0000000 --- a/src/error.rs +++ /dev/null @@ -1,240 +0,0 @@ -//! Code related to error handling for wasm-pack -use curl; -use serde_json; -use std::borrow::Cow; -use std::io; -use std::process::ExitStatus; -use toml; -use zip; - -/// Errors that can potentially occur in `wasm-pack`. -#[derive(Debug, Fail)] -pub enum Error { - /// Maps any underlying I/O errors that are thrown to this variant - #[fail(display = "{}", _0)] - Io(#[cause] io::Error), - - /// A JSON serialization or deserialization error. - #[fail(display = "{}", _0)] - SerdeJson(#[cause] serde_json::Error), - - /// A TOML serialization or deserialization error. - #[fail(display = "{}", _0)] - SerdeToml(#[cause] toml::de::Error), - - #[fail(display = "{}", _0)] - /// A curl error. - Curl(#[cause] curl::Error), - - #[fail(display = "{}", _0)] - /// An error handling zip archives. - Zip(#[cause] zip::result::ZipError), - - #[fail(display = "{}", _0)] - /// An error in parsing your rustc version. - RustcMissing { - /// Error message - message: String, - }, - - #[fail(display = "{}", _0)] - /// An error from having an unsupported rustc version. - RustcVersion { - /// Error message - message: String, - /// The minor version of the local rust - 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{}", - exit_status, - message, - stdout, - stderr - )] - Cli { - /// Error message. - message: String, - /// The underlying CLI's `stdout` output. - stdout: String, - /// The underlying CLI's `stderr` output. - stderr: String, - /// The exit status of the subprocess - exit_status: ExitStatus, - }, - - /// A crate configuration error. - #[fail(display = "{}", message)] - CrateConfig { - /// A message describing the configuration error. - message: String, - }, - - #[fail(display = "{}", message)] - /// Error when the 'pkg' directory is not found. - PkgNotFound { - /// Message describing the error. - message: String, - }, - - #[fail(display = "{}", message)] - /// An error related to an archive that we downloaded. - Archive { - /// Error message. - message: String, - }, - - #[fail(display = "{}", message)] - /// Error when some operation or feature is unsupported for the current - /// target or environment. - Unsupported { - /// Error message. - message: String, - }, - - #[fail(display = "{}", message)] - /// Error related to some HTTP request. - Http { - /// Error message. - message: String, - }, -} - -impl Error { - /// Construct a CLI error. - pub fn cli(message: &str, stdout: Cow, stderr: Cow, exit_status: ExitStatus) -> Self { - Error::Cli { - message: message.to_string(), - stdout: stdout.to_string(), - stderr: stderr.to_string(), - exit_status, - } - } - - /// Construct a crate configuration error. - pub fn crate_config(message: &str) -> Self { - Error::CrateConfig { - message: message.to_string(), - } - } - - /// Construct an archive error. - pub fn archive(message: &str) -> Self { - Error::Archive { - message: message.to_string(), - } - } - - /// Construct an unsupported error. - pub fn unsupported(message: &str) -> Self { - Error::Unsupported { - message: message.to_string(), - } - } - - /// Construct an http error. - pub fn http(message: &str) -> Self { - Error::Http { - message: message.to_string(), - } - } - - /// Construct a rustc version error. - pub fn rustc_version_error(message: &str, local_version: &str) -> Self { - Error::RustcVersion { - message: message.to_string(), - local_minor_version: local_version.to_string(), - } - } - - /// Get a string description of this error's type. - pub fn error_type(&self) -> String { - match self { - Error::Io(_) => "There was an I/O error. Details:\n\n", - Error::SerdeJson(_) => "There was an JSON error. Details:\n\n", - Error::SerdeToml(_) => "There was an TOML error. Details:\n\n", - Error::Zip(_) => "There was an error handling zip files. Details:\n\n", - Error::RustcMissing { - message: _, - } => "We can't figure out what your Rust version is- which means you might not have Rust installed. Please install Rust version 1.30.0 or higher.", - Error::RustcVersion { - 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: _, - stderr: _, - exit_status: _, - } => "There was an error while calling another CLI tool. Details:\n\n", - Error::CrateConfig { message: _ } => { - "There was a crate configuration error. Details:\n\n" - } - Error::PkgNotFound { - message: _, - } => "Unable to find the 'pkg' directory at the path, set the path as the parent of the 'pkg' directory \n\n", - Error::Curl(_) => "There was an error making an HTTP request with curl. Details:\n\n", - Error::Archive {..} => "There was an error related to an archive file. Details:\n\n", - Error::Unsupported {..} => "There was an unsupported operation attempted. Details:\n\n", - Error::Http {..} => "There wasn an HTTP error. Details:\n\n", - }.to_string() - } -} - -impl From for Error { - fn from(e: io::Error) -> Self { - Error::Io(e) - } -} - -impl From for Error { - fn from(e: curl::Error) -> Self { - Error::Curl(e) - } -} - -impl From for Error { - fn from(e: serde_json::Error) -> Self { - Error::SerdeJson(e) - } -} - -impl From for Error { - fn from(e: zip::result::ZipError) -> Self { - Error::Zip(e) - } -} - -impl From for Error { - fn from(e: toml::de::Error) -> Self { - Error::SerdeToml(e) - } -} diff --git a/src/lib.rs b/src/lib.rs index ed2e390..b30d78a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,20 +5,25 @@ extern crate cargo_metadata; extern crate console; extern crate curl; +extern crate dirs; #[macro_use] extern crate failure; extern crate flate2; +extern crate hex; extern crate indicatif; #[macro_use] extern crate lazy_static; extern crate parking_lot; +extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; +extern crate siphasher; #[macro_use] extern crate structopt; #[macro_use] extern crate slog; +extern crate chrono; extern crate slog_async; extern crate slog_term; extern crate tar; @@ -32,7 +37,6 @@ pub mod build; pub mod child; pub mod command; pub mod emoji; -pub mod error; pub mod lockfile; pub mod logger; pub mod manifest; diff --git a/src/lockfile.rs b/src/lockfile.rs index 1b2cb81..d174f6a 100644 --- a/src/lockfile.rs +++ b/src/lockfile.rs @@ -1,11 +1,11 @@ //! Reading Cargo.lock lock file. use std::fs; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; -use cargo_metadata; use console::style; -use error::Error; +use failure::{Error, ResultExt}; +use manifest::CrateData; use toml; /// This struct represents the contents of `Cargo.lock`. @@ -23,10 +23,13 @@ struct Package { impl Lockfile { /// Read the `Cargo.lock` file for the crate at the given path. - pub fn new(crate_path: &Path) -> Result { - let lock_path = get_lockfile_path(crate_path)?; - let lockfile = fs::read_to_string(lock_path)?; - toml::from_str(&lockfile).map_err(|err| Error::from(err).into()) + pub fn new(crate_data: &CrateData) -> Result { + let lock_path = get_lockfile_path(crate_data)?; + let lockfile = fs::read_to_string(&lock_path) + .with_context(|_| format!("failed to read: {}", lock_path.display()))?; + let lockfile = toml::from_str(&lockfile) + .with_context(|_| format!("failed to parse: {}", lock_path.display()))?; + Ok(lockfile) } /// Get the version of `wasm-bindgen` dependency used in the `Cargo.lock`. @@ -36,15 +39,14 @@ impl Lockfile { /// Like `wasm_bindgen_version`, except it returns an error instead of /// `None`. - pub fn require_wasm_bindgen(&self) -> Result<&str, failure::Error> { + pub fn require_wasm_bindgen(&self) -> Result<&str, Error> { self.wasm_bindgen_version().ok_or_else(|| { - let message = format!( + format_err!( "Ensure that you have \"{}\" as a dependency in your Cargo.toml file:\n\ [dependencies]\n\ wasm-bindgen = \"0.2\"", style("wasm-bindgen").bold().dim(), - ); - Error::CrateConfig { message }.into() + ) }) } @@ -63,22 +65,12 @@ impl Lockfile { /// Given the path to the crate that we are buliding, return a `PathBuf` /// containing the location of the lock file, by finding the workspace root. -fn get_lockfile_path(crate_path: &Path) -> Result { - // Identify the crate's root directory, or return an error. - let manifest = crate_path.join("Cargo.toml"); - let crate_root = cargo_metadata::metadata(Some(&manifest)) - .map_err(|_| Error::CrateConfig { - message: String::from("Error while processing crate metadata"), - })? - .workspace_root; +fn get_lockfile_path(crate_data: &CrateData) -> Result { // Check that a lock file can be found in the directory. Return an error // if it cannot, otherwise return the path buffer. - let lockfile_path = Path::new(&crate_root).join("Cargo.lock"); + let lockfile_path = crate_data.workspace_root().join("Cargo.lock"); if !lockfile_path.is_file() { - Err(Error::CrateConfig { - message: format!("Could not find lockfile at {:?}", lockfile_path), - } - .into()) + bail!("Could not find lockfile at {:?}", lockfile_path) } else { Ok(lockfile_path) } diff --git a/src/main.rs b/src/main.rs index c929539..0af8296 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod installer; fn main() { setup_panic!(); if let Err(e) = run() { - eprintln!("{}", e); + eprintln!("Error: {}", e); for cause in e.iter_causes() { eprintln!("Caused by: {}", cause); } diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 3f71fbf..d2c6f95 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -2,24 +2,34 @@ mod npm; -use std::collections::HashMap; -use std::fs::File; -use std::io::prelude::*; +use std::fs; use std::path::Path; use self::npm::{ repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage, }; +use cargo_metadata::Metadata; +use chrono::offset; +use chrono::DateTime; +use command::build::BuildProfile; use curl::easy; use emoji; -use error::Error; -use failure; +use failure::{Error, ResultExt}; use progressbar::Step; +use serde::{self, Deserialize}; use serde_json; +use std::io::Write; use toml; - +use which; use PBAR; +/// Store for metadata learned about a crate +pub struct CrateData { + data: Metadata, + current_idx: usize, + manifest: CargoManifest, +} + struct Collector(Vec); impl easy::Handler for Collector { @@ -29,66 +39,86 @@ impl easy::Handler for Collector { } } -#[derive(Debug, Deserialize)] +#[derive(Deserialize)] struct CargoManifest { package: CargoPackage, - dependencies: Option>, - #[serde(rename = "dev-dependencies")] - dev_dependencies: Option>, - lib: Option, } -#[derive(Debug, Deserialize)] +#[derive(Deserialize)] struct CargoPackage { name: String, - authors: Vec, description: Option, - version: String, license: Option, repository: Option, + + #[serde(default)] + metadata: CargoMetadata, } -impl CargoPackage { - fn check_optional_fields(&self) { - let mut messages = vec![]; - if self.description.is_none() { - messages.push("description"); - } - if self.repository.is_none() { - messages.push("repository"); - } - if self.license.is_none() { - messages.push("license"); - } +#[derive(Default, Deserialize)] +struct CargoMetadata { + #[serde(default, rename = "wasm-pack")] + wasm_pack: CargoWasmPack, +} - match messages.len() { - 1 => PBAR.info(&format!("Optional field missing from Cargo.toml: '{}'. This is not necessary, but recommended", messages[0])), - 2 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}'. These are not necessary, but recommended", messages[0], messages[1])), - 3 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}', and '{}'. These are not necessary, but recommended", messages[0], messages[1], messages[2])), - _ => () - }; - } +#[derive(Default, Deserialize)] +struct CargoWasmPack { + #[serde(default)] + profile: CargoWasmPackProfiles, } -#[derive(Debug, Deserialize)] -#[serde(untagged)] -enum CargoDependency { - Simple(String), - Detailed(DetailedCargoDependency), +#[derive(Deserialize)] +struct CargoWasmPackProfiles { + #[serde( + default = "CargoWasmPackProfile::default_dev", + deserialize_with = "CargoWasmPackProfile::deserialize_dev" + )] + dev: CargoWasmPackProfile, + + #[serde( + default = "CargoWasmPackProfile::default_release", + deserialize_with = "CargoWasmPackProfile::deserialize_release" + )] + release: CargoWasmPackProfile, + + #[serde( + default = "CargoWasmPackProfile::default_profiling", + deserialize_with = "CargoWasmPackProfile::deserialize_profiling" + )] + profiling: CargoWasmPackProfile, } -#[derive(Debug, Deserialize)] -struct DetailedCargoDependency { - version: Option, +impl Default for CargoWasmPackProfiles { + fn default() -> CargoWasmPackProfiles { + CargoWasmPackProfiles { + dev: CargoWasmPackProfile::default_dev(), + release: CargoWasmPackProfile::default_release(), + profiling: CargoWasmPackProfile::default_profiling(), + } + } } -#[derive(Debug, Deserialize)] -struct CargoLib { - #[serde(rename = "crate-type")] - crate_type: Option>, +/// This is where configuration goes for wasm-bindgen, wasm-opt, wasm-snip, or +/// anything else that wasm-pack runs. +#[derive(Default, Deserialize)] +pub struct CargoWasmPackProfile { + #[serde(default, rename = "wasm-bindgen")] + wasm_bindgen: CargoWasmPackProfileWasmBindgen, } -/// Struct for crates.io api, currently checking wasm-pack latest version +#[derive(Default, Deserialize)] +struct CargoWasmPackProfileWasmBindgen { + #[serde(default, rename = "debug-js-glue")] + debug_js_glue: Option, + + #[serde(default, rename = "demangle-name-section")] + demangle_name_section: Option, + + #[serde(default, rename = "dwarf-debug-info")] + dwarf_debug_info: Option, +} + +/// Struct for crate which is received from crates.io #[derive(Deserialize, Debug)] pub struct Crate { #[serde(rename = "crate")] @@ -101,209 +131,464 @@ struct CrateInformation { } 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 + /// Returns latest wasm-pack version + pub fn return_wasm_pack_latest_version() -> Option { + let current_time = chrono::offset::Local::now(); + if let Some(contents) = Crate::return_wasm_pack_file() { + let (created, version) = Crate::return_stamp_file_values(&contents); + + if current_time.signed_duration_since(created).num_hours() > 24 { + return Crate::return_api_call_result(current_time); + } else { + return Some(version); + } + } else { + return Crate::return_api_call_result(current_time); + } } - 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") + fn return_api_call_result(current_time: DateTime) -> Option { + match Crate::call_for_wasm_pack_version() { + Some(version) => { + Crate::override_stamp_file(current_time, &version); + return Some(version); + } + None => return None, + } + } + + fn override_stamp_file(current_time: DateTime, version: &String) { + if let Ok(path) = which::which("wasm-pack") { + let file = fs::OpenOptions::new() + .read(true) + .write(true) + .append(true) + .create(true) + .open(path.with_extension("stamp")); + + if let Ok(()) = file.as_ref().unwrap().set_len(0) { + if let Err(_) = write!( + file.unwrap(), + "created {:?}\nversion {}", + current_time, + version + ) {} + } + } + } + + fn return_wasm_pack_file() -> Option { + if let Ok(path) = which::which("wasm-pack") { + if let Ok(file) = fs::read_to_string(path.with_extension("stamp")) { + return Some(file); + } + return None; + } + None + } + + fn call_for_wasm_pack_version() -> Option { + if let Ok(crt) = Crate::check_wasm_pack_latest_version() { + return Some(crt.crt.max_version); + } + None + } + + fn return_stamp_file_values(file: &String) -> (DateTime, String) { + let created = file + .lines() + .find(|line| line.starts_with("created")) + .unwrap() + .split_whitespace() + .nth(1) .unwrap(); - easy.perform().unwrap(); + let last_updated = DateTime::parse_from_str(created, "%+").unwrap(); + + let version = file + .lines() + .find(|line| line.starts_with("version")) + .unwrap() + .split_whitespace() + .nth(1) + .unwrap() + .to_string(); + + (last_updated, version) + } + + /// Call to the crates.io api and return the latest version of `wasm-pack` + fn check_wasm_pack_latest_version() -> Result { + let mut easy = easy::Easy2::new(Collector(Vec::new())); + easy.get(true)?; + easy.url("https://crates.io/api/v1/crates/wasm-pack")?; + easy.perform()?; let contents = easy.get_ref(); let result = String::from_utf8_lossy(&contents.0); + Ok(serde_json::from_str(result.into_owned().as_str())?) + } +} + +impl CargoWasmPackProfile { + fn default_dev() -> Self { + CargoWasmPackProfile { + wasm_bindgen: CargoWasmPackProfileWasmBindgen { + debug_js_glue: Some(true), + demangle_name_section: Some(true), + dwarf_debug_info: Some(false), + }, + } + } + + fn default_release() -> Self { + CargoWasmPackProfile { + wasm_bindgen: CargoWasmPackProfileWasmBindgen { + debug_js_glue: Some(false), + demangle_name_section: Some(true), + dwarf_debug_info: Some(false), + }, + } + } + + fn default_profiling() -> Self { + CargoWasmPackProfile { + wasm_bindgen: CargoWasmPackProfileWasmBindgen { + debug_js_glue: Some(false), + demangle_name_section: Some(true), + dwarf_debug_info: Some(false), + }, + } + } + + fn deserialize_dev<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut profile = >::deserialize(deserializer)?.unwrap_or_default(); + profile.update_with_defaults(Self::default_dev()); + Ok(profile) + } + + fn deserialize_release<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut profile = >::deserialize(deserializer)?.unwrap_or_default(); + profile.update_with_defaults(Self::default_release()); + Ok(profile) + } + + fn deserialize_profiling<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut profile = >::deserialize(deserializer)?.unwrap_or_default(); + profile.update_with_defaults(Self::default_profiling()); + Ok(profile) + } + + fn update_with_defaults(&mut self, defaults: Self) { + macro_rules! d { + ( $( $path:ident ).* ) => { + self. $( $path ).* .get_or_insert(defaults. $( $path ).* .unwrap()); + } + } + d!(wasm_bindgen.debug_js_glue); + d!(wasm_bindgen.demangle_name_section); + d!(wasm_bindgen.dwarf_debug_info); + } + + /// Get this profile's configured `[wasm-bindgen.debug-js-glue]` value. + pub fn wasm_bindgen_debug_js_glue(&self) -> bool { + self.wasm_bindgen.debug_js_glue.unwrap() + } - serde_json::from_str(result.into_owned().as_str()).unwrap() + /// Get this profile's configured `[wasm-bindgen.demangle-name-section]` value. + pub fn wasm_bindgen_demangle_name_section(&self) -> bool { + self.wasm_bindgen.demangle_name_section.unwrap() + } + + /// Get this profile's configured `[wasm-bindgen.dwarf-debug-info]` value. + pub fn wasm_bindgen_dwarf_debug_info(&self) -> bool { + self.wasm_bindgen.dwarf_debug_info.unwrap() } } -fn read_cargo_toml(path: &Path) -> Result { - let manifest_path = path.join("Cargo.toml"); - if !manifest_path.is_file() { - return Err(Error::crate_config(&format!( - "Crate directory is missing a `Cargo.toml` file; is `{}` the wrong directory?", - path.display() - )) - .into()); - } - let mut cargo_file = File::open(manifest_path)?; - let mut cargo_contents = String::new(); - cargo_file.read_to_string(&mut cargo_contents)?; - - let manifest: CargoManifest = toml::from_str(&cargo_contents)?; - Ok(manifest) +struct NpmData { + name: String, + files: Vec, + dts_file: Option, + main: String, } -impl CargoManifest { - fn into_commonjs(mut self, scope: &Option, disable_dts: bool) -> NpmPackage { - let filename = self.package.name.replace("-", "_"); - let wasm_file = format!("{}_bg.wasm", filename); - let js_file = format!("{}.js", filename); - let mut files = vec![wasm_file]; +impl CrateData { + /// Reads all metadata for the crate whose manifest is inside the directory + /// specified by `path`. + pub fn new(crate_path: &Path) -> Result { + let manifest_path = crate_path.join("Cargo.toml"); + if !manifest_path.is_file() { + bail!( + "crate directory is missing a `Cargo.toml` file; is `{}` the \ + wrong directory?", + crate_path.display() + ) + } + let manifest = fs::read_to_string(&manifest_path) + .with_context(|_| format!("failed to read: {}", manifest_path.display()))?; + let manifest: CargoManifest = toml::from_str(&manifest) + .with_context(|_| format!("failed to parse manifest: {}", manifest_path.display()))?; + + let data = + cargo_metadata::metadata(Some(&manifest_path)).map_err(error_chain_to_failure)?; + + let current_idx = data + .packages + .iter() + .position(|pkg| pkg.name == manifest.package.name) + .ok_or_else(|| format_err!("failed to find package in metadata"))?; + + return Ok(CrateData { + data, + manifest, + current_idx, + }); + + fn error_chain_to_failure(err: cargo_metadata::Error) -> Error { + let errors = err.iter().collect::>(); + let mut err: Error = match errors.last() { + Some(e) => format_err!("{}", e), + None => return format_err!("{}", err), + }; + for e in errors[..errors.len() - 1].iter().rev() { + err = err.context(e.to_string()).into(); + } + return err; + } + } + + /// Get the configured profile. + pub fn configured_profile(&self, profile: BuildProfile) -> &CargoWasmPackProfile { + match profile { + BuildProfile::Dev => &self.manifest.package.metadata.wasm_pack.profile.dev, + BuildProfile::Profiling => &self.manifest.package.metadata.wasm_pack.profile.profiling, + BuildProfile::Release => &self.manifest.package.metadata.wasm_pack.profile.release, + } + } - let js_bg_file = format!("{}_bg.js", filename); - files.push(js_bg_file.to_string()); + /// Check that the crate the given path is properly configured. + pub fn check_crate_config(&self, step: &Step) -> Result<(), Error> { + let msg = format!("{}Checking crate configuration...", emoji::WRENCH); + PBAR.step(&step, &msg); + self.check_crate_type()?; + Ok(()) + } - if let Some(s) = scope { - self.package.name = format!("@{}/{}", s, self.package.name); + fn check_crate_type(&self) -> Result<(), Error> { + let pkg = &self.data.packages[self.current_idx]; + let any_cdylib = pkg + .targets + .iter() + .filter(|target| target.kind.iter().any(|k| k == "cdylib")) + .any(|target| target.crate_types.iter().any(|s| s == "cdylib")); + if any_cdylib { + return Ok(()); } + bail!( + "crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your \ + Cargo.toml file:\n\n\ + [lib]\n\ + crate-type = [\"cdylib\", \"rlib\"]" + ) + } - let dts_file = if disable_dts == false { - let file = format!("{}.d.ts", filename); - files.push(file.to_string()); - Some(file) + /// Get the crate name for the crate at the given path. + pub fn crate_name(&self) -> String { + let pkg = &self.data.packages[self.current_idx]; + match pkg + .targets + .iter() + .find(|t| t.kind.iter().any(|k| k == "cdylib")) + { + Some(lib) => lib.name.replace("-", "_"), + None => pkg.name.replace("-", "_"), + } + } + + /// Returns the path to this project's target directory where artifacts are + /// located after a cargo build. + pub fn target_directory(&self) -> &Path { + Path::new(&self.data.target_directory) + } + + /// Returns the path to this project's root cargo workspace directory + pub fn workspace_root(&self) -> &Path { + Path::new(&self.data.workspace_root) + } + + /// Generate a package.json file inside in `./pkg`. + pub fn write_package_json( + &self, + out_dir: &Path, + scope: &Option, + disable_dts: bool, + target: &str, + step: &Step, + ) -> Result<(), Error> { + let msg = format!("{}Writing a package.json...", emoji::MEMO); + + PBAR.step(step, &msg); + let pkg_file_path = out_dir.join("package.json"); + let npm_data = if target == "nodejs" { + self.to_commonjs(scope, disable_dts) + } else if target == "no-modules" { + self.to_nomodules(scope, disable_dts) } else { - None + self.to_esmodules(scope, disable_dts) }; - &self.package.check_optional_fields(); - - NpmPackage::CommonJSPackage(CommonJSPackage { - name: self.package.name, - collaborators: self.package.authors, - description: self.package.description, - version: self.package.version, - license: self.package.license, - repository: self.package.repository.map(|repo_url| Repository { - ty: "git".to_string(), - url: repo_url, - }), - files: files, - main: js_file, - types: dts_file, - }) + let npm_json = serde_json::to_string_pretty(&npm_data)?; + fs::write(&pkg_file_path, npm_json) + .with_context(|_| format!("failed to write: {}", pkg_file_path.display()))?; + Ok(()) } - fn into_esmodules(mut self, scope: &Option, disable_dts: bool) -> NpmPackage { - let filename = self.package.name.replace("-", "_"); - let wasm_file = format!("{}_bg.wasm", filename); - let js_file = format!("{}.js", filename); - let mut files = vec![wasm_file, js_file.clone()]; + fn npm_data( + &self, + scope: &Option, + include_commonjs_shim: bool, + disable_dts: bool, + ) -> NpmData { + let crate_name = self.crate_name(); + let wasm_file = format!("{}_bg.wasm", crate_name); + let js_file = format!("{}.js", crate_name); + let mut files = vec![wasm_file]; - let dts_file = if disable_dts == false { - let file = format!("{}.d.ts", filename); + files.push(js_file.clone()); + if include_commonjs_shim { + let js_bg_file = format!("{}_bg.js", crate_name); + files.push(js_bg_file.to_string()); + } + + let pkg = &self.data.packages[self.current_idx]; + let npm_name = match scope { + Some(s) => format!("@{}/{}", s, pkg.name), + None => pkg.name.clone(), + }; + + let dts_file = if !disable_dts { + let file = format!("{}.d.ts", crate_name); files.push(file.to_string()); Some(file) } else { None }; - - if let Some(s) = scope { - self.package.name = format!("@{}/{}", s, self.package.name); + NpmData { + name: npm_name, + dts_file, + files, + main: js_file, } + } - &self.package.check_optional_fields(); + fn to_commonjs(&self, scope: &Option, disable_dts: bool) -> NpmPackage { + let data = self.npm_data(scope, true, disable_dts); + let pkg = &self.data.packages[self.current_idx]; - NpmPackage::ESModulesPackage(ESModulesPackage { - name: self.package.name, - collaborators: self.package.authors, - description: self.package.description, - version: self.package.version, - license: self.package.license, - repository: self.package.repository.map(|repo_url| Repository { - ty: "git".to_string(), - url: repo_url, - }), - files: files, - module: js_file, - types: dts_file, - side_effects: "false".to_string(), + self.check_optional_fields(); + + NpmPackage::CommonJSPackage(CommonJSPackage { + name: data.name, + collaborators: pkg.authors.clone(), + description: self.manifest.package.description.clone(), + version: pkg.version.clone(), + license: self.manifest.package.license.clone(), + repository: self + .manifest + .package + .repository + .clone() + .map(|repo_url| Repository { + ty: "git".to_string(), + url: repo_url, + }), + files: data.files, + main: data.main, + types: data.dts_file, }) } - fn into_nomodules(mut self, scope: &Option, disable_dts: bool) -> NpmPackage { - let filename = self.package.name.replace("-", "_"); - let wasm_file = format!("{}_bg.wasm", filename); - let js_file = format!("{}.js", filename); - let mut files = vec![wasm_file, js_file.clone()]; + fn to_esmodules(&self, scope: &Option, disable_dts: bool) -> NpmPackage { + let data = self.npm_data(scope, false, disable_dts); + let pkg = &self.data.packages[self.current_idx]; - let dts_file = if disable_dts == false { - let file = format!("{}.d.ts", filename); - files.push(file.to_string()); - Some(file) - } else { - None - }; + self.check_optional_fields(); - if let Some(s) = scope { - self.package.name = format!("@{}/{}", s, self.package.name); - } + NpmPackage::ESModulesPackage(ESModulesPackage { + name: data.name, + collaborators: pkg.authors.clone(), + description: self.manifest.package.description.clone(), + version: pkg.version.clone(), + license: self.manifest.package.license.clone(), + repository: self + .manifest + .package + .repository + .clone() + .map(|repo_url| Repository { + ty: "git".to_string(), + url: repo_url, + }), + files: data.files, + module: data.main, + types: data.dts_file, + side_effects: "false".to_string(), + }) + } + + fn to_nomodules(&self, scope: &Option, disable_dts: bool) -> NpmPackage { + let data = self.npm_data(scope, false, disable_dts); + let pkg = &self.data.packages[self.current_idx]; - &self.package.check_optional_fields(); + self.check_optional_fields(); NpmPackage::NoModulesPackage(NoModulesPackage { - name: self.package.name, - collaborators: self.package.authors, - description: self.package.description, - version: self.package.version, - license: self.package.license, - repository: self.package.repository.map(|repo_url| Repository { - ty: "git".to_string(), - url: repo_url, - }), - files: files, - browser: js_file, - types: dts_file, + name: data.name, + collaborators: pkg.authors.clone(), + description: self.manifest.package.description.clone(), + version: pkg.version.clone(), + license: self.manifest.package.license.clone(), + repository: self + .manifest + .package + .repository + .clone() + .map(|repo_url| Repository { + ty: "git".to_string(), + url: repo_url, + }), + files: data.files, + browser: data.main, + types: data.dts_file, }) } -} - -/// Generate a package.json file inside in `./pkg`. -pub fn write_package_json( - path: &Path, - out_dir: &Path, - scope: &Option, - disable_dts: bool, - target: &str, - step: &Step, -) -> Result<(), failure::Error> { - let msg = format!("{}Writing a package.json...", emoji::MEMO); - - PBAR.step(step, &msg); - let pkg_file_path = out_dir.join("package.json"); - let mut pkg_file = File::create(pkg_file_path)?; - let crate_data = read_cargo_toml(path)?; - let npm_data = if target == "nodejs" { - crate_data.into_commonjs(scope, disable_dts) - } else if target == "no-modules" { - crate_data.into_nomodules(scope, disable_dts) - } else { - crate_data.into_esmodules(scope, disable_dts) - }; - - let npm_json = serde_json::to_string_pretty(&npm_data)?; - pkg_file.write_all(npm_json.as_bytes())?; - Ok(()) -} -/// Get the crate name for the crate at the given path. -pub fn get_crate_name(path: &Path) -> Result { - Ok(read_cargo_toml(path)?.package.name) -} - -/// Check that the crate the given path is properly configured. -pub fn check_crate_config(path: &Path, step: &Step) -> Result<(), failure::Error> { - let msg = format!("{}Checking crate configuration...", emoji::WRENCH); - PBAR.step(&step, &msg); - check_crate_type(path)?; - Ok(()) -} + fn check_optional_fields(&self) { + let mut messages = vec![]; + if self.manifest.package.description.is_none() { + messages.push("description"); + } + if self.manifest.package.repository.is_none() { + messages.push("repository"); + } + if self.manifest.package.license.is_none() { + messages.push("license"); + } -fn check_crate_type(path: &Path) -> Result<(), failure::Error> { - if read_cargo_toml(path)?.lib.map_or(false, |lib| { - lib.crate_type - .map_or(false, |types| types.iter().any(|s| s == "cdylib")) - }) { - return Ok(()); - } - Err(Error::crate_config( - "crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your \ - Cargo.toml file:\n\n\ - [lib]\n\ - crate-type = [\"cdylib\", \"rlib\"]" - ).into()) + match messages.len() { + 1 => PBAR.info(&format!("Optional field missing from Cargo.toml: '{}'. This is not necessary, but recommended", messages[0])), + 2 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}'. These are not necessary, but recommended", messages[0], messages[1])), + 3 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}', and '{}'. These are not necessary, but recommended", messages[0], messages[1], messages[2])), + _ => () + }; + } } diff --git a/src/test/mod.rs b/src/test/mod.rs index db683ff..1b71fed 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -22,12 +22,6 @@ where K: AsRef, V: AsRef, { - use std::sync::Mutex; - lazy_static! { - static ref ONE_TEST_AT_A_TIME: Mutex<()> = Mutex::new(()); - } - let _locked = ONE_TEST_AT_A_TIME.lock().unwrap(); - let output = { let mut cmd = Command::new("cargo"); cmd.envs(envs); diff --git a/src/test/webdriver.rs b/src/test/webdriver.rs index cac6d39..4b06314 100644 --- a/src/test/webdriver.rs +++ b/src/test/webdriver.rs @@ -1,40 +1,32 @@ //! Getting WebDriver client binaries. -use binaries::{ - self, bin_path, install_binaries_from_targz_at_url, install_binaries_from_zip_at_url, -}; +use binaries::Cache; use command::build::BuildMode; -use error::Error; use failure; -use slog::Logger; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use target; /// Get the path to an existing `chromedriver`, or install it if no existing /// binary is found. pub fn get_or_install_chromedriver( - log: &Logger, - crate_path: &Path, + cache: &Cache, mode: BuildMode, ) -> Result { - match (mode, bin_path(log, crate_path, "chromedriver")) { - (_, Some(path)) => Ok(path), - (BuildMode::Normal, None) => install_chromedriver(crate_path), - (BuildMode::Force, None) => install_chromedriver(crate_path), - (BuildMode::Noinstall, None) => Err(Error::crate_config( - "No crate-local `chromedriver` binary found, and could not find a global \ - `chromedriver` on the `$PATH`. Not installing `chromedriver` because of noinstall \ - mode.", - ) - .into()), + if let Ok(path) = which::which("chromedriver") { + return Ok(path); } + let installation_allowed = match mode { + BuildMode::Noinstall => false, + _ => true, + }; + install_chromedriver(cache, installation_allowed) } -fn get_local_chromedriver_path(crate_path: &Path) -> PathBuf { - binaries::local_bin_path(crate_path, "chromedriver") -} - -fn get_chromedriver_url() -> Result { +/// Download and install a pre-built `chromedriver` binary. +pub fn install_chromedriver( + cache: &Cache, + installation_allowed: bool, +) -> Result { let target = if target::LINUX && target::x86_64 { "linux64" } else if target::MACOS && target::x86_64 { @@ -42,46 +34,49 @@ fn get_chromedriver_url() -> Result { } else if target::WINDOWS && target::x86 { "win32" } else { - return Err(Error::unsupported( - "geckodriver binaries are unavailable for this target", - )); + bail!("geckodriver binaries are unavailable for this target") }; - Ok(format!( + let url = format!( "https://chromedriver.storage.googleapis.com/2.41/chromedriver_{}.zip", target - )) -} - -/// Download and install a pre-built `chromedriver` binary. -pub fn install_chromedriver(crate_path: &Path) -> Result { - let url = get_chromedriver_url()?; - install_binaries_from_zip_at_url(crate_path, &url, Some("chromedriver"))?; - let chromedriver = get_local_chromedriver_path(crate_path); - assert!(chromedriver.is_file()); - Ok(chromedriver) + ); + match cache.download( + installation_allowed, + "chromedriver", + &["chromedriver"], + &url, + )? { + 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 \ + mode." + ), + } } /// Get the path to an existing `geckodriver`, or install it if no existing /// binary is found. pub fn get_or_install_geckodriver( - log: &Logger, - crate_path: &Path, + cache: &Cache, mode: BuildMode, ) -> Result { - match (mode, bin_path(log, crate_path, "geckodriver")) { - (_, Some(path)) => Ok(path), - (BuildMode::Normal, None) => install_geckodriver(crate_path), - (BuildMode::Force, None) => install_geckodriver(crate_path), - (BuildMode::Noinstall, None) => Err(Error::crate_config( - "No crate-local `geckodriver` binary found, and could not find a global `geckodriver` \ - on the `$PATH`. Not installing `geckodriver` because of noinstall mode.", - ) - .into()), + if let Ok(path) = which::which("geckodriver") { + return Ok(path); } + let installation_allowed = match mode { + BuildMode::Noinstall => false, + _ => true, + }; + install_geckodriver(cache, installation_allowed) } -fn get_geckodriver_url() -> Result { +/// Download and install a pre-built `geckodriver` binary. +pub fn install_geckodriver( + cache: &Cache, + installation_allowed: bool, +) -> Result { let (target, ext) = if target::LINUX && target::x86 { ("linux32", "tar.gz") } else if target::LINUX && target::x86_64 { @@ -93,36 +88,21 @@ fn get_geckodriver_url() -> Result { } else if target::WINDOWS && target::x86_64 { ("win64", "zip") } else { - return Err(Error::unsupported( - "geckodriver binaries are unavailable for this target", - )); + bail!("geckodriver binaries are unavailable for this target") }; - Ok(format!( + let url = format!( "https://github.com/mozilla/geckodriver/releases/download/v0.21.0/geckodriver-v0.21.0-{}.{}", target, ext, - )) -} - -fn get_local_geckodriver_path(crate_path: &Path) -> PathBuf { - binaries::local_bin_path(crate_path, "geckodriver") -} - -/// Download and install a pre-built `geckodriver` binary. -pub fn install_geckodriver(crate_path: &Path) -> Result { - let url = get_geckodriver_url()?; - - if url.ends_with("tar.gz") { - install_binaries_from_targz_at_url(crate_path, &url, Some("geckodriver"))?; - } else { - assert!(url.ends_with("zip")); - install_binaries_from_zip_at_url(crate_path, &url, Some("geckodriver"))?; + ); + match cache.download(installation_allowed, "geckodriver", &["geckodriver"], &url)? { + 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." + ), } - - let geckodriver = get_local_geckodriver_path(crate_path); - assert!(geckodriver.is_file()); - Ok(geckodriver) } /// Get the path to an existing `safaridriver`. @@ -130,12 +110,9 @@ pub fn install_geckodriver(crate_path: &Path) -> Result /// We can't install `safaridriver` if an existing one is not found because /// Apple does not provide pre-built binaries. However, `safaridriver` *should* /// be present by default. -pub fn get_safaridriver(log: &Logger, crate_path: &Path) -> Result { - if let Some(p) = bin_path(log, crate_path, "safaridriver") { - Ok(p) - } else { - Err(Error::crate_config( - "could not find `safaridriver` on the `$PATH`", - )) +pub fn get_safaridriver() -> Result { + match which::which("safaridriver") { + Ok(p) => Ok(p), + Err(_) => bail!("could not find `safaridriver` on the `$PATH`"), } } diff --git a/tests/all/bindgen.rs b/tests/all/bindgen.rs index b79d58c..985a4d0 100644 --- a/tests/all/bindgen.rs +++ b/tests/all/bindgen.rs @@ -1,4 +1,5 @@ use tempfile; +use wasm_pack::binaries::Cache; use wasm_pack::bindgen; #[test] @@ -8,23 +9,11 @@ use wasm_pack::bindgen; all(windows, target_arch = "x86_64"), ))] fn can_download_prebuilt_wasm_bindgen() { - use std::env; let dir = tempfile::TempDir::new().unwrap(); - bindgen::download_prebuilt_wasm_bindgen(dir.path(), "0.2.21").unwrap(); - assert!( - dir.path() - .join("bin") - .join("wasm-bindgen") - .with_extension(env::consts::EXE_EXTENSION) - .is_file() - ); - assert!( - dir.path() - .join("bin") - .join("wasm-bindgen-test-runner") - .with_extension(env::consts::EXE_EXTENSION) - .is_file() - ); + 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()) } #[test] @@ -36,9 +25,13 @@ fn can_download_prebuilt_wasm_bindgen() { fn downloading_prebuilt_wasm_bindgen_handles_http_errors() { let dir = tempfile::TempDir::new().unwrap(); let bad_version = "0.2.21-some-trailing-version-stuff-that-does-not-exist"; - let result = bindgen::download_prebuilt_wasm_bindgen(dir.path(), bad_version); + let cache = Cache::at(dir.path()); + let result = bindgen::download_prebuilt_wasm_bindgen(&cache, bad_version, true); assert!(result.is_err()); - let error_msg = result.unwrap_err().to_string(); - assert!(error_msg.contains("404")); - assert!(error_msg.contains(bad_version)); + let error = result.err().unwrap(); + + assert!(error.iter_chain().any(|e| e.to_string().contains("404"))); + assert!(error + .iter_chain() + .any(|e| e.to_string().contains(bad_version))); } diff --git a/tests/all/build.rs b/tests/all/build.rs index 69a9bab..cc21fbb 100644 --- a/tests/all/build.rs +++ b/tests/all/build.rs @@ -1,6 +1,8 @@ +use std::fs; +use std::path::Path; use structopt::StructOpt; use utils; -use wasm_pack::{command, logger, Cli}; +use wasm_pack::Cli; #[test] fn build_in_non_crate_directory_doesnt_panic() { @@ -11,12 +13,218 @@ fn build_in_non_crate_directory_doesnt_panic() { &fixture.path.display().to_string(), ]) .unwrap(); - let logger = logger::new(&cli.cmd, cli.verbosity).unwrap(); - let result = command::run_wasm_pack(cli.cmd, &logger); + let result = fixture.run(cli.cmd); assert!( result.is_err(), "running wasm-pack in a non-crate directory should fail, but it should not panic" ); - let err_msg = result.unwrap_err().to_string(); - assert!(err_msg.contains("missing a `Cargo.toml`")); + let err = result.unwrap_err(); + assert!(err + .iter_chain() + .any(|e| e.to_string().contains("missing a `Cargo.toml`"))); +} + +#[test] +fn it_should_build_js_hello_world_example() { + let fixture = utils::fixture::js_hello_world(); + fixture.install_local_wasm_bindgen(); + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + &fixture.path.display().to_string(), + ]) + .unwrap(); + fixture.run(cli.cmd).unwrap(); +} + +#[test] +fn it_should_build_crates_in_a_workspace() { + let fixture = utils::fixture::Fixture::new(); + fixture + .file( + "Cargo.toml", + r#" + [workspace] + members = ["blah"] + "#, + ) + .file( + Path::new("blah").join("Cargo.toml"), + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "blah" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasm-bindgen = "=0.2.21" + "#, + ) + .file( + Path::new("blah").join("src").join("lib.rs"), + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + #[wasm_bindgen] + pub fn hello() -> u32 { 42 } + "#, + ); + fixture.install_local_wasm_bindgen(); + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + &fixture.path.join("blah").display().to_string(), + ]) + .unwrap(); + fixture.run(cli.cmd).unwrap(); +} + +#[test] +fn renamed_crate_name_works() { + let fixture = utils::fixture::Fixture::new(); + fixture + .readme() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [lib] + crate-type = ["cdylib"] + name = 'bar' + + [dependencies] + wasm-bindgen = "=0.2.21" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + #[wasm_bindgen] + pub fn one() -> u32 { 1 } + "#, + ); + fixture.install_local_wasm_bindgen(); + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + &fixture.path.display().to_string(), + ]) + .unwrap(); + fixture.run(cli.cmd).unwrap(); +} + +#[test] +fn it_should_build_nested_project_with_transitive_dependencies() { + let fixture = utils::fixture::transitive_dependencies(); + fixture.install_local_wasm_bindgen(); + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + &fixture.path.join("main").display().to_string(), + ]) + .unwrap(); + fixture.run(cli.cmd).unwrap(); +} + +#[test] +fn build_different_profiles() { + let fixture = utils::fixture::js_hello_world(); + fixture.install_local_wasm_bindgen(); + + for profile in ["--dev", "--debug", "--profiling", "--release"] + .iter() + .cloned() + { + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + profile, + &fixture.path.display().to_string(), + ]) + .unwrap(); + fixture.run(cli.cmd).unwrap(); + } +} + +#[test] +fn build_with_and_without_wasm_bindgen_debug() { + for debug in [true, false].iter().cloned() { + let fixture = utils::fixture::Fixture::new(); + fixture + .readme() + .file( + "Cargo.toml", + format!( + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "whatever" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasm-bindgen = "0.2" + + [package.metadata.wasm-pack.profile.dev.wasm-bindgen] + debug-js-glue = {} + "#, + debug + ), + ) + .file( + "src/lib.rs", + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + #[wasm_bindgen] + pub struct MyThing {} + + #[wasm_bindgen] + impl MyThing { + pub fn new() -> MyThing { + MyThing {} + } + + pub fn take(self) {} + } + "#, + ); + + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + "--dev", + &fixture.path.display().to_string(), + ]) + .unwrap(); + + fixture.run(cli.cmd).unwrap(); + + let contents = fs::read_to_string(fixture.path.join("pkg/whatever.js")).unwrap(); + assert_eq!( + contents.contains("throw new Error('Attempt to use a moved value')"), + debug, + "Should only contain moved value assertions when debug assertions are enabled" + ); + } } diff --git a/tests/all/lockfile.rs b/tests/all/lockfile.rs index 0752145..01876ba 100644 --- a/tests/all/lockfile.rs +++ b/tests/all/lockfile.rs @@ -1,11 +1,13 @@ use utils::fixture; use wasm_pack::lockfile::Lockfile; +use wasm_pack::manifest::CrateData; #[test] fn it_gets_wasm_bindgen_version() { let fixture = fixture::js_hello_world(); fixture.cargo_check(); - let lock = Lockfile::new(&fixture.path).unwrap(); + let data = CrateData::new(&fixture.path).unwrap(); + let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_version(), Some("0.2.21"),); } @@ -13,7 +15,8 @@ fn it_gets_wasm_bindgen_version() { fn it_gets_wasm_bindgen_test_version() { let fixture = fixture::wbg_test_node(); fixture.cargo_check(); - let lock = Lockfile::new(&fixture.path).unwrap(); + let data = CrateData::new(&fixture.path).unwrap(); + let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_test_version(), Some("0.2.21"),); } @@ -57,7 +60,8 @@ fn it_gets_wasm_bindgen_version_in_crate_inside_workspace() { "#, ); fixture.cargo_check(); - let lock = Lockfile::new(&fixture.path.join("blah")).unwrap(); + let data = CrateData::new(&fixture.path.join("blah")).unwrap(); + let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_version(), Some("0.2.21"),); } @@ -124,6 +128,7 @@ fn it_gets_wasm_bindgen_version_from_dependencies() { "#, ); fixture.cargo_check(); - let lock = Lockfile::new(&fixture.path.join("parent")).unwrap(); + let data = CrateData::new(&fixture.path.join("parent")).unwrap(); + let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_version(), Some("0.2.21"),); } diff --git a/tests/all/main.rs b/tests/all/main.rs index 553ce1f..3fa272f 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -1,5 +1,7 @@ extern crate failure; #[macro_use] +extern crate lazy_static; +#[macro_use] extern crate serde_derive; extern crate serde_json; #[macro_use] diff --git a/tests/all/manifest.rs b/tests/all/manifest.rs index 1add2b7..6bc9df8 100644 --- a/tests/all/manifest.rs +++ b/tests/all/manifest.rs @@ -2,24 +2,24 @@ use std::collections::HashSet; use std::fs; use std::path::PathBuf; +use structopt::StructOpt; + use utils::{self, fixture}; -use wasm_pack::{self, manifest}; +use wasm_pack::{self, manifest, Cli}; #[test] fn it_gets_the_crate_name_default_path() { let path = &PathBuf::from("."); - assert!(manifest::get_crate_name(path).is_ok()); - assert_eq!(manifest::get_crate_name(path).unwrap(), "wasm-pack"); + let crate_data = manifest::CrateData::new(&path).unwrap(); + let name = crate_data.crate_name(); + assert_eq!(name, "wasm_pack"); } #[test] fn it_gets_the_crate_name_provided_path() { let fixture = fixture::js_hello_world(); - assert!(manifest::get_crate_name(&fixture.path).is_ok()); - assert_eq!( - manifest::get_crate_name(&fixture.path).unwrap(), - "js-hello-world" - ); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); + assert_eq!(crate_data.crate_name(), "js_hello_world"); } #[test] @@ -27,8 +27,9 @@ fn it_checks_has_cdylib_default_path() { let fixture = fixture::no_cdylib(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); - assert!(manifest::check_crate_config(&fixture.path, &step).is_err()); + assert!(crate_data.check_crate_config(&step).is_err()); } #[test] @@ -36,15 +37,17 @@ fn it_checks_has_cdylib_provided_path() { let fixture = fixture::js_hello_world(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); - assert!(manifest::check_crate_config(&fixture.path, &step).is_ok()); + crate_data.check_crate_config(&step).unwrap(); } #[test] fn it_checks_has_cdylib_wrong_crate_type() { let fixture = fixture::bad_cargo_toml(); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); - assert!(manifest::check_crate_config(&fixture.path, &step).is_err()); + assert!(crate_data.check_crate_config(&step).is_err()); } #[test] @@ -52,20 +55,24 @@ fn it_recognizes_a_map_during_depcheck() { let fixture = fixture::serde_feature(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); - assert!(manifest::check_crate_config(&fixture.path, &step).is_ok()); + crate_data.check_crate_config(&step).unwrap(); } #[test] fn it_creates_a_package_json_default_path() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); - assert!(manifest::write_package_json(&fixture.path, &out_dir, &None, false, "", &step).is_ok()); + assert!(crate_data + .write_package_json(&out_dir, &None, false, "", &step) + .is_ok()); let package_json_path = &fixture.path.join("pkg").join("package.json"); - assert!(fs::metadata(package_json_path).is_ok()); - assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); + fs::metadata(package_json_path).unwrap(); + utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); assert_eq!(pkg.name, "js-hello-world"); assert_eq!(pkg.repository.ty, "git"); @@ -83,9 +90,9 @@ fn it_creates_a_package_json_default_path() { "js_hello_world.d.ts", "js_hello_world.js", ] - .iter() - .map(|&s| String::from(s)) - .collect(); + .iter() + .map(|&s| String::from(s)) + .collect(); assert_eq!(actual_files, expected_files); } @@ -93,11 +100,14 @@ fn it_creates_a_package_json_default_path() { fn it_creates_a_package_json_provided_path() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); - assert!(manifest::write_package_json(&fixture.path, &out_dir, &None, false, "", &step).is_ok()); + assert!(crate_data + .write_package_json(&out_dir, &None, false, "", &step) + .is_ok()); let package_json_path = &fixture.path.join("pkg").join("package.json"); - assert!(fs::metadata(package_json_path).is_ok()); + fs::metadata(package_json_path).unwrap(); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); assert_eq!(pkg.name, "js-hello-world"); @@ -109,9 +119,9 @@ fn it_creates_a_package_json_provided_path() { "js_hello_world.d.ts", "js_hello_world.js", ] - .iter() - .map(|&s| String::from(s)) - .collect(); + .iter() + .map(|&s| String::from(s)) + .collect(); assert_eq!(actual_files, expected_files); } @@ -119,22 +129,15 @@ fn it_creates_a_package_json_provided_path() { fn it_creates_a_package_json_provided_path_with_scope() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); - assert!( - manifest::write_package_json( - &fixture.path, - &out_dir, - &Some("test".to_string()), - false, - "", - &step - ) - .is_ok() - ); + assert!(crate_data + .write_package_json(&out_dir, &Some("test".to_string()), false, "", &step) + .is_ok()); let package_json_path = &fixture.path.join("pkg").join("package.json"); - assert!(fs::metadata(package_json_path).is_ok()); - assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); + fs::metadata(package_json_path).unwrap(); + utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); assert_eq!(pkg.name, "@test/js-hello-world"); assert_eq!(pkg.module, "js_hello_world.js"); @@ -145,9 +148,9 @@ fn it_creates_a_package_json_provided_path_with_scope() { "js_hello_world.d.ts", "js_hello_world.js", ] - .iter() - .map(|&s| String::from(s)) - .collect(); + .iter() + .map(|&s| String::from(s)) + .collect(); assert_eq!(actual_files, expected_files); } @@ -155,14 +158,14 @@ fn it_creates_a_package_json_provided_path_with_scope() { fn it_creates_a_pkg_json_with_correct_files_on_node() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); - assert!( - manifest::write_package_json(&fixture.path, &out_dir, &None, false, "nodejs", &step) - .is_ok() - ); + assert!(crate_data + .write_package_json(&out_dir, &None, false, "nodejs", &step) + .is_ok()); let package_json_path = &out_dir.join("package.json"); - assert!(fs::metadata(package_json_path).is_ok()); + fs::metadata(package_json_path).unwrap(); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); assert_eq!(pkg.name, "js-hello-world"); @@ -179,10 +182,11 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() { "js_hello_world_bg.wasm", "js_hello_world_bg.js", "js_hello_world.d.ts", + "js_hello_world.js", ] - .iter() - .map(|&s| String::from(s)) - .collect(); + .iter() + .map(|&s| String::from(s)) + .collect(); assert_eq!(actual_files, expected_files); } @@ -190,14 +194,14 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() { fn it_creates_a_pkg_json_with_correct_files_on_nomodules() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); - assert!( - manifest::write_package_json(&fixture.path, &out_dir, &None, false, "no-modules", &step) - .is_ok() - ); + assert!(crate_data + .write_package_json(&out_dir, &None, false, "no-modules", &step) + .is_ok()); let package_json_path = &out_dir.join("package.json"); - assert!(fs::metadata(package_json_path).is_ok()); + fs::metadata(package_json_path).unwrap(); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); assert_eq!(pkg.name, "js-hello-world"); @@ -215,9 +219,9 @@ fn it_creates_a_pkg_json_with_correct_files_on_nomodules() { "js_hello_world.js", "js_hello_world.d.ts", ] - .iter() - .map(|&s| String::from(s)) - .collect(); + .iter() + .map(|&s| String::from(s)) + .collect(); assert_eq!(actual_files, expected_files); } @@ -225,25 +229,31 @@ fn it_creates_a_pkg_json_with_correct_files_on_nomodules() { fn it_creates_a_pkg_json_in_out_dir() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("./custom/out"); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); - assert!(manifest::write_package_json(&fixture.path, &out_dir, &None, false, "", &step).is_ok()); + assert!(crate_data + .write_package_json(&out_dir, &None, false, "", &step) + .is_ok()); let package_json_path = &fixture.path.join(&out_dir).join("package.json"); - assert!(fs::metadata(package_json_path).is_ok()); - assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); + fs::metadata(package_json_path).unwrap(); + utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); } #[test] fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); - assert!(manifest::write_package_json(&fixture.path, &out_dir, &None, true, "", &step).is_ok()); + assert!(crate_data + .write_package_json(&out_dir, &None, true, "", &step) + .is_ok()); let package_json_path = &out_dir.join("package.json"); - assert!(fs::metadata(package_json_path).is_ok()); - assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); + fs::metadata(package_json_path).unwrap(); + utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); assert_eq!(pkg.name, "js-hello-world"); assert_eq!(pkg.repository.ty, "git"); @@ -264,8 +274,9 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() { #[test] fn it_errors_when_wasm_bindgen_is_not_declared() { let fixture = fixture::bad_cargo_toml(); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); - assert!(manifest::check_crate_config(&fixture.path, &step).is_err()); + assert!(crate_data.check_crate_config(&step).is_err()); } #[test] @@ -273,6 +284,52 @@ fn it_does_not_error_when_wasm_bindgen_is_declared() { let fixture = fixture::js_hello_world(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); + let crate_data = manifest::CrateData::new(&fixture.path).unwrap(); let step = wasm_pack::progressbar::Step::new(1); - assert!(manifest::check_crate_config(&fixture.path, &step).is_ok()); + crate_data.check_crate_config(&step).unwrap(); +} + +#[test] +fn configure_wasm_bindgen_debug_incorrectly_is_error() { + let fixture = utils::fixture::Fixture::new(); + fixture + .readme() + .file( + "Cargo.toml", + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "whatever" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasm-bindgen = "0.2" + + [package.metadata.wasm-pack.profile.dev.wasm-bindgen] + debug-js-glue = "not a boolean" + "#, + ) + .hello_world_src_lib(); + + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + "--dev", + &fixture.path.display().to_string(), + ]) + .unwrap(); + + let result = fixture.run(cli.cmd); + assert!(result.is_err()); + + let err = result.unwrap_err(); + assert!(err.iter_chain().any(|c| c + .to_string() + .contains("package.metadata.wasm-pack.profile.dev.wasm-bindgen.debug"))); } diff --git a/tests/all/readme.rs b/tests/all/readme.rs index 0bb2ded..af2fbcd 100644 --- a/tests/all/readme.rs +++ b/tests/all/readme.rs @@ -32,7 +32,7 @@ fn it_copies_a_readme_default_path() { } #[test] -fn it_creates_a_package_json_provided_path() { +fn it_copies_a_readme_provided_path() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); fs::create_dir(&out_dir).expect("should create pkg directory OK"); diff --git a/tests/all/test.rs b/tests/all/test.rs index 54d4131..278959a 100644 --- a/tests/all/test.rs +++ b/tests/all/test.rs @@ -1,10 +1,16 @@ +use failure::Error; use std::env; -use std::fs; -use tempfile; use utils::fixture; -use wasm_pack::binaries; -use wasm_pack::command::{self, build, test, Command}; -use wasm_pack::logger; +use wasm_pack::command::{build, test, Command}; + +fn assert_err(result: Result, msg: &str) -> Error { + let error = result.err().expect("should have failed"); + for e in error.iter_chain() { + println!("err: {}", e); + } + assert!(error.iter_chain().any(|e| e.to_string().contains(msg))); + error +} #[test] fn it_can_run_node_tests() { @@ -16,8 +22,7 @@ fn it_can_run_node_tests() { mode: build::BuildMode::Noinstall, ..Default::default() }); - let logger = logger::new(&cmd, 3).unwrap(); - command::run_wasm_pack(cmd, &logger).expect("should run test command OK"); + fixture.run(cmd).unwrap(); } #[test] @@ -30,8 +35,7 @@ fn it_can_run_tests_with_different_wbg_test_and_wbg_versions() { mode: build::BuildMode::Noinstall, ..Default::default() }); - let logger = logger::new(&cmd, 3).unwrap(); - command::run_wasm_pack(cmd, &logger).expect("should run test command OK"); + fixture.run(cmd).unwrap(); } #[test] @@ -81,8 +85,7 @@ fn it_can_run_browser_tests() { ..Default::default() }); - let logger = logger::new(&cmd, 3).unwrap(); - command::run_wasm_pack(cmd, &logger).expect("should run test command OK"); + fixture.run(cmd).unwrap(); } #[test] @@ -95,10 +98,9 @@ fn it_can_run_failing_tests() { mode: build::BuildMode::Noinstall, ..Default::default() }); - let logger = logger::new(&cmd, 3).unwrap(); - assert!( - command::run_wasm_pack(cmd, &logger).is_err(), - "failing tests should return Err" + assert_err( + fixture.run(cmd), + "Running Wasm tests with wasm-bindgen-test failed", ); } @@ -111,34 +113,37 @@ fn it_can_run_failing_tests() { all(target_os = "windows", target_arch = "x86_64") ))] fn it_can_find_a_webdriver_on_path() { + use std::process::Command; + let fixture = fixture::wbg_test_browser(); - fixture.install_local_wasm_bindgen(); - fixture.install_local_geckodriver(); - - let geckodriver_dir = tempfile::TempDir::new().unwrap(); - let local_geckodriver = binaries::local_bin_path(&fixture.path, "geckodriver"); - fs::copy( - &local_geckodriver, - geckodriver_dir - .path() - .join(local_geckodriver.file_name().unwrap()), - ) - .unwrap(); - fs::remove_file(&local_geckodriver).unwrap(); + let local_geckodriver = fixture.install_local_geckodriver(); + let local_wasm_bindgen = fixture.install_local_wasm_bindgen(); let mut paths: Vec<_> = env::split_paths(&env::var("PATH").unwrap()).collect(); - paths.insert(0, geckodriver_dir.path().into()); - env::set_var("PATH", env::join_paths(paths).unwrap()); + paths.insert(0, local_geckodriver.parent().unwrap().to_path_buf()); + paths.insert(0, local_wasm_bindgen.parent().unwrap().to_path_buf()); + let path = env::join_paths(paths).unwrap(); - let cmd = Command::Test(test::TestOptions { - path: Some(fixture.path.clone()), - firefox: true, - headless: true, - mode: build::BuildMode::Noinstall, - ..Default::default() - }); - let logger = logger::new(&cmd, 3).unwrap(); - command::run_wasm_pack(cmd, &logger).expect("should run test command OK"); + let _lock = fixture.lock(); + + let mut me = env::current_exe().unwrap(); + me.pop(); + me.pop(); + me.push("wasm-pack"); + let output = Command::new(&me) + .arg("test") + .arg("--firefox") + .arg("--headless") + .arg("--mode") + .arg("no-install") + .env("PATH", &path) + .arg(&fixture.path) + .output() + .unwrap(); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + println!("status: {}", output.status); + assert!(output.status.success()); } #[test] @@ -152,11 +157,7 @@ fn it_requires_node_or_a_browser() { // Note: not setting node or any browser to true here. ..Default::default() }); - let logger = logger::new(&cmd, 3).unwrap(); - assert!( - command::run_wasm_pack(cmd, &logger).is_err(), - "need to enable node or browser testing" - ); + assert_err(fixture.run(cmd), "Must specify at least one of"); } #[test] @@ -171,11 +172,7 @@ fn the_headless_flag_requires_a_browser() { headless: true, ..Default::default() }); - let logger = logger::new(&cmd, 3).unwrap(); - assert!( - command::run_wasm_pack(cmd, &logger).is_err(), - "running headless tests in node doesn't make sense" - ); + assert_err(fixture.run(cmd), "only applies to browser tests"); } #[test] @@ -213,13 +210,7 @@ fn complains_about_missing_wasm_bindgen_test_dependency() { mode: build::BuildMode::Noinstall, ..Default::default() }); - let logger = logger::new(&cmd, 3).unwrap(); - - let result = command::run_wasm_pack(cmd, &logger); - assert!( - result.is_err(), - "running tests without wasm-bindgen-test won't work" - ); + let error = assert_err(fixture.run(cmd), "Ensure that you have"); // Test that the error message has two occurrences of "wasm-bindgen-test" in // it. I am surprised to learn there is no `str` method to count @@ -244,10 +235,102 @@ fn complains_about_missing_wasm_bindgen_test_dependency() { // the output to a text file, then the escape codes go away, so I can't // figure out which exact escape codes are even used here. - let err_msg = result.unwrap_err().to_string(); + let err_msg = error.to_string(); let first = err_msg.find("wasm-bindgen-test"); assert!(first.is_some()); let second = err_msg.rfind("wasm-bindgen-test"); assert!(second.is_some()); assert_ne!(first, second, "should have found two occurrences"); } + +#[test] +fn renamed_crate_name_works() { + let fixture = fixture::Fixture::new(); + fixture + .readme() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [lib] + crate-type = ["cdylib"] + name = 'bar' + + [dependencies] + wasm-bindgen = "=0.2.21" + + [dev-dependencies] + wasm-bindgen-test = "=0.2.21" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + #[wasm_bindgen] + pub fn one() -> u32 { 1 } + "#, + ); + fixture.install_local_wasm_bindgen(); + let cmd = Command::Test(test::TestOptions { + path: Some(fixture.path.clone()), + node: true, + mode: build::BuildMode::Noinstall, + ..Default::default() + }); + fixture.run(cmd).unwrap(); +} + +#[test] +fn cdylib_not_required() { + let fixture = fixture::Fixture::new(); + fixture + .readme() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + wasm-bindgen = "=0.2.21" + + [dev-dependencies] + wasm-bindgen-test = "=0.2.21" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { 1 } + "#, + ) + .file( + "tests/foo.rs", + r#" + extern crate wasm_bindgen_test; + use wasm_bindgen_test::*; + + #[wasm_bindgen_test] + fn smoke() { + foo::foo(); + } + "#, + ); + fixture.install_local_wasm_bindgen(); + let cmd = Command::Test(test::TestOptions { + path: Some(fixture.path.clone()), + node: true, + mode: build::BuildMode::Noinstall, + ..Default::default() + }); + fixture.run(cmd).unwrap(); +} diff --git a/tests/all/utils/fixture.rs b/tests/all/utils/fixture.rs index dc47369..9a9a58c 100644 --- a/tests/all/utils/fixture.rs +++ b/tests/all/utils/fixture.rs @@ -1,20 +1,14 @@ use super::logger::null_logger; use std::env; use std::fs; -use std::io; use std::mem::ManuallyDrop; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use std::sync::{Once, ONCE_INIT}; +use std::sync::{MutexGuard, Once, ONCE_INIT}; use std::thread; use tempfile::TempDir; use wasm_pack; - -fn hard_link_or_copy, P2: AsRef>(from: P1, to: P2) -> io::Result<()> { - let from = from.as_ref(); - let to = to.as_ref(); - fs::hard_link(from, to).or_else(|_| fs::copy(from, to).map(|_| ())) -} +use wasm_pack::binaries::Cache; /// A test fixture in a temporary directory. pub struct Fixture { @@ -134,120 +128,63 @@ impl Fixture { /// /// Takes care not to re-install for every fixture, but only the one time /// for the whole test suite. - pub fn install_local_wasm_bindgen(&self) -> &Self { + pub fn install_local_wasm_bindgen(&self) -> PathBuf { static INSTALL_WASM_BINDGEN: Once = ONCE_INIT; + let cache = self.cache(); + let version = "0.2.21"; + let log = &null_logger(); + + let download = || { + if let Ok(download) = + wasm_pack::bindgen::download_prebuilt_wasm_bindgen(&cache, version, true) + { + return Ok(download); + } - let tests = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests"); - let shared_wasm_bindgen = wasm_pack::binaries::local_bin_path(&tests, "wasm-bindgen"); - let shared_wasm_bindgen_test_runner = - wasm_pack::binaries::local_bin_path(&tests, "wasm-bindgen-test-runner"); + wasm_pack::bindgen::cargo_install_wasm_bindgen(log, &cache, version, true) + }; + // Only one thread can perform the actual download, and then afterwards + // everything will hit the cache so we can run the same path. INSTALL_WASM_BINDGEN.call_once(|| { - if shared_wasm_bindgen.is_file() { - assert!(shared_wasm_bindgen_test_runner.is_file()); - return; - } - - const WASM_BINDGEN_VERSION: &str = "0.2.21"; - wasm_pack::bindgen::download_prebuilt_wasm_bindgen(&tests, WASM_BINDGEN_VERSION) - .or_else(|_| { - wasm_pack::bindgen::cargo_install_wasm_bindgen( - &null_logger(), - &tests, - WASM_BINDGEN_VERSION, - ) - }) - .unwrap(); + download().unwrap(); }); - - assert!(shared_wasm_bindgen.is_file()); - assert!(shared_wasm_bindgen_test_runner.is_file()); - - wasm_pack::binaries::ensure_local_bin_dir(&self.path).unwrap(); - - hard_link_or_copy( - &shared_wasm_bindgen, - wasm_pack::binaries::local_bin_path(&self.path, "wasm-bindgen"), - ) - .expect("could not copy `wasm-bindgen` to fixture directory"); - - hard_link_or_copy( - &shared_wasm_bindgen_test_runner, - wasm_pack::binaries::local_bin_path(&self.path, "wasm-bindgen-test-runner"), - ) - .expect("could not copy `wasm-bindgen-test` to fixture directory"); - - self + download().unwrap().binary("wasm-bindgen") } /// Download `geckodriver` and return its path. /// /// Takes care to ensure that only one `geckodriver` is downloaded for the whole /// test suite. - pub fn install_local_geckodriver(&self) -> &Self { + pub fn install_local_geckodriver(&self) -> PathBuf { static FETCH_GECKODRIVER: Once = ONCE_INIT; + let cache = self.cache(); - let tests = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests"); - - wasm_pack::binaries::ensure_local_bin_dir(&tests) - .expect("could not create fixture's `bin` directory"); - - let geckodriver = wasm_pack::binaries::local_bin_path(&tests, "geckodriver"); - + // like above for synchronization FETCH_GECKODRIVER.call_once(|| { - if geckodriver.is_file() { - return; - } - - wasm_pack::test::webdriver::install_geckodriver(&tests).unwrap(); - assert!(geckodriver.is_file()); + wasm_pack::test::webdriver::install_geckodriver(&cache, true).unwrap(); }); - - wasm_pack::binaries::ensure_local_bin_dir(&self.path) - .expect("could not create fixture's `bin` directory"); - - hard_link_or_copy( - &geckodriver, - wasm_pack::binaries::local_bin_path(&self.path, "geckodriver"), - ) - .expect("could not copy `geckodriver` to fixture directory"); - - self + wasm_pack::test::webdriver::install_geckodriver(&cache, true).unwrap() } /// Download `chromedriver` and return its path. /// /// Takes care to ensure that only one `chromedriver` is downloaded for the whole /// test suite. - pub fn install_local_chromedriver(&self) -> &Self { + pub fn install_local_chromedriver(&self) -> PathBuf { static FETCH_CHROMEDRIVER: Once = ONCE_INIT; + let cache = self.cache(); - let tests = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests"); - - wasm_pack::binaries::ensure_local_bin_dir(&tests) - .expect("could not create fixture's `bin` directory"); - - let chromedriver = wasm_pack::binaries::local_bin_path(&tests, "chromedriver"); - + // like above for synchronization FETCH_CHROMEDRIVER.call_once(|| { - if chromedriver.is_file() { - return; - } - - wasm_pack::test::webdriver::install_chromedriver(&tests).unwrap(); - assert!(chromedriver.is_file()); + wasm_pack::test::webdriver::install_chromedriver(&cache, true).unwrap(); }); + wasm_pack::test::webdriver::install_chromedriver(&cache, true).unwrap() + } - wasm_pack::binaries::ensure_local_bin_dir(&self.path) - .expect("could not create fixture's `bin` directory"); - - hard_link_or_copy( - &chromedriver, - wasm_pack::binaries::local_bin_path(&self.path, "chromedriver"), - ) - .expect("could not copy `chromedriver` to fixture directory"); - - self + pub fn cache(&self) -> Cache { + let target_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("target"); + Cache::at(&target_dir.join("test_cache")) } /// The `step_install_wasm_bindgen` and `step_run_wasm_bindgen` steps only @@ -266,6 +203,32 @@ impl Fixture { .unwrap(); self } + + pub fn run(&self, cmd: wasm_pack::command::Command) -> Result<(), failure::Error> { + let logger = wasm_pack::logger::new(&cmd, 3)?; + match cmd { + wasm_pack::command::Command::Test(cmd) => { + let _lock = self.lock(); + let mut test = wasm_pack::command::test::Test::try_from_opts(cmd)?; + test.set_cache(self.cache()); + test.run(&logger) + } + wasm_pack::command::Command::Build(cmd) => { + let mut build = wasm_pack::command::build::Build::try_from_opts(cmd)?; + build.set_cache(self.cache()); + build.run(&logger) + } + _ => unreachable!(), + } + } + + pub fn lock(&self) -> MutexGuard<'static, ()> { + use std::sync::Mutex; + lazy_static! { + static ref ONE_TEST_AT_A_TIME: Mutex<()> = Mutex::new(()); + } + ONE_TEST_AT_A_TIME.lock().unwrap_or_else(|e| e.into_inner()) + } } impl Drop for Fixture { @@ -314,7 +277,7 @@ pub fn no_cdylib() -> Fixture { authors = ["The wasm-pack developers"] description = "so awesome rust+wasm package" license = "WTFPL" - name = "{}" + name = "foo" repository = "https://github.com/rustwasm/wasm-pack.git" version = "0.1.0" @@ -474,3 +437,156 @@ pub fn wbg_test_node() -> Fixture { ); fixture } + +pub fn transitive_dependencies() -> Fixture { + fn project_main_fixture(fixture: &mut Fixture) { + fixture.file(PathBuf::from("main/README"), "# Main Fixture\n"); + fixture.file( + PathBuf::from("main/Cargo.toml"), + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "main_project" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasm-bindgen = "=0.2.21" + project_a = { path = "../project_a" } + project_b = { path = "../project_b" } + + [dev-dependencies] + wasm-bindgen-test = "=0.2.21" + "#, + ); + fixture.file( + PathBuf::from("main/src/lib.rs"), + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + // Import the `window.alert` function from the Web. + #[wasm_bindgen] + extern { + fn alert(s: &str); + } + + // Export a `greet` function from Rust to JavaScript, that alerts a + // hello message. + #[wasm_bindgen] + pub fn greet(name: &str) { + alert(&format!("Hello, {}!", name)); + } + "#, + ); + } + + fn project_a_fixture(fixture: &mut Fixture) { + fixture.file( + PathBuf::from("project_a/README"), + "# Project Alpha Fixture\n", + ); + fixture.file( + PathBuf::from("project_a/Cargo.toml"), + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "project_a" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasm-bindgen = "=0.2.21" + project_b = { path = "../project_b" } + + [dev-dependencies] + wasm-bindgen-test = "=0.2.21" + "#, + ); + fixture.file( + PathBuf::from("project_a/src/lib.rs"), + r#" + extern crate wasm_bindgen; + // extern crate project_b; + use wasm_bindgen::prelude::*; + + // Import the `window.alert` function from the Web. + #[wasm_bindgen] + extern { + fn alert(s: &str); + } + + // Export a `greet` function from Rust to JavaScript, that alerts a + // hello message. + #[wasm_bindgen] + pub fn greet(name: &str) { + alert(&format!("Hello, {}!", name)); + } + "#, + ); + } + + fn project_b_fixture(fixture: &mut Fixture) { + fixture.file( + PathBuf::from("project_b/README"), + "# Project Beta Fixture\n", + ); + fixture.file( + PathBuf::from("project_b/Cargo.toml"), + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "project_b" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasm-bindgen = "=0.2.21" + + [dev-dependencies] + wasm-bindgen-test = "=0.2.21" + "#, + ); + fixture.file( + PathBuf::from("project_b/src/lib.rs"), + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + // Import the `window.alert` function from the Web. + #[wasm_bindgen] + extern { + fn alert(s: &str); + } + + // Export a `greet` function from Rust to JavaScript, that alerts a + // hello message. + #[wasm_bindgen] + pub fn greet(name: &str) { + alert(&format!("Hello, {}!", name)); + } + "#, + ); + } + + let mut fixture = Fixture::new(); + project_b_fixture(&mut fixture); + project_a_fixture(&mut fixture); + project_main_fixture(&mut fixture); + fixture +} diff --git a/tests/all/webdriver.rs b/tests/all/webdriver.rs index 5e3b0cb..f57c275 100644 --- a/tests/all/webdriver.rs +++ b/tests/all/webdriver.rs @@ -1,4 +1,5 @@ use utils::fixture; +use wasm_pack::binaries::Cache; use wasm_pack::test::webdriver; #[test] @@ -9,7 +10,8 @@ use wasm_pack::test::webdriver; ))] fn can_install_chromedriver() { let fixture = fixture::js_hello_world(); - assert!(webdriver::install_chromedriver(&fixture.path).is_ok()); + let cache = Cache::at(&fixture.path); + assert!(webdriver::install_chromedriver(&cache, true).is_ok()); } #[test] @@ -22,5 +24,6 @@ fn can_install_chromedriver() { ))] fn can_install_geckodriver() { let fixture = fixture::js_hello_world(); - assert!(webdriver::install_geckodriver(&fixture.path).is_ok()); + let cache = Cache::at(&fixture.path); + assert!(webdriver::install_geckodriver(&cache, true).is_ok()); }