Merge pull request #1 from daubaris/wasm-pack-version

Addition of stamp file and additional thread for running version checks
master
daubaris 7 years ago committed by GitHub
commit ed074e7d72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      .appveyor.yml
  2. 18
      .travis.yml
  3. 390
      Cargo.lock
  4. 4
      Cargo.toml
  5. 1
      docs/src/SUMMARY.md
  6. 29
      docs/src/cargo-toml-configuration.md
  7. 27
      docs/src/commands/build.md
  8. 422
      src/binaries.rs
  9. 214
      src/bindgen.rs
  10. 78
      src/build.rs
  11. 9
      src/child.rs
  12. 154
      src/command/build.rs
  13. 37
      src/command/mod.rs
  14. 13
      src/command/pack.rs
  15. 4
      src/command/publish/access.rs
  16. 13
      src/command/publish/mod.rs
  17. 97
      src/command/test.rs
  18. 10
      src/command/utils.rs
  19. 240
      src/error.rs
  20. 6
      src/lib.rs
  21. 40
      src/lockfile.rs
  22. 2
      src/main.rs
  23. 703
      src/manifest/mod.rs
  24. 6
      src/test/mod.rs
  25. 137
      src/test/webdriver.rs
  26. 33
      tests/all/bindgen.rs
  27. 218
      tests/all/build.rs
  28. 13
      tests/all/lockfile.rs
  29. 2
      tests/all/main.rs
  30. 183
      tests/all/manifest.rs
  31. 2
      tests/all/readme.rs
  32. 197
      tests/all/test.rs
  33. 310
      tests/all/utils/fixture.rs
  34. 7
      tests/all/webdriver.rs

@ -5,17 +5,18 @@ environment:
install: install:
- ps: Install-Product node 10 - ps: Install-Product node 10
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - 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 PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- set RUST_BACKTRACE=1 - set RUST_BACKTRACE=1
- rustup target add wasm32-unknown-unknown --toolchain nightly - rustup target add wasm32-unknown-unknown --toolchain stable
- rustc -V - rustc -V
- cargo -V - cargo -V
build: false build: false
test_script: test_script:
- cargo test --release --locked - cargo test --release --tests --locked
- cargo test --release --doc
before_deploy: before_deploy:
- ps: | - ps: |

@ -38,8 +38,8 @@ DEPLOY_TO_GITHUB: &DEPLOY_TO_GITHUB
matrix: matrix:
include: include:
# tests pass - name: Tests
- env: JOB=test RUST_BACKTRACE=1 env: RUST_BACKTRACE=1
rust: nightly rust: nightly
addons: addons:
firefox: latest firefox: latest
@ -49,14 +49,14 @@ matrix:
script: script:
- cargo test --locked - cargo test --locked
- rustup component add rustfmt-preview - rustup component add rustfmt-preview
- cargo fmt --version
- cargo fmt --all -- --check - cargo fmt --all -- --check
# book - name: Book
- env: JOB=book
rust: stable rust: stable
before_script: before_script:
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - (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 - cargo install-update -a
script: script:
- (cd docs && mdbook build) - (cd docs && mdbook build)
@ -71,8 +71,8 @@ matrix:
on: on:
branch: master branch: master
# dist linux binary - name: Linux Binary
- env: JOB=dist-linux TARGET=x86_64-unknown-linux-musl env: TARGET=x86_64-unknown-linux-musl
rust: nightly rust: nightly
before_script: rustup target add $TARGET before_script: rustup target add $TARGET
script: cargo build --release --target $TARGET --locked --features vendored-openssl script: cargo build --release --target $TARGET --locked --features vendored-openssl
@ -82,8 +82,8 @@ matrix:
- musl-tools - musl-tools
<<: *DEPLOY_TO_GITHUB <<: *DEPLOY_TO_GITHUB
# dist OSX binary - name: macOS Binary
- env: JOB=dist-osx MACOSX_DEPLOYMENT_TARGET=10.7 TARGET=x86_64-apple-darwin env: MACOSX_DEPLOYMENT_TARGET=10.7 TARGET=x86_64-apple-darwin
os: osx os: osx
rust: nightly rust: nightly
script: cargo build --release --target $TARGET --locked script: cargo build --release --target $TARGET --locked

390
Cargo.lock generated

@ -5,10 +5,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.6.8" version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -19,6 +19,23 @@ dependencies = [
"winapi 0.3.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 = "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]] [[package]]
name = "atty" name = "atty"
version = "0.2.11" version = "0.2.11"
@ -35,7 +52,7 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -55,6 +72,15 @@ name = "bitflags"
version = "1.0.4" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "build_const" name = "build_const"
version = "0.2.1" version = "0.2.1"
@ -62,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.2.6" version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -85,13 +111,13 @@ dependencies = [
[[package]] [[package]]
name = "cargo_metadata" name = "cargo_metadata"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (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)", "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]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.5" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -155,15 +181,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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)", "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)", "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]] [[package]]
name = "crc" name = "crc"
version = "1.8.1" version = "1.8.1"
@ -174,14 +205,14 @@ dependencies = [
[[package]] [[package]]
name = "curl" name = "curl"
version = "0.4.18" version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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-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)", "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)", "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)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -189,18 +220,28 @@ dependencies = [
[[package]] [[package]]
name = "curl-sys" name = "curl-sys"
version = "0.4.13" version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "libz-sys 1.0.25 (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)",
"pkg-config 0.3.14 (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)", "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)", "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]] [[package]]
name = "error-chain" name = "error-chain"
version = "0.12.0" version = "0.12.0"
@ -211,42 +252,42 @@ dependencies = [
[[package]] [[package]]
name = "failure" name = "failure"
version = "0.1.2" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "failure_derive" name = "failure_derive"
version = "0.1.2" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.3" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "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-sys 0.1.11 (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_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -276,16 +317,29 @@ name = "fuchsia-zircon-sys"
version = "0.3.3" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "human-panic" name = "human-panic"
version = "1.0.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (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)", "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)", "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)", "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -308,7 +362,7 @@ name = "isatty"
version = "0.1.9" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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)", "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]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "libc" name = "libc"
@ -348,7 +399,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libz-sys" name = "libz-sys"
version = "1.0.23" version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
@ -368,17 +419,17 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.1.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "miniz-sys" name = "miniz-sys"
version = "0.1.10" version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
@ -387,22 +438,21 @@ dependencies = [
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.1.3" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "miniz_oxide_c_api" name = "miniz_oxide_c_api"
version = "0.1.3" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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]] [[package]]
@ -414,6 +464,11 @@ dependencies = [
"winapi 0.3.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 = "nodrop"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.39" version = "0.1.39"
@ -429,15 +484,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.12" version = "0.10.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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]] [[package]]
@ -447,7 +502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "openssl-src" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
@ -455,12 +510,12 @@ dependencies = [
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.36" version = "0.9.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -470,7 +525,7 @@ name = "os_type"
version = "2.2.0" version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -514,7 +569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.4.20" version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -522,10 +577,10 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.6.8" version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -576,28 +631,39 @@ dependencies = [
"redox_syscall 0.1.40 (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 = "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]] [[package]]
name = "regex" name = "regex"
version = "0.2.11" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aho-corasick 0.6.8 (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.0 (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)", "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)", "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]] [[package]]
name = "regex" name = "regex"
version = "1.0.5" version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aho-corasick 0.6.8 (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.0 (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.2 (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)", "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]] [[package]]
@ -605,15 +671,15 @@ name = "regex-syntax"
version = "0.5.6" version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.2" version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -647,10 +713,15 @@ name = "schannel"
version = "0.1.14" version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "0.3.3" version = "0.3.3"
@ -662,7 +733,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
@ -672,17 +743,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.79" version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.79" version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"quote 0.6.8 (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.9 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -692,9 +763,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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]] [[package]]
name = "slog" name = "slog"
version = "2.4.1" version = "2.4.1"
@ -735,7 +811,7 @@ name = "socket2"
version = "0.3.8" version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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)", "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]] [[package]]
name = "structopt" name = "structopt"
version = "0.2.11" version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "structopt-derive" name = "structopt-derive"
version = "0.2.11" version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.0 (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)",
"syn 0.15.9 (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]] [[package]]
name = "syn" name = "syn"
version = "0.14.9" version = "0.15.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"quote 0.6.8 (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 = "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)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "synstructure" name = "synstructure"
version = "0.9.0" version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (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)", "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]] [[package]]
name = "tar" name = "tar"
version = "0.4.17" version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -831,7 +898,7 @@ name = "tempfile"
version = "3.0.4" version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@ -844,7 +911,7 @@ name = "term"
version = "0.5.1" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -887,7 +954,7 @@ name = "thread_local"
version = "0.3.6" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -905,12 +972,17 @@ name = "toml"
version = "0.4.8" version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "ucd-util" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -933,7 +1005,7 @@ dependencies = [
[[package]] [[package]]
name = "utf8-ranges" name = "utf8-ranges"
version = "1.0.1" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -941,7 +1013,7 @@ name = "uuid"
version = "0.6.5" version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -970,24 +1042,27 @@ name = "wasm-pack"
version = "0.5.1" version = "0.5.1"
dependencies = [ dependencies = [
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.3 (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)", "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)", "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)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.10.12 (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)", "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 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (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)", "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 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-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)", "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)", "structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.17 (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)", "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)", "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)", "which 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -999,7 +1074,7 @@ name = "which"
version = "2.0.0" version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1062,86 +1137,97 @@ dependencies = [
[metadata] [metadata]
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16"
"checksum curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08459503c415173da1ce6b41036a37b8bfdd86af46d45abb9964d4c61fe670ef" "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 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 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
"checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f" "checksum filetime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f57e64bf5eae62efd4efed005ae81a7115012a61f522bba54542e1a556af921"
"checksum flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4af030962d89d62aa52cd9492083b1cd9b2d1a77764878102a6c0f86b4d5444d" "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 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 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 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 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 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 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 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 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 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 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 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 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 memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
"checksum miniz_oxide 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba430291c9d6cedae28bcd2d49d1c32fc57d60cd49086646c5dd5673a870eb5" "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
"checksum miniz_oxide_c_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5a5b8234d6103ebfba71e29786da4608540f862de5ce980a1c94f86a40ca0d51" "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 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-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 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-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-src 111.0.1+1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d1edaed888fd85a54a2646bf02992931ddefdda3b1a748fc79f088a8db27fcbe"
"checksum openssl-sys 0.9.36 (registry+https://github.com/rust-lang/crates.io-index)" = "409d77eeb492a1aebd6eb322b2ee72ff7c7496b4434d98b3bf8be038755de65e" "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 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 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 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 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 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 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 proc-macro2 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ab2fc21ba78ac73e4ff6b3818ece00be4e175ffbef4d0a717d978b48b24150c4"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "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.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 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.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 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_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_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 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.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 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-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 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 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 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 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 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 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 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
"checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" "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 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 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-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" "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 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 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 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 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "41c4a2479a078509940d82773d90ff824a8c89533ab3b59cd3ce8b0c0e369c02"
"checksum structopt-derive 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "1383e5db585da799a5c4acc496c5c868e18bf82e658c00c75cc91038fa26b55f" "checksum structopt-derive 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5352090cfae7a2c85e1a31146268b53396106c88ca5d6ccee2e3fae83b6e35c2"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)" = "90c39a061e2f412a9f869540471ab679e85e50c6b05604daf28bc3060f75c430"
"checksum syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b10ee269228fb723234fce98e9aac0eaed2bd5f1ad2f6930e8d5b93f04445a1a" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "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 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 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" "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 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 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 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-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 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 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 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 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" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"

@ -14,8 +14,10 @@ atty = "0.2.11"
cargo_metadata = "0.6.0" cargo_metadata = "0.6.0"
console = "0.6.1" console = "0.6.1"
curl = "0.4.13" curl = "0.4.13"
dirs = "1.0.4"
failure = "0.1.2" failure = "0.1.2"
flate2 = "1.0.2" flate2 = "1.0.2"
hex = "0.3"
human-panic = "1.0.1" human-panic = "1.0.1"
indicatif = "0.9.0" indicatif = "0.9.0"
lazy_static = "1.1.0" lazy_static = "1.1.0"
@ -24,6 +26,7 @@ parking_lot = "0.6"
serde = "1.0.74" serde = "1.0.74"
serde_derive = "1.0.74" serde_derive = "1.0.74"
serde_json = "1.0.26" serde_json = "1.0.26"
siphasher = "0.2.3"
slog = "2.3" slog = "2.3"
slog-term = "2.4" slog-term = "2.4"
slog-async = "2.3" slog-async = "2.3"
@ -32,6 +35,7 @@ tar = "0.4.16"
toml = "0.4" toml = "0.4"
which = "2.0.0" which = "2.0.0"
zip = "0.4.2" zip = "0.4.2"
chrono = "0.4.6"
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"

@ -18,4 +18,5 @@
- [`src/utils.rs`](./tutorial/template-deep-dive/src-utils-rs.md) - [`src/utils.rs`](./tutorial/template-deep-dive/src-utils-rs.md)
- [Packaging and Publishing](./tutorial/packaging-and-publishing.md) - [Packaging and Publishing](./tutorial/packaging-and-publishing.md)
- [Using your Library](./tutorial/using-your-library.md) - [Using your Library](./tutorial/using-your-library.md)
- [`Cargo.toml` Configuration](./cargo-toml-configuration.md)
- [Contributing](./contributing.md) - [Contributing](./contributing.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
```

@ -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 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. 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 The `build` command accepts an optional profile argument: one of `--dev`,
output package using cargo's `--profiling`, or `--release`. If none is supplied, then `--release` is used.
[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 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 [cargo-profile-sections-documentation]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-profile-sections

@ -1,247 +1,257 @@
//! Utilities for finding and installing binaries that we depend on. //! Utilities for finding and installing binaries that we depend on.
use curl; use curl;
use error::Error; use dirs;
use failure; use failure::{Error, ResultExt};
use flate2; use flate2;
use slog::Logger; use hex;
use siphasher::sip::SipHasher13;
use std::collections::HashSet; use std::collections::HashSet;
use std::env;
use std::ffi; use std::ffi;
use std::fs; use std::fs;
use std::hash::{Hash, Hasher};
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tar; use tar;
use target;
use which::which;
use zip; use zip;
/// Get the path for a crate's directory of locally-installed binaries. /// Global cache for wasm-pack, currently containing binaries downloaded from
/// /// urls like wasm-bindgen and such.
/// This does not check whether or ensure that the directory exists. pub struct Cache {
pub fn local_bin_dir(crate_path: &Path) -> PathBuf { destination: PathBuf,
crate_path.join("bin")
} }
/// Ensure that the crate's directory for locally-installed binaries exists. /// Representation of a downloaded tarball/zip
pub fn ensure_local_bin_dir(crate_path: &Path) -> io::Result<()> { pub struct Download {
fs::create_dir_all(local_bin_dir(crate_path)) root: PathBuf,
} }
/// Get the path for where `bin` would be if we have a crate-local install for impl Cache {
/// it. /// Returns the global cache directory, as inferred from env vars and such.
/// ///
/// This does *not* check whether there is a file at that path or not. /// This function may return an error if a cache directory cannot be
/// /// determined.
/// This will automatically add the `.exe` extension for windows. pub fn new() -> Result<Cache, Error> {
pub fn local_bin_path(crate_path: &Path, bin: &str) -> PathBuf { let destination = dirs::cache_dir()
let mut p = local_bin_dir(crate_path).join(bin); .map(|p| p.join("wasm-pack"))
if target::WINDOWS { .or_else(|| {
p.set_extension("exe"); 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 /// Creates a new cache specifically at a particular directory, useful in
/// for the given binary. /// testing and such.
/// pub fn at(path: &Path) -> Cache {
/// If this function returns `Some(path)`, then a file at that path exists (or Cache {
/// at least existed when we checked! In general, we aren't really worried about destination: path.to_path_buf(),
/// racing with an uninstall of a tool that we rely on.)
pub fn bin_path(log: &Logger, crate_path: &Path, bin: &str) -> Option<PathBuf> {
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<PathBuf> {
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
} }
}; }
// Return the path to the global binary, if it exists. /// Joins a path to the destination of this cache, returning the result
let global_path = || -> Option<PathBuf> { pub fn join(&self, path: &Path) -> PathBuf {
debug!(log, "Looking for global {} binary on $PATH", bin); self.destination.join(path)
if let Ok(p) = which(bin) { }
Some(p)
} else { /// Downloads a tarball or zip file from the specified url, extracting it
None /// 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<Option<Download>, 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<T, E>(url: &str, r: Result<T, E>) -> Result<T, impl failure::Fail> if !install_permitted {
where return Ok(None);
Result<T, E>: failure::ResultExt<T, E>, }
{
use failure::ResultExt;
r.with_context(|_| format!("when requesting {}", url))
}
fn transfer( let data = curl(&url).with_context(|_| format!("failed to download from {}", url))?;
url: &str,
easy: &mut curl::easy::Easy,
data: &mut Vec<u8>,
) -> 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(())
}
fn curl(url: &str) -> Result<Vec<u8>, failure::Error> { // Extract everything in a temporary directory in case we're ctrl-c'd.
let mut data = Vec::new(); // 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(); if url.ends_with(".tar.gz") {
with_url_context(url, easy.follow_location(true))?; self.extract_tarball(&data, &temp, binaries)
with_url_context(url, easy.url(url))?; .with_context(|_| format!("failed to extract tarball from {}", url))?;
transfer(url, &mut easy, &mut data)?; } 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())?; // Now that everything is ready move this over to our destination and
if 200 <= status_code && status_code < 300 { // we're good to go.
Ok(data) fs::rename(&temp, &destination)?;
} else { Ok(Some(Download { root: destination }))
Err(Error::http(&format!(
"received a bad HTTP status code ({}) when requesting {}",
status_code, url
))
.into())
} }
}
/// Download the `.tar.gz` file at the given URL and unpack the given binaries fn extract_tarball(&self, tarball: &[u8], dst: &Path, binaries: &[&str]) -> Result<(), Error> {
/// from it into the given crate. let mut binaries: HashSet<_> = binaries.into_iter().map(ffi::OsStr::new).collect();
/// let mut archive = tar::Archive::new(flate2::read::GzDecoder::new(tarball));
/// Upon success, every `$BIN` in `binaries` will be at `$CRATE/bin/$BIN`.
pub fn install_binaries_from_targz_at_url<'a, I>( for entry in archive.entries()? {
crate_path: &Path, let mut entry = entry?;
url: &str,
binaries: I, let dest = match entry.path()?.file_stem() {
) -> Result<(), failure::Error> Some(f) if binaries.contains(f) => {
where binaries.remove(f);
I: IntoIterator<Item = &'a str>, dst.join(entry.path()?.file_name().unwrap())
{ }
let mut binaries: HashSet<_> = binaries.into_iter().map(ffi::OsStr::new).collect(); _ => continue,
};
let tarball = curl(&url).map_err(|e| Error::http(&e.to_string()))?;
let mut archive = tar::Archive::new(flate2::read::GzDecoder::new(&tarball[..])); entry.unpack(dest)?;
}
ensure_local_bin_dir(crate_path)?;
let bin = local_bin_dir(crate_path); if !binaries.is_empty() {
bail!(
for entry in archive.entries()? { "the tarball was missing expected executables: {}",
let mut entry = entry?; binaries
.into_iter()
let dest = match entry.path()?.file_stem() { .map(|s| s.to_string_lossy())
Some(f) if binaries.contains(f) => { .collect::<Vec<_>>()
binaries.remove(f); .join(", "),
bin.join(entry.path()?.file_name().unwrap()) )
} }
_ => continue,
};
entry.unpack(dest)?;
}
if binaries.is_empty() {
Ok(()) Ok(())
} else { }
Err(Error::archive(&format!(
"the tarball at {} was missing expected executables: {}", fn extract_zip(&self, zip: &[u8], dst: &Path, binaries: &[&str]) -> Result<(), Error> {
url, let mut binaries: HashSet<_> = binaries.into_iter().map(ffi::OsStr::new).collect();
binaries
.into_iter() let data = io::Cursor::new(zip);
.map(|s| s.to_string_lossy()) let mut zip = zip::ZipArchive::new(data)?;
.collect::<Vec<_>>()
.join(", "), for i in 0..zip.len() {
)) let mut entry = zip.by_index(i).unwrap();
.into()) 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::<Vec<_>>()
.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. impl Download {
/// /// Manually constructs a download at the specified path
/// Upon success, the binaries will be at the `$CRATE/bin/$BIN` path. pub fn at(path: &Path) -> Download {
pub fn install_binaries_from_zip_at_url<'a, I>( Download {
crate_path: &Path, root: path.to_path_buf(),
url: &str, }
binaries: I,
) -> Result<(), failure::Error>
where
I: IntoIterator<Item = &'a str>,
{
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,
};
} }
if binaries.is_empty() { /// Returns the path to the binary `name` within this download
Ok(()) pub fn binary(&self, name: &str) -> PathBuf {
} else { let ret = self
Err(Error::archive(&format!( .root
"the zip at {} was missing expected executables: {}", .join(name)
url, .with_extension(env::consts::EXE_EXTENSION);
binaries assert!(ret.exists(), "binary {} doesn't exist", ret.display());
.into_iter() return ret;
.map(|s| s.to_string_lossy())
.collect::<Vec<_>>()
.join(", "),
))
.into())
} }
} }
#[cfg(unix)] fn curl(url: &str) -> Result<Vec<u8>, Error> {
fn bin_open_options() -> fs::OpenOptions { let mut data = Vec::new();
use std::os::unix::fs::OpenOptionsExt;
let mut opts = fs::OpenOptions::new(); let mut easy = curl::easy::Easy::new();
opts.mode(0o755); easy.follow_location(true)?;
opts 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))] let status_code = easy.response_code()?;
fn bin_open_options() -> fs::OpenOptions { if 200 <= status_code && status_code < 300 {
fs::OpenOptions::new() Ok(data)
} else {
bail!(
"received a bad HTTP status code ({}) when requesting {}",
status_code,
url
)
}
} }

@ -1,15 +1,18 @@
//! Functionality related to installing and running `wasm-bindgen`. //! 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 child;
use command::build::BuildProfile;
use emoji; use emoji;
use error::Error;
use failure::{self, ResultExt}; use failure::{self, ResultExt};
use manifest::CrateData;
use progressbar::Step; use progressbar::Step;
use slog::Logger; use slog::Logger;
use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use target; use target;
use which::which;
use PBAR; use PBAR;
/// Install the `wasm-bindgen` CLI. /// Install the `wasm-bindgen` CLI.
@ -19,46 +22,66 @@ use PBAR;
/// tarball from the GitHub releases page, if this target has prebuilt /// tarball from the GitHub releases page, if this target has prebuilt
/// binaries. Finally, falls back to `cargo install`. /// binaries. Finally, falls back to `cargo install`.
pub fn install_wasm_bindgen( pub fn install_wasm_bindgen(
root_path: &Path, cache: &Cache,
version: &str, version: &str,
install_permitted: bool, install_permitted: bool,
step: &Step, step: &Step,
log: &Logger, log: &Logger,
) -> Result<(), failure::Error> { ) -> Result<Download, failure::Error> {
// If the `wasm-bindgen` dependency is already met, print a message and return. // If `wasm-bindgen` is installed globally and it has the right version, use
if wasm_bindgen_path(log, root_path) // that. Assume that other tools are installed next to it.
.map(|bindgen_path| wasm_bindgen_version_check(&bindgen_path, version, log)) //
.unwrap_or(false) // This situation can arise if `wasm-bindgen` is already installed via
{ // `cargo install`, for example.
let msg = format!("{}wasm-bindgen already installed...", emoji::DOWN_ARROW); if let Ok(path) = which("wasm-bindgen") {
PBAR.step(step, &msg); debug!(
return Ok(()); log,
} "found global wasm-bindgen binary at: {}",
path.display()
// If the `wasm-bindgen` dependency was not met, and installs are not );
// permitted, return a configuration error. if wasm_bindgen_version_check(&path, version, log) {
if !install_permitted { return Ok(Download::at(path.parent().unwrap()));
let msg = format!("wasm-bindgen v{} is not installed!", version); }
return Err(Error::crate_config(&msg).into());
} }
let msg = format!("{}Installing wasm-bindgen...", emoji::DOWN_ARROW); let msg = format!("{}Installing wasm-bindgen...", emoji::DOWN_ARROW);
PBAR.step(step, &msg); PBAR.step(step, &msg);
download_prebuilt_wasm_bindgen(root_path, version).or_else(|e| { let dl = download_prebuilt_wasm_bindgen(&cache, version, install_permitted);
warn!( match dl {
log, Ok(dl) => return Ok(dl),
"could not download pre-built `wasm-bindgen`: {}. Falling back to `cargo install`.", e Err(e) => {
); warn!(
cargo_install_wasm_bindgen(log, root_path, version) 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( pub fn download_prebuilt_wasm_bindgen(
root_path: &Path, cache: &Cache,
version: &str, version: &str,
) -> Result<(), failure::Error> { install_permitted: bool,
) -> Result<Download, failure::Error> {
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<String> {
let target = if target::LINUX && target::x86_64 { let target = if target::LINUX && target::x86_64 {
"x86_64-unknown-linux-musl" "x86_64-unknown-linux-musl"
} else if target::MACOS && target::x86_64 { } else if target::MACOS && target::x86_64 {
@ -66,32 +89,40 @@ pub fn download_prebuilt_wasm_bindgen(
} else if target::WINDOWS && target::x86_64 { } else if target::WINDOWS && target::x86_64 {
"x86_64-pc-windows-msvc" "x86_64-pc-windows-msvc"
} else { } else {
return Err(Error::unsupported( return None;
"there are no pre-built `wasm-bindgen` binaries for this target",
)
.into());
}; };
let url = format!( Some(format!(
"https://github.com/rustwasm/wasm-bindgen/releases/download/{0}/wasm-bindgen-{0}-{1}.tar.gz", "https://github.com/rustwasm/wasm-bindgen/releases/download/{0}/wasm-bindgen-{0}-{1}.tar.gz",
version, version,
target 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 /// Use `cargo install` to install the `wasm-bindgen` CLI locally into the given
/// crate. /// crate.
pub fn cargo_install_wasm_bindgen( pub fn cargo_install_wasm_bindgen(
logger: &Logger, logger: &Logger,
crate_path: &Path, cache: &Cache,
version: &str, version: &str,
) -> Result<(), failure::Error> { install_permitted: bool,
) -> Result<Download, failure::Error> {
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"); let mut cmd = Command::new("cargo");
cmd.arg("install") cmd.arg("install")
.arg("--force") .arg("--force")
@ -99,66 +130,74 @@ pub fn cargo_install_wasm_bindgen(
.arg("--version") .arg("--version")
.arg(version) .arg(version)
.arg("--root") .arg("--root")
.arg(crate_path); .arg(&tmp);
child::run(logger, cmd, "cargo install").context("Installing wasm-bindgen with cargo")?; 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 /// Run the `wasm-bindgen` CLI to generate bindings for the current crate's
/// `.wasm`. /// `.wasm`.
pub fn wasm_bindgen_build( pub fn wasm_bindgen_build(
path: &Path, data: &CrateData,
bindgen: &Download,
out_dir: &Path, out_dir: &Path,
name: &str,
disable_dts: bool, disable_dts: bool,
target: &str, target: &str,
debug: bool, profile: BuildProfile,
step: &Step, step: &Step,
log: &Logger, log: &Logger,
) -> Result<(), failure::Error> { ) -> Result<(), failure::Error> {
let msg = format!("{}Running WASM-bindgen...", emoji::RUNNER); let msg = format!("{}Running WASM-bindgen...", emoji::RUNNER);
PBAR.step(step, &msg); PBAR.step(step, &msg);
let binary_name = name.replace("-", "_"); let release_or_debug = match profile {
let release_or_debug = if debug { "debug" } else { "release" }; BuildProfile::Release | BuildProfile::Profiling => "release",
BuildProfile::Dev => "debug",
};
let out_dir = out_dir.to_str().unwrap(); let out_dir = out_dir.to_str().unwrap();
if let Some(wasm_bindgen_path) = wasm_bindgen_path(log, path) { let wasm_path = data
let wasm_path = format!( .target_directory()
"target/wasm32-unknown-unknown/{}/{}.wasm", .join("wasm32-unknown-unknown")
release_or_debug, binary_name .join(release_or_debug)
); .join(data.crate_name())
let dts_arg = if disable_dts { .with_extension("wasm");
"--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");
}
child::run(log, cmd, "wasm-bindgen").context("Running the wasm-bindgen CLI")?; let dts_arg = if disable_dts {
Ok(()) "--no-typescript"
} else { } 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. /// 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) .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<PathBuf> {
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<PathBuf> {
bin_path(log, crate_path, "wasm-bindgen-test-runner")
}

@ -1,9 +1,9 @@
//! Building a Rust crate into a `.wasm` binary. //! Building a Rust crate into a `.wasm` binary.
use child; use child;
use command::build::BuildProfile;
use emoji; use emoji;
use error::Error; use failure::{Error, ResultExt};
use failure::ResultExt;
use manifest::Crate; use manifest::Crate;
use progressbar::Step; use progressbar::Step;
use slog::Logger; use slog::Logger;
@ -13,47 +13,35 @@ use std::str;
use PBAR; use PBAR;
/// Ensure that `rustc` is present and that it is >= 1.30.0 /// Ensure that `rustc` is present and that it is >= 1.30.0
pub fn check_rustc_version(step: &Step) -> Result<String, failure::Error> { pub fn check_rustc_version(step: &Step) -> Result<String, Error> {
let msg = format!("{}Checking `rustc` version...", emoji::CRAB); let msg = format!("{}Checking `rustc` version...", emoji::CRAB);
PBAR.step(step, &msg); PBAR.step(step, &msg);
let local_minor_version = rustc_minor_version(); let local_minor_version = rustc_minor_version();
match local_minor_version { match local_minor_version {
Some(mv) => { Some(mv) => {
if mv < 30 { if mv < 30 {
return Err(Error::RustcVersion { bail!(
message: format!( "Your version of Rust, '1.{}', is not supported. Please install Rust version 1.30.0 or higher.",
"Your version of Rust, '1.{}', is not supported. Please install Rust version 1.30.0 or higher.", mv.to_string()
mv.to_string() )
),
local_minor_version: mv.to_string(),
}.into())
} else { } else {
Ok(mv.to_string()) Ok(mv.to_string())
} }
}, },
None => Err(Error::RustcMissing { 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."),
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()),
} }
} }
/// Checks if `wasm-pack` is updated to the latest version /// Checks if `wasm-pack` is updated to the latest version
pub fn check_wasm_pack_version(step: &Step) -> Result<(), failure::Error> { pub fn check_wasm_pack_versions() -> Result<(String, String), Error> {
let msg = format!("{}Checking `wasm-pack` version...", emoji::PACKAGE); match wasm_pack_local_version() {
PBAR.step(step, &msg); Some(local) => {
let wasm_pack_local_version = wasm_pack_local_version(); match Crate::return_wasm_pack_latest_version() {
let wasm_pack_latest_version = Crate::return_wasm_pack_latest_version(); Some(latest) => Ok((local, latest)),
match wasm_pack_local_version { None => Ok((local, "".to_string()))
Some(lv) => {
if !(lv == wasm_pack_latest_version) {
Ok(PBAR.info(&format!("There's a newer version of wasm-pack available, the new version is: {}, you are using: {}", wasm_pack_latest_version, lv)))
} else {
Ok(())
} }
}, },
None => Err(Error::WasmPackMissing { None => bail!("We can't figure out what your wasm-pack version is, make sure the installation path is correct.")
message: "We can't figure out what your wasm-pack version is, make sure the installation path is correct.".to_string(),
}.into()),
} }
} }
@ -101,7 +89,7 @@ fn wasm_pack_local_version() -> Option<String> {
/// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for /// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for
/// current toolchain /// 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); let msg = format!("{}Adding WASM target...", emoji::TARGET);
PBAR.step(step, &msg); PBAR.step(step, &msg);
let mut cmd = Command::new("rustup"); 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( pub fn cargo_build_wasm(
log: &Logger, log: &Logger,
path: &Path, path: &Path,
debug: bool, profile: BuildProfile,
step: &Step, step: &Step,
) -> Result<(), failure::Error> { ) -> Result<(), Error> {
let msg = format!("{}Compiling to WASM...", emoji::CYCLONE); let msg = format!("{}Compiling to WASM...", emoji::CYCLONE);
PBAR.step(step, &msg); PBAR.step(step, &msg);
let mut cmd = Command::new("cargo"); let mut cmd = Command::new("cargo");
cmd.current_dir(path).arg("build").arg("--lib"); cmd.current_dir(path).arg("build").arg("--lib");
if !debug { match profile {
cmd.arg("--release"); 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"); 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(()) Ok(())
} }
/// Run `cargo build --tests` targetting `wasm32-unknown-unknown`. /// Run `cargo build --tests` targetting `wasm32-unknown-unknown`.
pub fn cargo_build_wasm_tests( pub fn cargo_build_wasm_tests(log: &Logger, path: &Path, debug: bool) -> Result<(), Error> {
log: &Logger,
path: &Path,
debug: bool,
) -> Result<(), failure::Error> {
let mut cmd = Command::new("cargo"); let mut cmd = Command::new("cargo");
cmd.current_dir(path).arg("build").arg("--tests"); cmd.current_dir(path).arg("build").arg("--tests");
if !debug { if !debug {

@ -3,8 +3,7 @@
//! This module helps us ensure that all child processes that we spawn get //! This module helps us ensure that all child processes that we spawn get
//! properly logged and their output is logged as well. //! properly logged and their output is logged as well.
use error::Error; use failure::Error;
use failure;
use slog::Logger; use slog::Logger;
use std::{ use std::{
io::{self, Read}, io::{self, Read},
@ -120,7 +119,7 @@ pub fn run(
logger: &Logger, logger: &Logger,
mut command: process::Command, mut command: process::Command,
command_name: &str, command_name: &str,
) -> Result<String, failure::Error> { ) -> Result<String, Error> {
info!(logger, "Running {:?}", command); info!(logger, "Running {:?}", command);
let mut child = command let mut child = command
@ -171,7 +170,7 @@ pub fn run(
if exit.success() { if exit.success() {
return Ok(stdout); return Ok(stdout);
} else { } else {
let msg = format!("`{}` did not exit successfully", command_name); drop((stdout, stderr));
return Err(Error::cli(&msg, stdout.into(), stderr.into(), exit).into()); bail!("failed to execute `{}`: exited with {}", command_name, exit)
} }
} }

@ -1,10 +1,11 @@
//! Implementation of the `wasm-pack build` command. //! Implementation of the `wasm-pack build` command.
use binaries::{Cache, Download};
use bindgen; use bindgen;
use build; use build;
use command::utils::{create_pkg_dir, set_crate_path}; use command::utils::{create_pkg_dir, set_crate_path};
use emoji; use emoji;
use error::Error; use failure::Error;
use indicatif::HumanDuration; use indicatif::HumanDuration;
use lockfile::Lockfile; use lockfile::Lockfile;
use manifest; use manifest;
@ -17,16 +18,18 @@ use std::time::Instant;
use PBAR; use PBAR;
/// Everything required to configure and run the `wasm-pack init` command. /// 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_path: PathBuf,
pub crate_data: manifest::CrateData,
pub scope: Option<String>, pub scope: Option<String>,
pub disable_dts: bool, pub disable_dts: bool,
pub target: String, pub target: String,
pub debug: bool, pub profile: BuildProfile,
pub mode: BuildMode, pub mode: BuildMode,
// build_config: Option<BuildConfig>,
pub crate_name: String,
pub out_dir: PathBuf, pub out_dir: PathBuf,
pub bindgen: Option<Download>,
pub cache: Cache,
} }
/// The `BuildMode` determines which mode of initialization we are running, and /// The `BuildMode` determines which mode of initialization we are running, and
@ -55,11 +58,23 @@ impl FromStr for BuildMode {
"no-install" => Ok(BuildMode::Noinstall), "no-install" => Ok(BuildMode::Noinstall),
"normal" => Ok(BuildMode::Normal), "normal" => Ok(BuildMode::Normal),
"force" => Ok(BuildMode::Force), "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. /// Everything required to configure and run the `wasm-pack build` command.
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
pub struct BuildOptions { pub struct BuildOptions {
@ -81,43 +96,71 @@ pub struct BuildOptions {
pub disable_dts: bool, pub disable_dts: bool,
#[structopt(long = "target", short = "t", default_value = "browser")] #[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, pub target: String,
#[structopt(long = "debug")] #[structopt(long = "debug")]
/// Build without --release. /// Deprecated. Renamed to `--dev`.
debug: bool, debug: bool,
// build config from manifest
// build_config: Option<BuildConfig>, #[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")] #[structopt(long = "out-dir", short = "d", default_value = "pkg")]
/// Sets the output directory with a relative path. /// Sets the output directory with a relative path.
pub out_dir: String, 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 { impl Build {
/// Construct a build command from the given options. /// Construct a build command from the given options.
pub fn try_from_opts(build_opts: BuildOptions) -> Result<Self, failure::Error> { pub fn try_from_opts(build_opts: BuildOptions) -> Result<Self, Error> {
let crate_path = set_crate_path(build_opts.path)?; 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 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 { Ok(Build {
crate_path, crate_path,
crate_data,
scope: build_opts.scope, scope: build_opts.scope,
disable_dts: build_opts.disable_dts, disable_dts: build_opts.disable_dts,
target: build_opts.target, target: build_opts.target,
debug: build_opts.debug, profile,
mode: build_opts.mode, mode: build_opts.mode,
// build_config,
crate_name,
out_dir, 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. /// 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 process_steps = Build::get_process_steps(&self.mode);
let mut step_counter = Step::new(process_steps.len()); let mut step_counter = Step::new(process_steps.len());
@ -160,7 +203,6 @@ impl Build {
match &mode { match &mode {
BuildMode::Normal => steps![ BuildMode::Normal => steps![
step_check_rustc_version, step_check_rustc_version,
step_check_wasm_pack_version,
step_check_crate_config, step_check_crate_config,
step_add_wasm_target, step_add_wasm_target,
step_build_wasm, step_build_wasm,
@ -172,7 +214,6 @@ impl Build {
], ],
BuildMode::Noinstall => steps![ BuildMode::Noinstall => steps![
step_check_rustc_version, step_check_rustc_version,
step_check_wasm_pack_version,
step_check_crate_config, step_check_crate_config,
step_build_wasm, step_build_wasm,
step_create_dir, step_create_dir,
@ -190,11 +231,13 @@ impl Build {
} }
} }
fn step_check_rustc_version( /// Returns local and latest versions of wasm-pack
&mut self, pub fn return_wasm_pack_versions() -> Result<(String, String), Error> {
step: &Step, let (local, latest) = build::check_wasm_pack_versions()?;
log: &Logger, Ok((local, latest))
) -> Result<(), failure::Error> { }
fn step_check_rustc_version(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Checking rustc version..."); info!(&log, "Checking rustc version...");
let version = build::check_rustc_version(step)?; let version = build::check_rustc_version(step)?;
let msg = format!("rustc version is {}.", version); let msg = format!("rustc version is {}.", version);
@ -202,35 +245,23 @@ impl Build {
Ok(()) Ok(())
} }
fn step_check_wasm_pack_version( fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
&mut self,
step: &Step,
log: &Logger,
) -> Result<(), failure::Error> {
info!(&log, "Checking wasm-pack version...");
let version = build::check_wasm_pack_version(step)?;
let msg = format!("wasm-pack version is: {:?}.", version);
info!(&log, "{}", &msg);
Ok(())
}
fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> {
info!(&log, "Checking crate configuration..."); 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."); info!(&log, "Crate is correctly configured.");
Ok(()) 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..."); info!(&log, "Adding wasm-target...");
build::rustup_add_wasm_target(log, step)?; build::rustup_add_wasm_target(log, step)?;
info!(&log, "Adding wasm-target was successful."); info!(&log, "Adding wasm-target was successful.");
Ok(()) 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..."); 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!( info!(
&log, &log,
@ -244,17 +275,16 @@ impl Build {
Ok(()) 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..."); info!(&log, "Creating a pkg directory...");
create_pkg_dir(&self.out_dir, step)?; create_pkg_dir(&self.out_dir, step)?;
info!(&log, "Created a pkg directory at {:#?}.", &self.crate_path); info!(&log, "Created a pkg directory at {:#?}.", &self.crate_path);
Ok(()) 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..."); info!(&log, "Writing a package.json...");
manifest::write_package_json( self.crate_data.write_package_json(
&self.crate_path,
&self.out_dir, &self.out_dir,
&self.scope, &self.scope,
self.disable_dts, self.disable_dts,
@ -269,20 +299,16 @@ impl Build {
Ok(()) 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..."); info!(&log, "Copying readme from crate...");
readme::copy_from_crate(&self.crate_path, &self.out_dir, step)?; readme::copy_from_crate(&self.crate_path, &self.out_dir, step)?;
info!(&log, "Copied readme from crate to {:#?}.", &self.out_dir); info!(&log, "Copied readme from crate to {:#?}.", &self.out_dir);
Ok(()) Ok(())
} }
fn step_install_wasm_bindgen( fn step_install_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
&mut self,
step: &Step,
log: &Logger,
) -> Result<(), failure::Error> {
info!(&log, "Identifying wasm-bindgen dependency..."); 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()?; let bindgen_version = lockfile.require_wasm_bindgen()?;
info!(&log, "Installing wasm-bindgen-cli..."); info!(&log, "Installing wasm-bindgen-cli...");
let install_permitted = match self.mode { let install_permitted = match self.mode {
@ -290,35 +316,27 @@ impl Build {
BuildMode::Force => true, BuildMode::Force => true,
BuildMode::Noinstall => false, BuildMode::Noinstall => false,
}; };
bindgen::install_wasm_bindgen( let bindgen = bindgen::install_wasm_bindgen(
&self.crate_path, &self.cache,
&bindgen_version, &bindgen_version,
install_permitted, install_permitted,
step, step,
log, log,
)?; )?;
self.bindgen = Some(bindgen);
info!(&log, "Installing wasm-bindgen-cli was successful."); 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(()) 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..."); info!(&log, "Building the wasm bindings...");
bindgen::wasm_bindgen_build( bindgen::wasm_bindgen_build(
&self.crate_path, &self.crate_data,
self.bindgen.as_ref().unwrap(),
&self.out_dir, &self.out_dir,
&self.crate_name,
self.disable_dts, self.disable_dts,
&self.target, &self.target,
self.debug, self.profile,
step, step,
log, log,
)?; )?;

@ -13,11 +13,12 @@ use self::login::login;
use self::pack::pack; use self::pack::pack;
use self::publish::{access::Access, publish}; use self::publish::{access::Access, publish};
use self::test::{Test, TestOptions}; use self::test::{Test, TestOptions};
use error::Error; use failure::Error;
use slog::Logger; use slog::Logger;
use std::path::PathBuf; use std::path::PathBuf;
use std::result; use std::result;
use PBAR; use std::sync::mpsc;
use std::thread;
/// The various kinds of commands that `wasm-pack` can execute. /// The various kinds of commands that `wasm-pack` can execute.
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
@ -83,10 +84,27 @@ pub enum Command {
Test(TestOptions), 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! /// 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 // Run the correct command based off input and store the result of it so that we can clear
// the progress bar then return it // the progress bar then return it
let update_available = background_check_for_updates();
let status = match command { let status = match command {
Command::Build(build_opts) => { Command::Build(build_opts) => {
info!(&log, "Running build command..."); info!(&log, "Running build command...");
@ -125,17 +143,8 @@ pub fn run_wasm_pack(command: Command, log: &Logger) -> result::Result<(), failu
} }
}; };
match status { if let Ok(update_available) = update_available.try_recv() {
Ok(_) => {} println!("There's a newer version of wasm-pack available, the new version is: {}, you are using: {}", update_available.1, update_available.0);
Err(ref e) => {
error!(&log, "{}", e);
for c in e.iter_chain() {
if let Some(e) = c.downcast_ref::<Error>() {
PBAR.error(e.error_type());
break;
}
}
}
} }
// Return the actual status of the program to the main function // Return the actual status of the program to the main function

@ -1,5 +1,5 @@
use command::utils::{find_pkg_directory, set_crate_path}; use command::utils::{find_pkg_directory, set_crate_path};
use error::Error; use failure::Error;
use npm; use npm;
use slog::Logger; use slog::Logger;
use std::path::PathBuf; use std::path::PathBuf;
@ -8,15 +8,16 @@ use PBAR;
/// Executes the 'npm pack' command on the 'pkg' directory /// Executes the 'npm pack' command on the 'pkg' directory
/// which creates a tarball that can be published to the NPM registry /// which creates a tarball that can be published to the NPM registry
pub fn pack(path: Option<PathBuf>, log: &Logger) -> result::Result<(), failure::Error> { pub fn pack(path: Option<PathBuf>, log: &Logger) -> result::Result<(), Error> {
let crate_path = set_crate_path(path)?; let crate_path = set_crate_path(path)?;
info!(&log, "Packing up the npm package..."); info!(&log, "Packing up the npm package...");
let pkg_directory = find_pkg_directory(&crate_path).ok_or(Error::PkgNotFound { let pkg_directory = find_pkg_directory(&crate_path).ok_or_else(|| {
message: format!( format_err!(
"Unable to find the pkg directory at path {:#?}, or in a child directory of {:#?}", "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())?; npm::npm_pack(log, &pkg_directory.to_string_lossy())?;
info!( info!(

@ -1,4 +1,4 @@
use error::Error; use failure::Error;
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
@ -19,7 +19,7 @@ impl FromStr for Access {
"public" => Ok(Access::Public), "public" => Ok(Access::Public),
"restricted" => Ok(Access::Restricted), "restricted" => Ok(Access::Restricted),
"private" => 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),
} }
} }
} }

@ -3,7 +3,7 @@ pub mod access;
use self::access::Access; use self::access::Access;
use command::utils::{find_pkg_directory, set_crate_path}; use command::utils::{find_pkg_directory, set_crate_path};
use error::Error; use failure::Error;
use npm; use npm;
use slog::Logger; use slog::Logger;
use std::path::PathBuf; use std::path::PathBuf;
@ -16,16 +16,17 @@ pub fn publish(
path: Option<PathBuf>, path: Option<PathBuf>,
access: Option<Access>, access: Option<Access>,
log: &Logger, log: &Logger,
) -> result::Result<(), failure::Error> { ) -> result::Result<(), Error> {
let crate_path = set_crate_path(path)?; let crate_path = set_crate_path(path)?;
info!(&log, "Publishing the npm package..."); info!(&log, "Publishing the npm package...");
info!(&log, "npm info located in the npm debug log"); info!(&log, "npm info located in the npm debug log");
let pkg_directory = find_pkg_directory(&crate_path).ok_or(Error::PkgNotFound { let pkg_directory = find_pkg_directory(&crate_path).ok_or_else(|| {
message: format!( format_err!(
"Unable to find the pkg directory at path '{:#?}', or in a child directory of '{:#?}'", "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)?; npm::npm_publish(log, &pkg_directory.to_string_lossy(), access)?;

@ -1,12 +1,13 @@
//! Implementation of the `wasm-pack test` command. //! Implementation of the `wasm-pack test` command.
use super::build::BuildMode; use super::build::BuildMode;
use binaries::Cache;
use bindgen; use bindgen;
use build; use build;
use command::utils::set_crate_path; use command::utils::set_crate_path;
use console::style; use console::style;
use emoji; use emoji;
use error::Error; use failure::Error;
use indicatif::HumanDuration; use indicatif::HumanDuration;
use lockfile::Lockfile; use lockfile::Lockfile;
use manifest; use manifest;
@ -81,6 +82,8 @@ pub struct TestOptions {
/// A configured `wasm-pack test` command. /// A configured `wasm-pack test` command.
pub struct Test { pub struct Test {
crate_path: PathBuf, crate_path: PathBuf,
crate_data: manifest::CrateData,
cache: Cache,
node: bool, node: bool,
mode: BuildMode, mode: BuildMode,
firefox: bool, firefox: bool,
@ -94,11 +97,11 @@ pub struct Test {
test_runner_path: Option<PathBuf>, test_runner_path: Option<PathBuf>,
} }
type TestStep = fn(&mut Test, &Step, &Logger) -> Result<(), failure::Error>; type TestStep = fn(&mut Test, &Step, &Logger) -> Result<(), Error>;
impl Test { impl Test {
/// Construct a test command from the given options. /// Construct a test command from the given options.
pub fn try_from_opts(test_opts: TestOptions) -> Result<Self, failure::Error> { pub fn try_from_opts(test_opts: TestOptions) -> Result<Self, Error> {
let TestOptions { let TestOptions {
path, path,
node, node,
@ -114,32 +117,24 @@ impl Test {
} = test_opts; } = test_opts;
let crate_path = set_crate_path(path)?; let crate_path = set_crate_path(path)?;
let crate_data = manifest::CrateData::new(&crate_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 any_browser = chrome || firefox || safari; let any_browser = chrome || firefox || safari;
if !node && !any_browser { if !node && !any_browser {
return Err(Error::crate_config( bail!("Must specify at least one of `--node`, `--chrome`, `--firefox`, or `--safari`")
"Must specify at least one of `--node`, `--chrome`, `--firefox`, or `--safari`",
)
.into());
} }
if headless && !any_browser { if headless && !any_browser {
return Err(Error::crate_config( bail!(
"The `--headless` flag only applies to browser tests. Node does not provide a UI, \ "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 { Ok(Test {
cache: Cache::new()?,
crate_path, crate_path,
crate_data,
node, node,
mode, mode,
chrome, 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. /// 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 process_steps = self.get_process_steps();
let mut step_counter = Step::new(process_steps.len()); let mut step_counter = Step::new(process_steps.len());
@ -188,7 +188,6 @@ impl Test {
match self.mode { match self.mode {
BuildMode::Normal => steps![ BuildMode::Normal => steps![
step_check_rustc_version, step_check_rustc_version,
step_check_crate_config,
step_add_wasm_target, step_add_wasm_target,
step_build_tests, step_build_tests,
step_install_wasm_bindgen, step_install_wasm_bindgen,
@ -213,7 +212,6 @@ impl Test {
step_test_safari if self.safari, step_test_safari if self.safari,
], ],
BuildMode::Noinstall => steps![ BuildMode::Noinstall => steps![
step_check_crate_config,
step_build_tests, step_build_tests,
step_install_wasm_bindgen, step_install_wasm_bindgen,
step_test_node if self.node, step_test_node if self.node,
@ -227,32 +225,21 @@ impl Test {
} }
} }
fn step_check_rustc_version( fn step_check_rustc_version(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
&mut self,
step: &Step,
log: &Logger,
) -> Result<(), failure::Error> {
info!(log, "Checking rustc version..."); info!(log, "Checking rustc version...");
let _ = build::check_rustc_version(step)?; let _ = build::check_rustc_version(step)?;
info!(log, "Rustc version is correct."); info!(log, "Rustc version is correct.");
Ok(()) Ok(())
} }
fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), failure::Error> { fn step_add_wasm_target(&mut self, step: &Step, log: &Logger) -> Result<(), 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> {
info!(&log, "Adding wasm-target..."); info!(&log, "Adding wasm-target...");
build::rustup_add_wasm_target(log, step)?; build::rustup_add_wasm_target(log, step)?;
info!(&log, "Adding wasm-target was successful."); info!(&log, "Adding wasm-target was successful.");
Ok(()) 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..."); info!(log, "Compiling tests to wasm...");
let msg = format!("{}Compiling tests to WASM...", emoji::CYCLONE); let msg = format!("{}Compiling tests to WASM...", emoji::CYCLONE);
@ -264,13 +251,9 @@ impl Test {
Ok(()) Ok(())
} }
fn step_install_wasm_bindgen( fn step_install_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
&mut self,
step: &Step,
log: &Logger,
) -> Result<(), failure::Error> {
info!(&log, "Identifying wasm-bindgen dependency..."); 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()?; let bindgen_version = lockfile.require_wasm_bindgen()?;
// Unlike `wasm-bindgen` and `wasm-bindgen-cli`, `wasm-bindgen-test` // 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 // `wasm32-unkown-unknown`. Don't enforce that it is the same version as
// `wasm-bindgen`. // `wasm-bindgen`.
if lockfile.wasm_bindgen_test_version().is_none() { 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\ "Ensure that you have \"{}\" as a dependency in your Cargo.toml file:\n\
[dev-dependencies]\n\ [dev-dependencies]\n\
wasm-bindgen-test = \"0.2\"", wasm-bindgen-test = \"0.2\"",
style("wasm-bindgen-test").bold().dim(), style("wasm-bindgen-test").bold().dim(),
); )
return Err(Error::CrateConfig { message }.into());
} }
let install_permitted = match self.mode { let install_permitted = match self.mode {
@ -303,22 +285,21 @@ impl Test {
} }
}; };
bindgen::install_wasm_bindgen( let dl = bindgen::install_wasm_bindgen(
&self.crate_path, &self.cache,
&bindgen_version, &bindgen_version,
install_permitted, install_permitted,
step, step,
log, log,
)?; )?;
self.test_runner_path = Some(bindgen::wasm_bindgen_test_runner_path(log, &self.crate_path) self.test_runner_path = Some(dl.binary("wasm-bindgen-test-runner"));
.expect("if installing wasm-bindgen succeeded, then we should have wasm-bindgen-test-runner too"));
info!(&log, "Getting wasm-bindgen-cli was successful."); info!(&log, "Getting wasm-bindgen-cli was successful.");
Ok(()) 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); assert!(self.node);
info!(log, "Running tests in node..."); info!(log, "Running tests in node...");
PBAR.step(step, "Running tests in node..."); PBAR.step(step, "Running tests in node...");
@ -335,19 +316,18 @@ impl Test {
Ok(()) 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..."); PBAR.step(step, "Getting chromedriver...");
assert!(self.chrome && self.chromedriver.is_none()); assert!(self.chrome && self.chromedriver.is_none());
self.chromedriver = Some(webdriver::get_or_install_chromedriver( self.chromedriver = Some(webdriver::get_or_install_chromedriver(
log, &self.cache,
&self.crate_path,
self.mode, self.mode,
)?); )?);
Ok(()) 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..."); PBAR.step(step, "Running tests in Chrome...");
let chromedriver = self.chromedriver.as_ref().unwrap().display().to_string(); let chromedriver = self.chromedriver.as_ref().unwrap().display().to_string();
@ -378,19 +358,18 @@ impl Test {
Ok(()) 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..."); PBAR.step(step, "Getting geckodriver...");
assert!(self.firefox && self.geckodriver.is_none()); assert!(self.firefox && self.geckodriver.is_none());
self.geckodriver = Some(webdriver::get_or_install_geckodriver( self.geckodriver = Some(webdriver::get_or_install_geckodriver(
log, &self.cache,
&self.crate_path,
self.mode, self.mode,
)?); )?);
Ok(()) 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..."); PBAR.step(step, "Running tests in Firefox...");
let geckodriver = self.geckodriver.as_ref().unwrap().display().to_string(); let geckodriver = self.geckodriver.as_ref().unwrap().display().to_string();
@ -421,15 +400,15 @@ impl Test {
Ok(()) 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..."); PBAR.step(step, "Getting safaridriver...");
assert!(self.safari && self.safaridriver.is_none()); assert!(self.safari && self.safaridriver.is_none());
self.safaridriver = Some(webdriver::get_safaridriver(log, &self.crate_path)?); self.safaridriver = Some(webdriver::get_safaridriver()?);
Ok(()) 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..."); PBAR.step(step, "Running tests in Safari...");
let safaridriver = self.safaridriver.as_ref().unwrap().display().to_string(); let safaridriver = self.safaridriver.as_ref().unwrap().display().to_string();

@ -4,19 +4,13 @@ use emoji;
use failure; use failure;
use progressbar::Step; use progressbar::Step;
use std::fs; use std::fs;
use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use PBAR; use PBAR;
/// If an explicit path is given, then use it, otherwise assume the current /// If an explicit path is given, then use it, otherwise assume the current
/// directory is the crate path. /// directory is the crate path.
pub fn set_crate_path(path: Option<PathBuf>) -> io::Result<PathBuf> { pub fn set_crate_path(path: Option<PathBuf>) -> Result<PathBuf, failure::Error> {
let crate_path = match path { Ok(path.unwrap_or(PathBuf::from(".")))
Some(p) => p,
None => PathBuf::from("."),
};
crate_path.canonicalize()
} }
/// Construct our `pkg` directory in the crate. /// Construct our `pkg` directory in the crate.

@ -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<str>, stderr: Cow<str>, 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<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error::Io(e)
}
}
impl From<curl::Error> for Error {
fn from(e: curl::Error) -> Self {
Error::Curl(e)
}
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::SerdeJson(e)
}
}
impl From<zip::result::ZipError> for Error {
fn from(e: zip::result::ZipError) -> Self {
Error::Zip(e)
}
}
impl From<toml::de::Error> for Error {
fn from(e: toml::de::Error) -> Self {
Error::SerdeToml(e)
}
}

@ -5,20 +5,25 @@
extern crate cargo_metadata; extern crate cargo_metadata;
extern crate console; extern crate console;
extern crate curl; extern crate curl;
extern crate dirs;
#[macro_use] #[macro_use]
extern crate failure; extern crate failure;
extern crate flate2; extern crate flate2;
extern crate hex;
extern crate indicatif; extern crate indicatif;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
extern crate parking_lot; extern crate parking_lot;
extern crate serde;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate serde_json; extern crate serde_json;
extern crate siphasher;
#[macro_use] #[macro_use]
extern crate structopt; extern crate structopt;
#[macro_use] #[macro_use]
extern crate slog; extern crate slog;
extern crate chrono;
extern crate slog_async; extern crate slog_async;
extern crate slog_term; extern crate slog_term;
extern crate tar; extern crate tar;
@ -32,7 +37,6 @@ pub mod build;
pub mod child; pub mod child;
pub mod command; pub mod command;
pub mod emoji; pub mod emoji;
pub mod error;
pub mod lockfile; pub mod lockfile;
pub mod logger; pub mod logger;
pub mod manifest; pub mod manifest;

@ -1,11 +1,11 @@
//! Reading Cargo.lock lock file. //! Reading Cargo.lock lock file.
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use cargo_metadata;
use console::style; use console::style;
use error::Error; use failure::{Error, ResultExt};
use manifest::CrateData;
use toml; use toml;
/// This struct represents the contents of `Cargo.lock`. /// This struct represents the contents of `Cargo.lock`.
@ -23,10 +23,13 @@ struct Package {
impl Lockfile { impl Lockfile {
/// Read the `Cargo.lock` file for the crate at the given path. /// Read the `Cargo.lock` file for the crate at the given path.
pub fn new(crate_path: &Path) -> Result<Lockfile, failure::Error> { pub fn new(crate_data: &CrateData) -> Result<Lockfile, Error> {
let lock_path = get_lockfile_path(crate_path)?; let lock_path = get_lockfile_path(crate_data)?;
let lockfile = fs::read_to_string(lock_path)?; let lockfile = fs::read_to_string(&lock_path)
toml::from_str(&lockfile).map_err(|err| Error::from(err).into()) .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`. /// 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 /// Like `wasm_bindgen_version`, except it returns an error instead of
/// `None`. /// `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(|| { 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\ "Ensure that you have \"{}\" as a dependency in your Cargo.toml file:\n\
[dependencies]\n\ [dependencies]\n\
wasm-bindgen = \"0.2\"", wasm-bindgen = \"0.2\"",
style("wasm-bindgen").bold().dim(), 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` /// 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. /// containing the location of the lock file, by finding the workspace root.
fn get_lockfile_path(crate_path: &Path) -> Result<PathBuf, failure::Error> { fn get_lockfile_path(crate_data: &CrateData) -> Result<PathBuf, Error> {
// 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;
// Check that a lock file can be found in the directory. Return an error // Check that a lock file can be found in the directory. Return an error
// if it cannot, otherwise return the path buffer. // 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() { if !lockfile_path.is_file() {
Err(Error::CrateConfig { bail!("Could not find lockfile at {:?}", lockfile_path)
message: format!("Could not find lockfile at {:?}", lockfile_path),
}
.into())
} else { } else {
Ok(lockfile_path) Ok(lockfile_path)
} }

@ -16,7 +16,7 @@ mod installer;
fn main() { fn main() {
setup_panic!(); setup_panic!();
if let Err(e) = run() { if let Err(e) = run() {
eprintln!("{}", e); eprintln!("Error: {}", e);
for cause in e.iter_causes() { for cause in e.iter_causes() {
eprintln!("Caused by: {}", cause); eprintln!("Caused by: {}", cause);
} }

@ -2,24 +2,34 @@
mod npm; mod npm;
use std::collections::HashMap; use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path; use std::path::Path;
use self::npm::{ use self::npm::{
repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage, repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage,
}; };
use cargo_metadata::Metadata;
use chrono::offset;
use chrono::DateTime;
use command::build::BuildProfile;
use curl::easy; use curl::easy;
use emoji; use emoji;
use error::Error; use failure::{Error, ResultExt};
use failure;
use progressbar::Step; use progressbar::Step;
use serde::{self, Deserialize};
use serde_json; use serde_json;
use std::io::Write;
use toml; use toml;
use which;
use PBAR; use PBAR;
/// Store for metadata learned about a crate
pub struct CrateData {
data: Metadata,
current_idx: usize,
manifest: CargoManifest,
}
struct Collector(Vec<u8>); struct Collector(Vec<u8>);
impl easy::Handler for Collector { impl easy::Handler for Collector {
@ -29,66 +39,86 @@ impl easy::Handler for Collector {
} }
} }
#[derive(Debug, Deserialize)] #[derive(Deserialize)]
struct CargoManifest { struct CargoManifest {
package: CargoPackage, package: CargoPackage,
dependencies: Option<HashMap<String, CargoDependency>>,
#[serde(rename = "dev-dependencies")]
dev_dependencies: Option<HashMap<String, CargoDependency>>,
lib: Option<CargoLib>,
} }
#[derive(Debug, Deserialize)] #[derive(Deserialize)]
struct CargoPackage { struct CargoPackage {
name: String, name: String,
authors: Vec<String>,
description: Option<String>, description: Option<String>,
version: String,
license: Option<String>, license: Option<String>,
repository: Option<String>, repository: Option<String>,
#[serde(default)]
metadata: CargoMetadata,
} }
impl CargoPackage { #[derive(Default, Deserialize)]
fn check_optional_fields(&self) { struct CargoMetadata {
let mut messages = vec![]; #[serde(default, rename = "wasm-pack")]
if self.description.is_none() { wasm_pack: CargoWasmPack,
messages.push("description"); }
}
if self.repository.is_none() {
messages.push("repository");
}
if self.license.is_none() {
messages.push("license");
}
match messages.len() { #[derive(Default, Deserialize)]
1 => PBAR.info(&format!("Optional field missing from Cargo.toml: '{}'. This is not necessary, but recommended", messages[0])), struct CargoWasmPack {
2 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}'. These are not necessary, but recommended", messages[0], messages[1])), #[serde(default)]
3 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}', and '{}'. These are not necessary, but recommended", messages[0], messages[1], messages[2])), profile: CargoWasmPackProfiles,
_ => ()
};
}
} }
#[derive(Debug, Deserialize)] #[derive(Deserialize)]
#[serde(untagged)] struct CargoWasmPackProfiles {
enum CargoDependency { #[serde(
Simple(String), default = "CargoWasmPackProfile::default_dev",
Detailed(DetailedCargoDependency), 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)] impl Default for CargoWasmPackProfiles {
struct DetailedCargoDependency { fn default() -> CargoWasmPackProfiles {
version: Option<String>, CargoWasmPackProfiles {
dev: CargoWasmPackProfile::default_dev(),
release: CargoWasmPackProfile::default_release(),
profiling: CargoWasmPackProfile::default_profiling(),
}
}
} }
#[derive(Debug, Deserialize)] /// This is where configuration goes for wasm-bindgen, wasm-opt, wasm-snip, or
struct CargoLib { /// anything else that wasm-pack runs.
#[serde(rename = "crate-type")] #[derive(Default, Deserialize)]
crate_type: Option<Vec<String>>, 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<bool>,
#[serde(default, rename = "demangle-name-section")]
demangle_name_section: Option<bool>,
#[serde(default, rename = "dwarf-debug-info")]
dwarf_debug_info: Option<bool>,
}
/// Struct for crate which is received from crates.io
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Crate { pub struct Crate {
#[serde(rename = "crate")] #[serde(rename = "crate")]
@ -101,209 +131,464 @@ struct CrateInformation {
} }
impl Crate { impl Crate {
/// Call to the crates.io api and return the latest version of `wasm-pack` /// Returns latest wasm-pack version
pub fn return_wasm_pack_latest_version() -> String { pub fn return_wasm_pack_latest_version() -> Option<String> {
let crt = Crate::check_wasm_pack_latest_version(); let current_time = chrono::offset::Local::now();
crt.crt.max_version 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 { fn return_api_call_result(current_time: DateTime<offset::Local>) -> Option<String> {
let mut easy = easy::Easy2::new(Collector(Vec::new())); match Crate::call_for_wasm_pack_version() {
easy.get(true).unwrap(); Some(version) => {
easy.url("https://crates.io/api/v1/crates/wasm-pack") Crate::override_stamp_file(current_time, &version);
return Some(version);
}
None => return None,
}
}
fn override_stamp_file(current_time: DateTime<offset::Local>, 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<String> {
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<String> {
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<offset::FixedOffset>, String) {
let created = file
.lines()
.find(|line| line.starts_with("created"))
.unwrap()
.split_whitespace()
.nth(1)
.unwrap(); .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<Crate, Error> {
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 contents = easy.get_ref();
let result = String::from_utf8_lossy(&contents.0); 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<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut profile = <Option<Self>>::deserialize(deserializer)?.unwrap_or_default();
profile.update_with_defaults(Self::default_dev());
Ok(profile)
}
fn deserialize_release<'de, D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut profile = <Option<Self>>::deserialize(deserializer)?.unwrap_or_default();
profile.update_with_defaults(Self::default_release());
Ok(profile)
}
fn deserialize_profiling<'de, D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut profile = <Option<Self>>::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<CargoManifest, failure::Error> { struct NpmData {
let manifest_path = path.join("Cargo.toml"); name: String,
if !manifest_path.is_file() { files: Vec<String>,
return Err(Error::crate_config(&format!( dts_file: Option<String>,
"Crate directory is missing a `Cargo.toml` file; is `{}` the wrong directory?", main: String,
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)
} }
impl CargoManifest { impl CrateData {
fn into_commonjs(mut self, scope: &Option<String>, disable_dts: bool) -> NpmPackage { /// Reads all metadata for the crate whose manifest is inside the directory
let filename = self.package.name.replace("-", "_"); /// specified by `path`.
let wasm_file = format!("{}_bg.wasm", filename); pub fn new(crate_path: &Path) -> Result<CrateData, Error> {
let js_file = format!("{}.js", filename); let manifest_path = crate_path.join("Cargo.toml");
let mut files = vec![wasm_file]; 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::<Vec<_>>();
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); /// Check that the crate the given path is properly configured.
files.push(js_bg_file.to_string()); 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 { fn check_crate_type(&self) -> Result<(), Error> {
self.package.name = format!("@{}/{}", s, self.package.name); 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 { /// Get the crate name for the crate at the given path.
let file = format!("{}.d.ts", filename); pub fn crate_name(&self) -> String {
files.push(file.to_string()); let pkg = &self.data.packages[self.current_idx];
Some(file) 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<String>,
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 { } else {
None self.to_esmodules(scope, disable_dts)
}; };
&self.package.check_optional_fields(); let npm_json = serde_json::to_string_pretty(&npm_data)?;
fs::write(&pkg_file_path, npm_json)
NpmPackage::CommonJSPackage(CommonJSPackage { .with_context(|_| format!("failed to write: {}", pkg_file_path.display()))?;
name: self.package.name, Ok(())
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,
})
} }
fn into_esmodules(mut self, scope: &Option<String>, disable_dts: bool) -> NpmPackage { fn npm_data(
let filename = self.package.name.replace("-", "_"); &self,
let wasm_file = format!("{}_bg.wasm", filename); scope: &Option<String>,
let js_file = format!("{}.js", filename); include_commonjs_shim: bool,
let mut files = vec![wasm_file, js_file.clone()]; 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 { files.push(js_file.clone());
let file = format!("{}.d.ts", filename); 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()); files.push(file.to_string());
Some(file) Some(file)
} else { } else {
None None
}; };
NpmData {
if let Some(s) = scope { name: npm_name,
self.package.name = format!("@{}/{}", s, self.package.name); dts_file,
files,
main: js_file,
} }
}
&self.package.check_optional_fields(); fn to_commonjs(&self, scope: &Option<String>, disable_dts: bool) -> NpmPackage {
let data = self.npm_data(scope, true, disable_dts);
let pkg = &self.data.packages[self.current_idx];
NpmPackage::ESModulesPackage(ESModulesPackage { self.check_optional_fields();
name: self.package.name,
collaborators: self.package.authors, NpmPackage::CommonJSPackage(CommonJSPackage {
description: self.package.description, name: data.name,
version: self.package.version, collaborators: pkg.authors.clone(),
license: self.package.license, description: self.manifest.package.description.clone(),
repository: self.package.repository.map(|repo_url| Repository { version: pkg.version.clone(),
ty: "git".to_string(), license: self.manifest.package.license.clone(),
url: repo_url, repository: self
}), .manifest
files: files, .package
module: js_file, .repository
types: dts_file, .clone()
side_effects: "false".to_string(), .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<String>, disable_dts: bool) -> NpmPackage { fn to_esmodules(&self, scope: &Option<String>, disable_dts: bool) -> NpmPackage {
let filename = self.package.name.replace("-", "_"); let data = self.npm_data(scope, false, disable_dts);
let wasm_file = format!("{}_bg.wasm", filename); let pkg = &self.data.packages[self.current_idx];
let js_file = format!("{}.js", filename);
let mut files = vec![wasm_file, js_file.clone()];
let dts_file = if disable_dts == false { self.check_optional_fields();
let file = format!("{}.d.ts", filename);
files.push(file.to_string());
Some(file)
} else {
None
};
if let Some(s) = scope { NpmPackage::ESModulesPackage(ESModulesPackage {
self.package.name = format!("@{}/{}", s, self.package.name); 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<String>, 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 { NpmPackage::NoModulesPackage(NoModulesPackage {
name: self.package.name, name: data.name,
collaborators: self.package.authors, collaborators: pkg.authors.clone(),
description: self.package.description, description: self.manifest.package.description.clone(),
version: self.package.version, version: pkg.version.clone(),
license: self.package.license, license: self.manifest.package.license.clone(),
repository: self.package.repository.map(|repo_url| Repository { repository: self
ty: "git".to_string(), .manifest
url: repo_url, .package
}), .repository
files: files, .clone()
browser: js_file, .map(|repo_url| Repository {
types: dts_file, 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<String>,
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. fn check_optional_fields(&self) {
pub fn get_crate_name(path: &Path) -> Result<String, failure::Error> { let mut messages = vec![];
Ok(read_cargo_toml(path)?.package.name) if self.manifest.package.description.is_none() {
} messages.push("description");
}
/// Check that the crate the given path is properly configured. if self.manifest.package.repository.is_none() {
pub fn check_crate_config(path: &Path, step: &Step) -> Result<(), failure::Error> { messages.push("repository");
let msg = format!("{}Checking crate configuration...", emoji::WRENCH); }
PBAR.step(&step, &msg); if self.manifest.package.license.is_none() {
check_crate_type(path)?; messages.push("license");
Ok(()) }
}
fn check_crate_type(path: &Path) -> Result<(), failure::Error> { match messages.len() {
if read_cargo_toml(path)?.lib.map_or(false, |lib| { 1 => PBAR.info(&format!("Optional field missing from Cargo.toml: '{}'. This is not necessary, but recommended", messages[0])),
lib.crate_type 2 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}'. These are not necessary, but recommended", messages[0], messages[1])),
.map_or(false, |types| types.iter().any(|s| s == "cdylib")) 3 => PBAR.info(&format!("Optional fields missing from Cargo.toml: '{}', '{}', and '{}'. These are not necessary, but recommended", messages[0], messages[1], messages[2])),
}) { _ => ()
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())
} }

@ -22,12 +22,6 @@ where
K: AsRef<OsStr>, K: AsRef<OsStr>,
V: AsRef<OsStr>, V: AsRef<OsStr>,
{ {
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 output = {
let mut cmd = Command::new("cargo"); let mut cmd = Command::new("cargo");
cmd.envs(envs); cmd.envs(envs);

@ -1,40 +1,32 @@
//! Getting WebDriver client binaries. //! Getting WebDriver client binaries.
use binaries::{ use binaries::Cache;
self, bin_path, install_binaries_from_targz_at_url, install_binaries_from_zip_at_url,
};
use command::build::BuildMode; use command::build::BuildMode;
use error::Error;
use failure; use failure;
use slog::Logger; use std::path::PathBuf;
use std::path::{Path, PathBuf};
use target; use target;
/// Get the path to an existing `chromedriver`, or install it if no existing /// Get the path to an existing `chromedriver`, or install it if no existing
/// binary is found. /// binary is found.
pub fn get_or_install_chromedriver( pub fn get_or_install_chromedriver(
log: &Logger, cache: &Cache,
crate_path: &Path,
mode: BuildMode, mode: BuildMode,
) -> Result<PathBuf, failure::Error> { ) -> Result<PathBuf, failure::Error> {
match (mode, bin_path(log, crate_path, "chromedriver")) { if let Ok(path) = which::which("chromedriver") {
(_, Some(path)) => Ok(path), return 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()),
} }
let installation_allowed = match mode {
BuildMode::Noinstall => false,
_ => true,
};
install_chromedriver(cache, installation_allowed)
} }
fn get_local_chromedriver_path(crate_path: &Path) -> PathBuf { /// Download and install a pre-built `chromedriver` binary.
binaries::local_bin_path(crate_path, "chromedriver") pub fn install_chromedriver(
} cache: &Cache,
installation_allowed: bool,
fn get_chromedriver_url() -> Result<String, Error> { ) -> Result<PathBuf, failure::Error> {
let target = if target::LINUX && target::x86_64 { let target = if target::LINUX && target::x86_64 {
"linux64" "linux64"
} else if target::MACOS && target::x86_64 { } else if target::MACOS && target::x86_64 {
@ -42,46 +34,49 @@ fn get_chromedriver_url() -> Result<String, Error> {
} else if target::WINDOWS && target::x86 { } else if target::WINDOWS && target::x86 {
"win32" "win32"
} else { } else {
return Err(Error::unsupported( bail!("geckodriver binaries are unavailable for this target")
"geckodriver binaries are unavailable for this target",
));
}; };
Ok(format!( let url = format!(
"https://chromedriver.storage.googleapis.com/2.41/chromedriver_{}.zip", "https://chromedriver.storage.googleapis.com/2.41/chromedriver_{}.zip",
target target
)) );
} match cache.download(
installation_allowed,
/// Download and install a pre-built `chromedriver` binary. "chromedriver",
pub fn install_chromedriver(crate_path: &Path) -> Result<PathBuf, failure::Error> { &["chromedriver"],
let url = get_chromedriver_url()?; &url,
install_binaries_from_zip_at_url(crate_path, &url, Some("chromedriver"))?; )? {
let chromedriver = get_local_chromedriver_path(crate_path); Some(dl) => Ok(dl.binary("chromedriver")),
assert!(chromedriver.is_file()); None => bail!(
Ok(chromedriver) "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 /// Get the path to an existing `geckodriver`, or install it if no existing
/// binary is found. /// binary is found.
pub fn get_or_install_geckodriver( pub fn get_or_install_geckodriver(
log: &Logger, cache: &Cache,
crate_path: &Path,
mode: BuildMode, mode: BuildMode,
) -> Result<PathBuf, failure::Error> { ) -> Result<PathBuf, failure::Error> {
match (mode, bin_path(log, crate_path, "geckodriver")) { if let Ok(path) = which::which("geckodriver") {
(_, Some(path)) => Ok(path), return 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()),
} }
let installation_allowed = match mode {
BuildMode::Noinstall => false,
_ => true,
};
install_geckodriver(cache, installation_allowed)
} }
fn get_geckodriver_url() -> Result<String, Error> { /// Download and install a pre-built `geckodriver` binary.
pub fn install_geckodriver(
cache: &Cache,
installation_allowed: bool,
) -> Result<PathBuf, failure::Error> {
let (target, ext) = if target::LINUX && target::x86 { let (target, ext) = if target::LINUX && target::x86 {
("linux32", "tar.gz") ("linux32", "tar.gz")
} else if target::LINUX && target::x86_64 { } else if target::LINUX && target::x86_64 {
@ -93,36 +88,21 @@ fn get_geckodriver_url() -> Result<String, Error> {
} else if target::WINDOWS && target::x86_64 { } else if target::WINDOWS && target::x86_64 {
("win64", "zip") ("win64", "zip")
} else { } else {
return Err(Error::unsupported( bail!("geckodriver binaries are unavailable for this target")
"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-{}.{}", "https://github.com/mozilla/geckodriver/releases/download/v0.21.0/geckodriver-v0.21.0-{}.{}",
target, target,
ext, ext,
)) );
} match cache.download(installation_allowed, "geckodriver", &["geckodriver"], &url)? {
Some(dl) => Ok(dl.binary("geckodriver")),
fn get_local_geckodriver_path(crate_path: &Path) -> PathBuf { None => bail!(
binaries::local_bin_path(crate_path, "geckodriver") "No cached `geckodriver` binary found, and could not find a global `geckodriver` \
} on the `$PATH`. Not installing `geckodriver` because of noinstall mode."
),
/// Download and install a pre-built `geckodriver` binary.
pub fn install_geckodriver(crate_path: &Path) -> Result<PathBuf, failure::Error> {
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"))?;
} }
let geckodriver = get_local_geckodriver_path(crate_path);
assert!(geckodriver.is_file());
Ok(geckodriver)
} }
/// Get the path to an existing `safaridriver`. /// Get the path to an existing `safaridriver`.
@ -130,12 +110,9 @@ pub fn install_geckodriver(crate_path: &Path) -> Result<PathBuf, failure::Error>
/// We can't install `safaridriver` if an existing one is not found because /// We can't install `safaridriver` if an existing one is not found because
/// Apple does not provide pre-built binaries. However, `safaridriver` *should* /// Apple does not provide pre-built binaries. However, `safaridriver` *should*
/// be present by default. /// be present by default.
pub fn get_safaridriver(log: &Logger, crate_path: &Path) -> Result<PathBuf, Error> { pub fn get_safaridriver() -> Result<PathBuf, failure::Error> {
if let Some(p) = bin_path(log, crate_path, "safaridriver") { match which::which("safaridriver") {
Ok(p) Ok(p) => Ok(p),
} else { Err(_) => bail!("could not find `safaridriver` on the `$PATH`"),
Err(Error::crate_config(
"could not find `safaridriver` on the `$PATH`",
))
} }
} }

@ -1,4 +1,5 @@
use tempfile; use tempfile;
use wasm_pack::binaries::Cache;
use wasm_pack::bindgen; use wasm_pack::bindgen;
#[test] #[test]
@ -8,23 +9,11 @@ use wasm_pack::bindgen;
all(windows, target_arch = "x86_64"), all(windows, target_arch = "x86_64"),
))] ))]
fn can_download_prebuilt_wasm_bindgen() { fn can_download_prebuilt_wasm_bindgen() {
use std::env;
let dir = tempfile::TempDir::new().unwrap(); let dir = tempfile::TempDir::new().unwrap();
bindgen::download_prebuilt_wasm_bindgen(dir.path(), "0.2.21").unwrap(); let cache = Cache::at(dir.path());
assert!( let dl = bindgen::download_prebuilt_wasm_bindgen(&cache, "0.2.21", true).unwrap();
dir.path() assert!(dl.binary("wasm-bindgen").is_file());
.join("bin") assert!(dl.binary("wasm-bindgen-test-runner").is_file())
.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()
);
} }
#[test] #[test]
@ -36,9 +25,13 @@ fn can_download_prebuilt_wasm_bindgen() {
fn downloading_prebuilt_wasm_bindgen_handles_http_errors() { fn downloading_prebuilt_wasm_bindgen_handles_http_errors() {
let dir = tempfile::TempDir::new().unwrap(); let dir = tempfile::TempDir::new().unwrap();
let bad_version = "0.2.21-some-trailing-version-stuff-that-does-not-exist"; 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()); assert!(result.is_err());
let error_msg = result.unwrap_err().to_string(); let error = result.err().unwrap();
assert!(error_msg.contains("404"));
assert!(error_msg.contains(bad_version)); assert!(error.iter_chain().any(|e| e.to_string().contains("404")));
assert!(error
.iter_chain()
.any(|e| e.to_string().contains(bad_version)));
} }

@ -1,6 +1,8 @@
use std::fs;
use std::path::Path;
use structopt::StructOpt; use structopt::StructOpt;
use utils; use utils;
use wasm_pack::{command, logger, Cli}; use wasm_pack::Cli;
#[test] #[test]
fn build_in_non_crate_directory_doesnt_panic() { 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(), &fixture.path.display().to_string(),
]) ])
.unwrap(); .unwrap();
let logger = logger::new(&cli.cmd, cli.verbosity).unwrap(); let result = fixture.run(cli.cmd);
let result = command::run_wasm_pack(cli.cmd, &logger);
assert!( assert!(
result.is_err(), result.is_err(),
"running wasm-pack in a non-crate directory should fail, but it should not panic" "running wasm-pack in a non-crate directory should fail, but it should not panic"
); );
let err_msg = result.unwrap_err().to_string(); let err = result.unwrap_err();
assert!(err_msg.contains("missing a `Cargo.toml`")); 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"
);
}
} }

@ -1,11 +1,13 @@
use utils::fixture; use utils::fixture;
use wasm_pack::lockfile::Lockfile; use wasm_pack::lockfile::Lockfile;
use wasm_pack::manifest::CrateData;
#[test] #[test]
fn it_gets_wasm_bindgen_version() { fn it_gets_wasm_bindgen_version() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
fixture.cargo_check(); 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"),); 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() { fn it_gets_wasm_bindgen_test_version() {
let fixture = fixture::wbg_test_node(); let fixture = fixture::wbg_test_node();
fixture.cargo_check(); 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"),); 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(); 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"),); 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(); 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"),); assert_eq!(lock.wasm_bindgen_version(), Some("0.2.21"),);
} }

@ -1,5 +1,7 @@
extern crate failure; extern crate failure;
#[macro_use] #[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate serde_json; extern crate serde_json;
#[macro_use] #[macro_use]

@ -2,24 +2,24 @@ use std::collections::HashSet;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use structopt::StructOpt;
use utils::{self, fixture}; use utils::{self, fixture};
use wasm_pack::{self, manifest}; use wasm_pack::{self, manifest, Cli};
#[test] #[test]
fn it_gets_the_crate_name_default_path() { fn it_gets_the_crate_name_default_path() {
let path = &PathBuf::from("."); let path = &PathBuf::from(".");
assert!(manifest::get_crate_name(path).is_ok()); let crate_data = manifest::CrateData::new(&path).unwrap();
assert_eq!(manifest::get_crate_name(path).unwrap(), "wasm-pack"); let name = crate_data.crate_name();
assert_eq!(name, "wasm_pack");
} }
#[test] #[test]
fn it_gets_the_crate_name_provided_path() { fn it_gets_the_crate_name_provided_path() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
assert!(manifest::get_crate_name(&fixture.path).is_ok()); let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
assert_eq!( assert_eq!(crate_data.crate_name(), "js_hello_world");
manifest::get_crate_name(&fixture.path).unwrap(),
"js-hello-world"
);
} }
#[test] #[test]
@ -27,8 +27,9 @@ fn it_checks_has_cdylib_default_path() {
let fixture = fixture::no_cdylib(); let fixture = fixture::no_cdylib();
// Ensure that there is a `Cargo.lock`. // Ensure that there is a `Cargo.lock`.
fixture.cargo_check(); fixture.cargo_check();
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); 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] #[test]
@ -36,15 +37,17 @@ fn it_checks_has_cdylib_provided_path() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
// Ensure that there is a `Cargo.lock`. // Ensure that there is a `Cargo.lock`.
fixture.cargo_check(); fixture.cargo_check();
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); 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] #[test]
fn it_checks_has_cdylib_wrong_crate_type() { fn it_checks_has_cdylib_wrong_crate_type() {
let fixture = fixture::bad_cargo_toml(); let fixture = fixture::bad_cargo_toml();
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); 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] #[test]
@ -52,20 +55,24 @@ fn it_recognizes_a_map_during_depcheck() {
let fixture = fixture::serde_feature(); let fixture = fixture::serde_feature();
// Ensure that there is a `Cargo.lock`. // Ensure that there is a `Cargo.lock`.
fixture.cargo_check(); fixture.cargo_check();
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); 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] #[test]
fn it_creates_a_package_json_default_path() { fn it_creates_a_package_json_default_path() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg"); let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); 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"); 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();
assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
let pkg = 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.name, "js-hello-world");
assert_eq!(pkg.repository.ty, "git"); 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.d.ts",
"js_hello_world.js", "js_hello_world.js",
] ]
.iter() .iter()
.map(|&s| String::from(s)) .map(|&s| String::from(s))
.collect(); .collect();
assert_eq!(actual_files, expected_files); 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() { fn it_creates_a_package_json_provided_path() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg"); let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); 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"); 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(); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
let pkg = 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.name, "js-hello-world");
@ -109,9 +119,9 @@ fn it_creates_a_package_json_provided_path() {
"js_hello_world.d.ts", "js_hello_world.d.ts",
"js_hello_world.js", "js_hello_world.js",
] ]
.iter() .iter()
.map(|&s| String::from(s)) .map(|&s| String::from(s))
.collect(); .collect();
assert_eq!(actual_files, expected_files); 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() { fn it_creates_a_package_json_provided_path_with_scope() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg"); let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!( assert!(crate_data
manifest::write_package_json( .write_package_json(&out_dir, &Some("test".to_string()), false, "", &step)
&fixture.path, .is_ok());
&out_dir,
&Some("test".to_string()),
false,
"",
&step
)
.is_ok()
);
let package_json_path = &fixture.path.join("pkg").join("package.json"); 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();
assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
let pkg = 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.name, "@test/js-hello-world");
assert_eq!(pkg.module, "js_hello_world.js"); 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.d.ts",
"js_hello_world.js", "js_hello_world.js",
] ]
.iter() .iter()
.map(|&s| String::from(s)) .map(|&s| String::from(s))
.collect(); .collect();
assert_eq!(actual_files, expected_files); 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() { fn it_creates_a_pkg_json_with_correct_files_on_node() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg"); let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!( assert!(crate_data
manifest::write_package_json(&fixture.path, &out_dir, &None, false, "nodejs", &step) .write_package_json(&out_dir, &None, false, "nodejs", &step)
.is_ok() .is_ok());
);
let package_json_path = &out_dir.join("package.json"); 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(); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
let pkg = 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.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.wasm",
"js_hello_world_bg.js", "js_hello_world_bg.js",
"js_hello_world.d.ts", "js_hello_world.d.ts",
"js_hello_world.js",
] ]
.iter() .iter()
.map(|&s| String::from(s)) .map(|&s| String::from(s))
.collect(); .collect();
assert_eq!(actual_files, expected_files); 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() { fn it_creates_a_pkg_json_with_correct_files_on_nomodules() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg"); let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!( assert!(crate_data
manifest::write_package_json(&fixture.path, &out_dir, &None, false, "no-modules", &step) .write_package_json(&out_dir, &None, false, "no-modules", &step)
.is_ok() .is_ok());
);
let package_json_path = &out_dir.join("package.json"); 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(); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
let pkg = 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.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.js",
"js_hello_world.d.ts", "js_hello_world.d.ts",
] ]
.iter() .iter()
.map(|&s| String::from(s)) .map(|&s| String::from(s))
.collect(); .collect();
assert_eq!(actual_files, expected_files); 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() { fn it_creates_a_pkg_json_in_out_dir() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("./custom/out"); 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); 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"); let package_json_path = &fixture.path.join(&out_dir).join("package.json");
assert!(fs::metadata(package_json_path).is_ok()); fs::metadata(package_json_path).unwrap();
assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
} }
#[test] #[test]
fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() { fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg"); let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); 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"); let package_json_path = &out_dir.join("package.json");
assert!(fs::metadata(package_json_path).is_ok()); fs::metadata(package_json_path).unwrap();
assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok()); utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
let pkg = 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.name, "js-hello-world");
assert_eq!(pkg.repository.ty, "git"); assert_eq!(pkg.repository.ty, "git");
@ -264,8 +274,9 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
#[test] #[test]
fn it_errors_when_wasm_bindgen_is_not_declared() { fn it_errors_when_wasm_bindgen_is_not_declared() {
let fixture = fixture::bad_cargo_toml(); let fixture = fixture::bad_cargo_toml();
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); 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] #[test]
@ -273,6 +284,52 @@ fn it_does_not_error_when_wasm_bindgen_is_declared() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
// Ensure that there is a `Cargo.lock`. // Ensure that there is a `Cargo.lock`.
fixture.cargo_check(); fixture.cargo_check();
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(1); 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")));
} }

@ -32,7 +32,7 @@ fn it_copies_a_readme_default_path() {
} }
#[test] #[test]
fn it_creates_a_package_json_provided_path() { fn it_copies_a_readme_provided_path() {
let fixture = fixture::js_hello_world(); let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg"); let out_dir = fixture.path.join("pkg");
fs::create_dir(&out_dir).expect("should create pkg directory OK"); fs::create_dir(&out_dir).expect("should create pkg directory OK");

@ -1,10 +1,16 @@
use failure::Error;
use std::env; use std::env;
use std::fs;
use tempfile;
use utils::fixture; use utils::fixture;
use wasm_pack::binaries; use wasm_pack::command::{build, test, Command};
use wasm_pack::command::{self, build, test, Command};
use wasm_pack::logger; fn assert_err<T>(result: Result<T, Error>, 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] #[test]
fn it_can_run_node_tests() { fn it_can_run_node_tests() {
@ -16,8 +22,7 @@ fn it_can_run_node_tests() {
mode: build::BuildMode::Noinstall, mode: build::BuildMode::Noinstall,
..Default::default() ..Default::default()
}); });
let logger = logger::new(&cmd, 3).unwrap(); fixture.run(cmd).unwrap();
command::run_wasm_pack(cmd, &logger).expect("should run test command OK");
} }
#[test] #[test]
@ -30,8 +35,7 @@ fn it_can_run_tests_with_different_wbg_test_and_wbg_versions() {
mode: build::BuildMode::Noinstall, mode: build::BuildMode::Noinstall,
..Default::default() ..Default::default()
}); });
let logger = logger::new(&cmd, 3).unwrap(); fixture.run(cmd).unwrap();
command::run_wasm_pack(cmd, &logger).expect("should run test command OK");
} }
#[test] #[test]
@ -81,8 +85,7 @@ fn it_can_run_browser_tests() {
..Default::default() ..Default::default()
}); });
let logger = logger::new(&cmd, 3).unwrap(); fixture.run(cmd).unwrap();
command::run_wasm_pack(cmd, &logger).expect("should run test command OK");
} }
#[test] #[test]
@ -95,10 +98,9 @@ fn it_can_run_failing_tests() {
mode: build::BuildMode::Noinstall, mode: build::BuildMode::Noinstall,
..Default::default() ..Default::default()
}); });
let logger = logger::new(&cmd, 3).unwrap(); assert_err(
assert!( fixture.run(cmd),
command::run_wasm_pack(cmd, &logger).is_err(), "Running Wasm tests with wasm-bindgen-test failed",
"failing tests should return Err"
); );
} }
@ -111,34 +113,37 @@ fn it_can_run_failing_tests() {
all(target_os = "windows", target_arch = "x86_64") all(target_os = "windows", target_arch = "x86_64")
))] ))]
fn it_can_find_a_webdriver_on_path() { fn it_can_find_a_webdriver_on_path() {
use std::process::Command;
let fixture = fixture::wbg_test_browser(); let fixture = fixture::wbg_test_browser();
fixture.install_local_wasm_bindgen(); let local_geckodriver = fixture.install_local_geckodriver();
fixture.install_local_geckodriver(); let local_wasm_bindgen = fixture.install_local_wasm_bindgen();
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 mut paths: Vec<_> = env::split_paths(&env::var("PATH").unwrap()).collect(); let mut paths: Vec<_> = env::split_paths(&env::var("PATH").unwrap()).collect();
paths.insert(0, geckodriver_dir.path().into()); paths.insert(0, local_geckodriver.parent().unwrap().to_path_buf());
env::set_var("PATH", env::join_paths(paths).unwrap()); paths.insert(0, local_wasm_bindgen.parent().unwrap().to_path_buf());
let path = env::join_paths(paths).unwrap();
let cmd = Command::Test(test::TestOptions { let _lock = fixture.lock();
path: Some(fixture.path.clone()),
firefox: true, let mut me = env::current_exe().unwrap();
headless: true, me.pop();
mode: build::BuildMode::Noinstall, me.pop();
..Default::default() me.push("wasm-pack");
}); let output = Command::new(&me)
let logger = logger::new(&cmd, 3).unwrap(); .arg("test")
command::run_wasm_pack(cmd, &logger).expect("should run test command OK"); .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] #[test]
@ -152,11 +157,7 @@ fn it_requires_node_or_a_browser() {
// Note: not setting node or any browser to true here. // Note: not setting node or any browser to true here.
..Default::default() ..Default::default()
}); });
let logger = logger::new(&cmd, 3).unwrap(); assert_err(fixture.run(cmd), "Must specify at least one of");
assert!(
command::run_wasm_pack(cmd, &logger).is_err(),
"need to enable node or browser testing"
);
} }
#[test] #[test]
@ -171,11 +172,7 @@ fn the_headless_flag_requires_a_browser() {
headless: true, headless: true,
..Default::default() ..Default::default()
}); });
let logger = logger::new(&cmd, 3).unwrap(); assert_err(fixture.run(cmd), "only applies to browser tests");
assert!(
command::run_wasm_pack(cmd, &logger).is_err(),
"running headless tests in node doesn't make sense"
);
} }
#[test] #[test]
@ -213,13 +210,7 @@ fn complains_about_missing_wasm_bindgen_test_dependency() {
mode: build::BuildMode::Noinstall, mode: build::BuildMode::Noinstall,
..Default::default() ..Default::default()
}); });
let logger = logger::new(&cmd, 3).unwrap(); let error = assert_err(fixture.run(cmd), "Ensure that you have");
let result = command::run_wasm_pack(cmd, &logger);
assert!(
result.is_err(),
"running tests without wasm-bindgen-test won't work"
);
// Test that the error message has two occurrences of "wasm-bindgen-test" in // 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 // 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 // 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. // 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"); let first = err_msg.find("wasm-bindgen-test");
assert!(first.is_some()); assert!(first.is_some());
let second = err_msg.rfind("wasm-bindgen-test"); let second = err_msg.rfind("wasm-bindgen-test");
assert!(second.is_some()); assert!(second.is_some());
assert_ne!(first, second, "should have found two occurrences"); 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();
}

@ -1,20 +1,14 @@
use super::logger::null_logger; use super::logger::null_logger;
use std::env; use std::env;
use std::fs; use std::fs;
use std::io;
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::{Once, ONCE_INIT}; use std::sync::{MutexGuard, Once, ONCE_INIT};
use std::thread; use std::thread;
use tempfile::TempDir; use tempfile::TempDir;
use wasm_pack; use wasm_pack;
use wasm_pack::binaries::Cache;
fn hard_link_or_copy<P1: AsRef<Path>, P2: AsRef<Path>>(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(|_| ()))
}
/// A test fixture in a temporary directory. /// A test fixture in a temporary directory.
pub struct Fixture { pub struct Fixture {
@ -134,120 +128,63 @@ impl Fixture {
/// ///
/// Takes care not to re-install for every fixture, but only the one time /// Takes care not to re-install for every fixture, but only the one time
/// for the whole test suite. /// 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; 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"); wasm_pack::bindgen::cargo_install_wasm_bindgen(log, &cache, version, true)
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");
// 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(|| { INSTALL_WASM_BINDGEN.call_once(|| {
if shared_wasm_bindgen.is_file() { download().unwrap();
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().binary("wasm-bindgen")
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 `geckodriver` and return its path. /// Download `geckodriver` and return its path.
/// ///
/// Takes care to ensure that only one `geckodriver` is downloaded for the whole /// Takes care to ensure that only one `geckodriver` is downloaded for the whole
/// test suite. /// test suite.
pub fn install_local_geckodriver(&self) -> &Self { pub fn install_local_geckodriver(&self) -> PathBuf {
static FETCH_GECKODRIVER: Once = ONCE_INIT; static FETCH_GECKODRIVER: Once = ONCE_INIT;
let cache = self.cache();
let tests = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests"); // like above for synchronization
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");
FETCH_GECKODRIVER.call_once(|| { FETCH_GECKODRIVER.call_once(|| {
if geckodriver.is_file() { wasm_pack::test::webdriver::install_geckodriver(&cache, true).unwrap();
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
} }
/// Download `chromedriver` and return its path. /// Download `chromedriver` and return its path.
/// ///
/// Takes care to ensure that only one `chromedriver` is downloaded for the whole /// Takes care to ensure that only one `chromedriver` is downloaded for the whole
/// test suite. /// test suite.
pub fn install_local_chromedriver(&self) -> &Self { pub fn install_local_chromedriver(&self) -> PathBuf {
static FETCH_CHROMEDRIVER: Once = ONCE_INIT; static FETCH_CHROMEDRIVER: Once = ONCE_INIT;
let cache = self.cache();
let tests = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests"); // like above for synchronization
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");
FETCH_CHROMEDRIVER.call_once(|| { FETCH_CHROMEDRIVER.call_once(|| {
if chromedriver.is_file() { wasm_pack::test::webdriver::install_chromedriver(&cache, true).unwrap();
return;
}
wasm_pack::test::webdriver::install_chromedriver(&tests).unwrap();
assert!(chromedriver.is_file());
}); });
wasm_pack::test::webdriver::install_chromedriver(&cache, true).unwrap()
}
wasm_pack::binaries::ensure_local_bin_dir(&self.path) pub fn cache(&self) -> Cache {
.expect("could not create fixture's `bin` directory"); let target_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("target");
Cache::at(&target_dir.join("test_cache"))
hard_link_or_copy(
&chromedriver,
wasm_pack::binaries::local_bin_path(&self.path, "chromedriver"),
)
.expect("could not copy `chromedriver` to fixture directory");
self
} }
/// The `step_install_wasm_bindgen` and `step_run_wasm_bindgen` steps only /// The `step_install_wasm_bindgen` and `step_run_wasm_bindgen` steps only
@ -266,6 +203,32 @@ impl Fixture {
.unwrap(); .unwrap();
self 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 { impl Drop for Fixture {
@ -314,7 +277,7 @@ pub fn no_cdylib() -> Fixture {
authors = ["The wasm-pack developers"] authors = ["The wasm-pack developers"]
description = "so awesome rust+wasm package" description = "so awesome rust+wasm package"
license = "WTFPL" license = "WTFPL"
name = "{}" name = "foo"
repository = "https://github.com/rustwasm/wasm-pack.git" repository = "https://github.com/rustwasm/wasm-pack.git"
version = "0.1.0" version = "0.1.0"
@ -474,3 +437,156 @@ pub fn wbg_test_node() -> Fixture {
); );
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
}

@ -1,4 +1,5 @@
use utils::fixture; use utils::fixture;
use wasm_pack::binaries::Cache;
use wasm_pack::test::webdriver; use wasm_pack::test::webdriver;
#[test] #[test]
@ -9,7 +10,8 @@ use wasm_pack::test::webdriver;
))] ))]
fn can_install_chromedriver() { fn can_install_chromedriver() {
let fixture = fixture::js_hello_world(); 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] #[test]
@ -22,5 +24,6 @@ fn can_install_chromedriver() {
))] ))]
fn can_install_geckodriver() { fn can_install_geckodriver() {
let fixture = fixture::js_hello_world(); 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());
} }

Loading…
Cancel
Save