diff --git a/.travis.yml b/.travis.yml index b76be3a4..7d8f888b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ matrix: - env: TARGET=armv7-unknown-linux-gnueabihf - env: TARGET=x86_64-unknown-linux-gnu - env: TARGET=x86_64-unknown-linux-musl + - env: TARGET=x86_64-unknown-freebsd # OSX - env: TARGET=x86_64-apple-darwin @@ -72,3 +73,10 @@ before_cache: notifications: email: on_success: never + +branches: + only: + - staging + - trying + - master + - /^v[\d.]+$/ diff --git a/Cargo.lock b/Cargo.lock index 267b9263..fe515459 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,9 +1,22 @@ [[package]] -name = "aho-corasick" -version = "0.6.8" +name = "MacTypes-sys" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "adler32" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -14,35 +27,66 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -50,14 +94,51 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bzip2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bzip2-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" -version = "1.0.25" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -76,12 +157,12 @@ dependencies = [ [[package]] name = "clicolors-control" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -95,61 +176,201 @@ dependencies = [ [[package]] name = "console" -version = "0.6.2" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "clicolors-control 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "core-foundation" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "directories" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dtoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "encode_unicode" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "encoding_rs" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "env_logger" -version = "0.5.13" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "filetime" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "flate2" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -164,14 +385,152 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "h2" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +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 = "http" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "humantime" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.12.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-old-types" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -182,65 +541,228 @@ dependencies = [ ] [[package]] -name = "lazy_static" -version = "0.2.11" +name = "language-tags" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.1.0" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "libc" -version = "0.2.43" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "lock_api" -version = "0.1.4" +name = "libflate" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" -version = "2.1.0" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mime" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", + "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime_guess" +version = "2.0.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz-sys" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide_c_api" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (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.50 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "native-tls" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (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.42 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nix" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl" +version = "0.10.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (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.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl-sys" +version = "0.9.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -248,28 +770,90 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.6.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "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)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pbr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "phf" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_codegen" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_generator" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_shared" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "podio" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" -version = "0.4.20" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -282,40 +866,131 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_core" -version = "0.2.2" +name = "rand" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" -version = "0.1.40" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -323,32 +998,69 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.5" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "reqwest" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -359,12 +1071,31 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "safemem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "same-file" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schannel" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -372,6 +1103,44 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "security-framework" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "self_update" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-old-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "zip 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -387,17 +1156,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.79" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" -version = "1.0.79" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_urlencoded" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 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)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -406,18 +1199,30 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "smallvec" -version = "0.6.5" +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "string" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.7.0" @@ -425,62 +1230,76 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.14.9" +version = "0.15.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (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 = "term_size" -version = "0.3.1" +name = "tar" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "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)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempfile" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -496,8 +1315,8 @@ name = "termion" version = "1.5.1" 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_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -506,7 +1325,7 @@ name = "termios" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -522,43 +1341,214 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-trace-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "topgrade" -version = "0.16.0" +version = "1.9.0" dependencies = [ - "console 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "console 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "self_update 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "shellexpand 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "which 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "try-lock" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ucd-util" -version = "0.1.1" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -572,16 +1562,31 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unreachable" -version = "1.0.0" +name = "url" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "utf8-ranges" -version = "1.0.1" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "uuid" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "vcpkg" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -601,21 +1606,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.5" +version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "want" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "which" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -644,7 +1659,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -661,88 +1676,231 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zip" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.21 (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.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" +"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" +"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"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 build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" +"checksum bzip2-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6584aa36f5ad4c9247f5323b0a42f37802b37a836f0ad87084d7a33961abe25f" +"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "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 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9" "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.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2bf3720d3f3fc30b721ef1ae54e13af3264af4af39dc476a8de56a6ee1e2184b" +"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" +"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" +"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" -"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" +"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd" +"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" +"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" +"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "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 humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" +"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "910a5e7be6283a9c91b3982fa5188368c8719cce2a3cf3b86048673bf9d9c36b" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" +"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5b6658b016965ae301fa995306db965c93677880ea70765a84235a96eae896" +"checksum hyper-old-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6896be51ecf3966c0fa14ff2da3233dbb9aef57ccea1be1afe55f105f4d4c9c4" +"checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" +"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" -"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" -"checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" -"checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" -"checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" -"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" -"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" +"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libflate 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "7346a83e8a2c3958d44d24225d905385dc31fc16e89dffb356c457b278914d20" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" +"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" +"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" +"checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" +"checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" +"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum pbr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "deb73390ab68d81992bd994d145f697451bb0b54fd39738e72eef32458ad6907" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e542d9f077c126af32536b6aacc75bb7325400eab8cd0743543be5d91660780d" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" +"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" +"checksum self_update 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4997d828329f3bea234b5efd084f0ee07b284a556d64023cc0e3e47cc44d74" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" -"checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum shellexpand 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de7a5b5a9142fd278a10e0209b021a1b85849352e6951f4f914735c976737564" -"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" +"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ca85f2c9a5a1e2d5ac686fc0be48e40f8ad803f5bbe31f692ff71eb2dd8aad45" -"checksum structopt-derive 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "1383e5db585da799a5c4acc496c5c868e18bf82e658c00c75cc91038fa26b55f" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b10ee269228fb723234fce98e9aac0eaed2bd5f1ad2f6930e8d5b93f04445a1a" -"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" -"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" +"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1" +"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum tar 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2167ff53da2a661702b3299f71a91b61b1dffef36b4b2884b1f9c67254c0133" +"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"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 time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tokio 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "1021bb1f4150435ab8f222eb7ed37c60b2d57037def63ba43085a79f387512d7" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fda385df506bf7546e70872767f71e81640f1f251bdf2fd8eb81a0eaec5fe022" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" +"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41d17211f887da8e4a70a45b9536f26fc5de166b81e2d5d80de4a17fd22553bd" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" +"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" +"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 version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" -"checksum which 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49c4f580e93079b70ac522e7bdebbe1568c8afa7d8d05ee534ee737ca37d2f51" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" +"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +"checksum zip 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cbbddef6339155bc4fa8e2609040078ff18f3011117b55caa9f0516d544a357" diff --git a/Cargo.toml b/Cargo.toml index f5dee46b..00b8fc96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,32 +1,36 @@ [package] name = "topgrade" description = "Upgrade all the things" -license-file = "LICENCE" +license-file = "LICENSE" repository = "https://github.com/r-darwish/topgrade" -version = "0.16.0" +version = "1.9.0" authors = ["Roey Darwish Dror "] exclude = ["doc/screenshot.gif"] +edition = "2018" [dependencies] directories = "1.0.2" -failure = "0.1.2" -failure_derive = "0.1.2" -serde = "1.0.79" -serde_derive = "1.0.79" -toml = "0.4.8" -which = "2.0.0" +failure = "0.1.5" +failure_derive = "0.1.5" +serde = { version = "1.0.88", features = ["derive"] } +toml = "0.4.10" +which_crate = { version = "2.0.1", package = "which" } shellexpand = "1.0.0" -structopt = "0.2.10" -log = "0.4.5" -env_logger = "0.5.13" -term_size = "0.3.1" -termcolor = "1.0.4" -walkdir = "2.2.5" -console = "0.6.2" +structopt = "0.2.14" +log = "0.4.6" +env_logger = "0.6.0" +walkdir = "2.2.7" +console = "0.7.5" +self_update_crate = { version = "0.5.1", optional = true, package = "self_update" } +lazy_static = "1.2.0" [target.'cfg(unix)'.dependencies] -nix = "0.11" -lazy_static = "1.1.0" +nix = "0.13.0" [profile.release] lto = true + +[features] +default = [] + +self-update = ["self_update_crate"] diff --git a/LICENCE b/LICENSE similarity index 100% rename from LICENCE rename to LICENSE diff --git a/README.md b/README.md index f52c16f6..f6244d96 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,30 @@ Keeping your system up to date mostly involves invoking more than a single packa usually results in big shell one-liners saved in your shell history. Topgrade tries to solve this problem by detecting which tools you use and run their appropriate package managers. +## Supported Platforms +Topgrade should probably work on whichever platform it can be build. The real question is whether +Topgrade knows that platform and can utilize its unique features, such as the operating system's +pacakge manager. Topgrade is tested on and knows the following platforms: + +* Linux + * Arch + * CentOS/RHEL + * Fedora + * Debian/Ubuntu + * Gentoo + * openSUSE + * Void +* FreeBSD +* macOS +* Windows + ## Installation Arch Linux users can use the [AUR](https://aur.archlinux.org/packages/topgrade/) package. macOS users can install topgrade via Homebrew. Other systems users can either use `cargo install` or use the compiled binaries from the release -page. +page. The compiled binaries contain a self-upgrading feature. Topgrade isn't guaranteed to work on Rust versions older than the latest stable release. If you intend to install Topgrade using Cargo then you should either install Rust using rustup or use a @@ -27,15 +44,24 @@ distribution which ships the latest version of Rust, such as Arch Linux. ## Usage Just run `topgrade`. It will run the following steps: -* *Linux*: Run the system package manager: - * *Arch*: Run [yay](https://github.com/Jguer/yay) or fall back to pacman - * *CentOS/RHEL*: Run `yum upgrade` - * *Fedora* - Run `dnf upgrade` - * *Debian/Ubuntu*: Run `apt update && apt dist-upgrade` -* *Linux*: Run [etc-update](https://dev.gentoo.org/~zmedico/portage/doc/man/etc-update.1.html): -* *Unix*: Run `brew update && brew upgrade`. This should handle both Homebrew and Linuxbrew -* *Windows*: Upgrade Powershell modules -* *Windows*: Upgrade all [Chocolatey](https://chocolatey.org/) packages +* Try to self-upgrade if compiled with this feature. On Unix systems Topgrade will also respawn + itself if it was upgraded +* **Linux**: Run the system package manager: + * **Arch**: Run [yay](https://github.com/Jguer/yay) or fall back to pacman + * **CentOS/RHEL**: Run `yum upgrade` + * **Fedora**: Run `dnf upgrade` + * **Debian/Ubuntu**: Run `apt update && apt dist-upgrade` + * **Gentoo**: Run `layman -s ALL && emerge --sync -q && eix-update && emerge -uDNa world` + * **openSUSE**: Run `zypper refresh && zypper dist-upgrade` + * **Void**: Run `xbps-install -Su` +* **Linux**: Run [etc-update](https://dev.gentoo.org/~zmedico/portage/doc/man/etc-update.1.html): +* **FreeBSD**: Upgrade and audit packages +* **Unix**: Run `brew update && brew upgrade`. This should handle both Homebrew and Linuxbrew +* **Unix**: Run `nix upgrade-nix && nix --upgrade`. +* **Unix**: Run [Pearl](https://github.com/pearl-core/pearl) `pearl update`. +* **Windows**: Upgrade Powershell modules +* **Windows**: Upgrade all [Chocolatey](https://chocolatey.org/) packages +* **Windows**: Upgrade all [Scoop](https://scoop.sh) packages * Check if the following paths are tracked by Git. If so, pull them: * ~/.emacs.d (Should work whether you use [Spacemacs](http://spacemacs.org/) or a custom configuration) * ~/.zshrc @@ -45,15 +71,21 @@ Just run `topgrade`. It will run the following steps: * ~/.config/nvim * ~/.vim * ~/.config/openbox + * ~/.config/bspwm + * ~/.config/i3 * Powershell Profile * Custom defined paths -* *Unix*: Run [zplug](https://github.com/zplug/zplug) update -* *Unix*: Run [fisher](https://github.com/jorgebucaran/fisher) -* *Unix*: Upgrade tmux plugins with [TPM](https://github.com/tmux-plugins/tpm) +* **Unix**: Run [zplug](https://github.com/zplug/zplug) update +* **Unix**: Run [fisher](https://github.com/jorgebucaran/fisher) +* **Unix**: Upgrade tmux plugins with [TPM](https://github.com/tmux-plugins/tpm). *Note*: Do not use + the `-b` flag in your configuration as suggested by the TPM readme. * Update Rustup by running `rustup update`. This will also attempt to run `rustup self update` when Rustup is installed inside the home directory. * Run Cargo [install-update](https://github.com/nabijaczleweli/cargo-update) * Upgrade Emacs packages (You'll get a better output if you have [Paradox](https://github.com/Malabarba/paradox) installed) * Upgrade [OCaml packages](https://opam.ocaml.org/) +* Upgrade [vcpkg](https://github.com/Microsoft/vcpkg) globally installed packages +* Upgrade Python packages installed using [pipx](https://github.com/cs01/pipx) +* Upgrade [R globally installed packages](https://github.com/ankane/jetpack) * Upgrade Vim/Neovim packages. Works with the following plugin frameworks: * [NeoBundle](https://github.com/Shougo/neobundle.vim) * [Vundle](https://github.com/VundleVim/Vundle.vim) @@ -61,29 +93,36 @@ Just run `topgrade`. It will run the following steps: * Node * Run `yarn global update` if yarn is installed. * Run `npm update -g` if NPM is installed and `npm root -g` is a path inside your home directory. -* Run `composer global update` if Composer's home directory is inside the home directory of the user. +* Run `composer global update` if Composer's home directory is inside the home directory of the + user. Run `valet install` after. * Upgrade Atom packages * Run `gem upgrade --user-install` if `~/.gem` exists -* *Linux*: Update Flatpak packages -* *Linux*: Update snap packages -* *Linux*: Run [fwupdmgr](https://github.com/hughsie/fwupd) to show firmware upgrade. (View +* **Linux**: Update Flatpak packages +* **Linux**: Update snap packages +* **Linux**: Run [fwupdmgr](https://github.com/hughsie/fwupd) to show firmware upgrade. (View only. No upgrades will actually be performed) * Run custom defined commands * Final stage - * *Linux*: Run [needrestart](https://github.com/liske/needrestart) - * *Windows*: Run Windows Update (You'll have to install [PSWindowsUpdate](https://marckean.com/2016/06/01/use-powershell-to-install-windows-updates/)) - * *macOS*: Upgrade App Store applications + * **Linux**: Run [needrestart](https://github.com/liske/needrestart) + * **Windows**: Run Windows Update (You'll have to install [PSWindowsUpdate](https://marckean.com/2016/06/01/use-powershell-to-install-windows-updates/)) + * **macOS**: Upgrade App Store applications + * **FreeBSD**: Run `freebsd-upgrade` ## Flags * `-t/--tmux` - Topgrade will launch itself in a new tmux session. This flag has no effect if Topgrade already runs inside tmux. This is useful when using topgrade on remote systems. +* `-c/--cleanup` - Topgrade will instruct package managers to remove old or unused files * `-n/--dry-run` - Print what should be run. -* `--no-system` - Skip the system upgrade phase. -* `--no-git-repos` - Don't pull custom git repositories. -* `--no-emacs` - Don't upgrade Emacs packages or configuration files. +* `--disable [STEPS]` - Disable one or more steps: + * `system` - Skip the system upgrade phase. + * `git-repos` - Don't pull custom git repositories. + * `emacs` - Don't upgrade Emacs packages or configuration files. + * `vim` - Don't upgrade Vim/NeoVim packages or configuration files. + * `gem` - Don't upgrade ruby gems. +* `--no-retry` - Don't ask to retry failed steps. ## Customization -You can place a configuration file at `~/.config/topgrade.toml` (on macOS `~/Library/Preferences/topgrade.toml`).. Here's an example: +Here's an example for a configuration file: ``` toml @@ -91,6 +130,9 @@ git_repos = [ "~/dev/topgrade", ] +# Same options as the command line flag +disable = ["system", "emacs"] + [pre_commands] "Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak" @@ -102,3 +144,11 @@ git_repos = [ will not proceed * `commands` - Custom upgrade steps. If any command fails it will be reported in the summary as all upgrade steps are reported, but it will not cause Topgrade to stop. + +### Configuration path + +The configuration should be placed in the following paths depending by the operating system: + +* **macOS** - `~/Library/Preferences/topgrade.toml` +* **Windows** - `%APPDATA%/topgrade.toml` +* **Other Unix systems** - `~/.config/topgrade.toml` diff --git a/appveyor.yml b/appveyor.yml index fadd3d4d..168880ac 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,19 +20,19 @@ install: - rustup-init.exe -y --default-host %TARGET% --default-toolchain %RUST_VERSION% - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - rustup component add rustfmt-preview clippy-preview - - cargo fmt --all -- --check - - cargo clippy --all-targets --all-features -- -D warnings - rustc -Vv - cargo -V test_script: - if [%APPVEYOR_REPO_TAG%]==[false] ( - cargo check --target %TARGET% && - cargo check --target %TARGET% --release + cargo fmt --all -- --check && + cargo clippy --all-targets --all-features -- -D warnings && + cargo clippy --all-targets -- -D warnings && + cargo test ) before_deploy: - - cargo rustc --target %TARGET% --release --bin topgrade -- -C lto + - cargo rustc --target %TARGET% --release --bin topgrade --all-features -- -C lto - ps: ci\before_deploy.ps1 deploy: @@ -55,3 +55,10 @@ notifications: # Building is done in the test phase, so we disable Appveyor's build phase. build: false + +branches: + only: + - staging + - trying + - master + - /^v[\d.]+$/ diff --git a/bors.toml b/bors.toml new file mode 100644 index 00000000..4e6e85f4 --- /dev/null +++ b/bors.toml @@ -0,0 +1,4 @@ +status = [ + "continuous-integration/travis-ci/push", + "continuous-integration/appveyor/branch" +] diff --git a/ci/before_deploy.sh b/ci/before_deploy.sh index 176d7181..099344a5 100644 --- a/ci/before_deploy.sh +++ b/ci/before_deploy.sh @@ -18,7 +18,7 @@ main() { test -f Cargo.lock || cargo generate-lockfile # TODO Update this to build the artifacts that matter to you - cross rustc --bin topgrade --target $TARGET --release -- -C lto + cross rustc --bin topgrade --target $TARGET --release --all-features -- -C lto # TODO Update this to package the right artifacts cp target/$TARGET/release/topgrade $stage/ diff --git a/ci/script.sh b/ci/script.sh index ee3383d1..aec5e257 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -5,11 +5,12 @@ set -ex # TODO This is the "test phase", tweak it as you see fit main() { cargo fmt --all -- --check - cargo clippy --all-targets --all-features -- -D warnings - cross check --target $TARGET - cross check --target $TARGET --release + cross clippy --all-targets -- -D warnings + cross clippy --all-targets --all-features -- -D warnings + cross check --target $TARGET --release --all-features if [ ! -z $DISABLE_TESTS ]; then + cross test return fi diff --git a/src/config.rs b/src/config.rs index 33531b1f..bbfd137d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,27 +1,88 @@ +use super::error::{Error, ErrorKind}; use directories::BaseDirs; -use failure; +use failure::ResultExt; +use lazy_static::lazy_static; +use serde::Deserialize; use shellexpand; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::fs; +use structopt::StructOpt; use toml; type Commands = BTreeMap; +lazy_static! { + // While this is used to automatically generate possible value list everywhere in the code, the + // README.md file still needs to be manually updated. + static ref STEPS_MAPPING: HashMap<&'static str, Step> = { + let mut m = HashMap::new(); + + m.insert("system", Step::System); + m.insert("git-repos", Step::GitRepos); + m.insert("vim", Step::Vim); + m.insert("emacs", Step::Emacs); + m.insert("gem", Step::Gem); + + #[cfg(windows)] + m.insert("powershell", Step::Powershell); + + m + }; +} + +#[derive(Debug, Clone, PartialEq, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum Step { + /// Don't perform system upgrade + System, + /// Don't perform updates on configured git repos + GitRepos, + /// Don't upgrade Vim packages or configuration files + Vim, + /// Don't upgrade Emacs packages or configuration files + Emacs, + /// Don't upgrade ruby gems + Gem, + + #[cfg(windows)] + /// Don't update Powershell modules + Powershell, +} + +impl Step { + fn possible_values() -> Vec<&'static str> { + STEPS_MAPPING.keys().cloned().collect() + } +} + +impl std::str::FromStr for Step { + type Err = structopt::clap::Error; + fn from_str(s: &str) -> Result { + Ok(STEPS_MAPPING.get(s).unwrap().clone()) + } +} + #[derive(Deserialize, Default)] -pub struct Config { +/// Configuration file +pub struct ConfigFile { pre_commands: Option, commands: Option, git_repos: Option>, + disable: Option>, } -impl Config { - pub fn read(base_dirs: &BaseDirs) -> Result { +impl ConfigFile { + /// Read the configuration file. + /// + /// If the configuration file does not exist the function returns the default ConfigFile. + fn read(base_dirs: &BaseDirs) -> Result { let config_path = base_dirs.config_dir().join("topgrade.toml"); if !config_path.exists() { return Ok(Default::default()); } - let mut result: Self = toml::from_str(&fs::read_to_string(config_path)?)?; + let mut result: Self = toml::from_str(&fs::read_to_string(config_path).context(ErrorKind::Configuration)?) + .context(ErrorKind::Configuration)?; if let Some(ref mut paths) = &mut result.git_repos { for path in paths.iter_mut() { @@ -31,41 +92,101 @@ impl Config { Ok(result) } - - pub fn pre_commands(&self) -> &Option { - &self.pre_commands - } - - pub fn commands(&self) -> &Option { - &self.commands - } - - pub fn git_repos(&self) -> &Option> { - &self.git_repos - } } #[derive(StructOpt, Debug)] #[structopt(name = "Topgrade")] -pub struct Opt { - #[structopt(short = "t", long = "tmux", help = "Run inside tmux")] - pub run_in_tmux: bool, +/// Command line arguments +pub struct CommandLineArgs { + /// Run inside tmux + #[structopt(short = "t", long = "tmux")] + run_in_tmux: bool, - #[structopt(long = "no-system", help = "Don't perform system upgrade")] - pub no_system: bool, + /// Cleanup temporary or old files + #[structopt(short = "c", long = "cleanup")] + cleanup: bool, - #[structopt( - long = "no-git-repos", - help = "Don't perform updates on configured git repos" - )] - pub no_git_repos: bool, + /// Print what would be done + #[structopt(short = "n", long = "dry-run")] + dry_run: bool, - #[structopt( - long = "no-emacs", - help = "Don't upgrade Emacs packages or configuration files" - )] - pub no_emacs: bool, + /// Do not ask to retry failed steps + #[structopt(long = "no-retry")] + no_retry: bool, - #[structopt(short = "n", long = "dry-run", help = "Print what would be done")] - pub dry_run: bool, + /// Do not perform upgrades for the given steps + #[structopt(long = "disable", raw(possible_values = "&Step::possible_values()"))] + disable: Vec, +} + +/// Represents the application configuration +/// +/// The struct holds the loaded configuration file, as well as the arguments parsed from the command line. +/// Its provided methods decide the appropriate options based on combining the configuraiton file and the +/// command line arguments. +pub struct Config { + opt: CommandLineArgs, + config_file: ConfigFile, +} + +impl Config { + /// Load the configuration. + /// + /// The function parses the command line arguments and reading the configuration file. + pub fn load(base_dirs: &BaseDirs) -> Result { + Ok(Self { + opt: CommandLineArgs::from_args(), + config_file: ConfigFile::read(base_dirs)?, + }) + } + + /// The list of commands to run before performing any step. + pub fn pre_commands(&self) -> &Option { + &self.config_file.pre_commands + } + + /// The list of custom steps. + pub fn commands(&self) -> &Option { + &self.config_file.commands + } + + /// The list of additional git repositories to pull. + pub fn git_repos(&self) -> &Option> { + &self.config_file.git_repos + } + + /// Tell whether the specified step should run. + /// + /// If the step appears either in the `--disable` command line argument + /// or the `disable` option in the configuration, the function returns false. + pub fn should_run(&self, step: Step) -> bool { + !(self + .config_file + .disable + .as_ref() + .map(|d| d.contains(&step)) + .unwrap_or(false) + || self.opt.disable.contains(&step)) + } + + /// Tell whether we should run in tmux. + pub fn run_in_tmux(&self) -> bool { + self.opt.run_in_tmux + } + + /// Tell whether we should perform cleanup steps. + #[cfg(not(windows))] + pub fn cleanup(&self) -> bool { + self.opt.cleanup + } + + /// Tell whether we are dry-running. + pub fn dry_run(&self) -> bool { + self.opt.dry_run + } + + /// Tell whether we should not attempt to retry anything. + pub fn no_retry(&self) -> bool { + self.opt.no_retry + } } diff --git a/src/ctrlc/mod.rs b/src/ctrlc/mod.rs index 25cf5bb3..4284cd92 100644 --- a/src/ctrlc/mod.rs +++ b/src/ctrlc/mod.rs @@ -1,3 +1,5 @@ +//! Provides handling for process interruption. +//! There's no actual handling for Windows at the moment. #[cfg(unix)] mod unix; #[cfg(unix)] diff --git a/src/ctrlc/unix.rs b/src/ctrlc/unix.rs index 329f807d..d63eca81 100644 --- a/src/ctrlc/unix.rs +++ b/src/ctrlc/unix.rs @@ -1,22 +1,31 @@ +//! SIGINT handling in Unix systems. +use lazy_static::lazy_static; use nix::sys::signal; use std::sync::atomic::{AtomicBool, Ordering}; lazy_static! { - static ref RUNNING: AtomicBool = AtomicBool::new(true); + /// A global variable telling whether the application has been interrupted. + static ref INTERRUPTED: AtomicBool = AtomicBool::new(false); } -pub fn running() -> bool { - RUNNING.load(Ordering::SeqCst) +/// Tells whether the program has been interrupted +pub fn interrupted() -> bool { + INTERRUPTED.load(Ordering::SeqCst) } -pub fn set_running(value: bool) { - RUNNING.store(value, Ordering::SeqCst) +/// Clears the interrupted flag +pub fn unset_interrupted() { + debug_assert!(INTERRUPTED.load(Ordering::SeqCst)); + INTERRUPTED.store(false, Ordering::SeqCst) } +/// Handle SIGINT. Set the interruption flag. extern "C" fn handle_sigint(_: i32) { - set_running(false); + INTERRUPTED.store(true, Ordering::SeqCst) } +/// Set the necessary signal handlers. +/// The function panics on failure. pub fn set_handler() { let sig_action = signal::SigAction::new( signal::SigHandler::Handler(handle_sigint), diff --git a/src/ctrlc/windows.rs b/src/ctrlc/windows.rs index 83f9d380..65ac4ef9 100644 --- a/src/ctrlc/windows.rs +++ b/src/ctrlc/windows.rs @@ -1,7 +1,9 @@ -pub fn running() -> bool { - true +//! A stub for Ctrl + C handling. + +pub fn interrupted() -> bool { + false } -pub fn set_running(_value: bool) {} +pub fn unset_interrupted() {} pub fn set_handler() {} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..acc75255 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,83 @@ +use failure::{Backtrace, Context, Fail}; +use std::fmt::{self, Display}; +use std::process::ExitStatus; + +#[derive(Debug)] +pub struct Error { + inner: Context, +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)] +pub enum ErrorKind { + #[fail(display = "Error asking the user for retry")] + Retry, + + #[fail(display = "Cannot find the user base directories")] + NoBaseDirectories, + + #[fail(display = "A step failed")] + StepFailed, + + #[fail(display = "Error reading the configuration")] + Configuration, + + #[fail(display = "A custom pre-command failed")] + PreCommand, + + #[fail(display = "{}", _0)] + ProcessFailed(ExitStatus), + + #[fail(display = "Unknown Linux Distribution")] + #[cfg(target_os = "linux")] + UnknownLinuxDistribution, + + #[fail(display = "Detected Python is not the system Python")] + #[cfg(target_os = "linux")] + NotSystemPython, + + #[fail(display = "Process execution failure")] + ProcessExecution, + + #[fail(display = "Self-update failure")] + #[cfg(feature = "self-update")] + SelfUpdate, + + #[fail(display = "A step should be skipped")] + SkipStep, +} + +impl Fail for Error { + fn cause(&self) -> Option<&Fail> { + self.inner.cause() + } + + fn backtrace(&self) -> Option<&Backtrace> { + self.inner.backtrace() + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.inner, f) + } +} + +impl Error { + pub fn kind(&self) -> ErrorKind { + *self.inner.get_context() + } +} + +impl From for Error { + fn from(kind: ErrorKind) -> Error { + Error { + inner: Context::new(kind), + } + } +} + +impl From> for Error { + fn from(inner: Context) -> Error { + Error { inner } + } +} diff --git a/src/executor.rs b/src/executor.rs index 9f76af2b..0540c038 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,27 +1,62 @@ +//! Utilities for command execution +use super::error::{Error, ErrorKind}; use super::utils::Check; -use failure; +use failure::ResultExt; use std::ffi::{OsStr, OsString}; -use std::io; use std::path::Path; use std::process::{Child, Command, ExitStatus}; +/// An enum telling whether Topgrade should perform dry runs or actually perform the steps. +#[derive(Clone, Copy, Debug)] +pub enum RunType { + /// Executing commands will just print the command with its argument. + Dry, + + /// Executing commands will perform actual execution. + Wet, +} + +impl RunType { + /// Create a new instance from a boolean telling whether to dry run. + pub fn new(dry_run: bool) -> Self { + if dry_run { + RunType::Dry + } else { + RunType::Wet + } + } + + /// Create an instance of `Executor` that should run `program`. + pub fn execute>(self, program: S) -> Executor { + match self { + RunType::Dry => Executor::Dry(DryCommand { + program: program.as_ref().into(), + ..Default::default() + }), + RunType::Wet => Executor::Wet(Command::new(program)), + } + } + + #[cfg(feature = "self-update")] + /// Tells whether we're performing a dry run. + pub fn dry(self) -> bool { + match self { + RunType::Dry => true, + RunType::Wet => false, + } + } +} + +/// An enum providing a similar interface to `std::process::Command`. +/// If the enum is set to `Wet`, execution will be performed with `std::process::Command`. +/// If the enum is set to `Dry`, execution will just print the command with its arguments. pub enum Executor { Wet(Command), Dry(DryCommand), } impl Executor { - pub fn new>(program: S, dry: bool) -> Self { - if dry { - Executor::Dry(DryCommand { - program: program.as_ref().into(), - ..Default::default() - }) - } else { - Executor::Wet(Command::new(program)) - } - } - + /// See `std::process::Command::arg` pub fn arg>(&mut self, arg: S) -> &mut Executor { match self { Executor::Wet(c) => { @@ -35,6 +70,7 @@ impl Executor { self } + /// See `std::process::Command::args` pub fn args(&mut self, args: I) -> &mut Executor where I: IntoIterator, @@ -52,6 +88,7 @@ impl Executor { self } + /// See `std::process::Command::current_dir` pub fn current_dir>(&mut self, dir: P) -> &mut Executor { match self { Executor::Wet(c) => { @@ -63,9 +100,10 @@ impl Executor { self } - pub fn spawn(&mut self) -> Result { - match self { - Executor::Wet(c) => c.spawn().map(ExecutorChild::Wet), + /// See `std::process::Command::spawn` + pub fn spawn(&mut self) -> Result { + let result = match self { + Executor::Wet(c) => c.spawn().context(ErrorKind::ProcessExecution).map(ExecutorChild::Wet)?, Executor::Dry(c) => { print!( "Dry running: {} {}", @@ -80,12 +118,22 @@ impl Executor { Some(dir) => println!(" in {}", dir.to_string_lossy()), None => println!(), }; - Ok(ExecutorChild::Dry) + ExecutorChild::Dry } - } + }; + + Ok(result) + } + + /// A convinence method for `spawn().wait().check()`. + /// Returns an error if something went wrong during the execution or if the + /// process exited with failure. + pub fn check_run(&mut self) -> Result<(), Error> { + self.spawn()?.wait()?.check() } } +/// A struct represending a command. Trying to execute it will just print its arguments. #[derive(Default)] pub struct DryCommand { program: OsString, @@ -93,30 +141,55 @@ pub struct DryCommand { directory: Option, } +/// The Result of spawn. Contains an actual `std::process::Child` if executed by a wet command. pub enum ExecutorChild { Wet(Child), Dry, } impl ExecutorChild { - pub fn wait(&mut self) -> Result { - match self { - ExecutorChild::Wet(c) => c.wait().map(ExecutorExitStatus::Wet), - ExecutorChild::Dry => Ok(ExecutorExitStatus::Dry), - } + /// See `std::process::Child::wait` + pub fn wait(&mut self) -> Result { + let result = match self { + ExecutorChild::Wet(c) => c + .wait() + .context(ErrorKind::ProcessExecution) + .map(ExecutorExitStatus::Wet)?, + ExecutorChild::Dry => ExecutorExitStatus::Dry, + }; + + Ok(result) } } +/// The Result of wait. Contains an actual `std::process::ExitStatus` if executed by a wet command. pub enum ExecutorExitStatus { Wet(ExitStatus), Dry, } impl Check for ExecutorExitStatus { - fn check(self) -> Result<(), failure::Error> { + fn check(self) -> Result<(), Error> { match self { ExecutorExitStatus::Wet(e) => e.check(), ExecutorExitStatus::Dry => Ok(()), } } } + +/// Extension methods for `std::process::Command` +pub trait CommandExt { + /// Run the command, wait for it to complete, check the return code and decode the output as UTF-8. + fn check_output(&mut self) -> Result; +} + +impl CommandExt for Command { + fn check_output(&mut self) -> Result { + let output = self.output().context(ErrorKind::ProcessExecution)?; + let status = output.status; + if !status.success() { + Err(ErrorKind::ProcessFailed(status))? + } + Ok(String::from_utf8(output.stdout).context(ErrorKind::ProcessExecution)?) + } +} diff --git a/src/generic.rs b/src/generic.rs deleted file mode 100644 index 262dd87c..00000000 --- a/src/generic.rs +++ /dev/null @@ -1,195 +0,0 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::{self, Check, PathExt}; -use directories::BaseDirs; -use failure::Error; -use std::path::PathBuf; -use std::process::Command; - -const EMACS_UPGRADE: &str = include_str!("emacs.el"); - -#[must_use] -pub fn run_cargo_update(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(cargo_update) = base_dirs.home_dir().join(".cargo/bin/cargo-install-update").if_exists() { - terminal.print_separator("Cargo"); - - let success = || -> Result<(), Error> { - Executor::new(cargo_update, dry_run) - .args(&["install-update", "--git", "--all"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - return Some(("Cargo", success)); - } - - None -} - -#[must_use] -pub fn run_gem(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(gem) = utils::which("gem") { - if base_dirs.home_dir().join(".gem").exists() { - terminal.print_separator("RubyGems"); - - let success = || -> Result<(), Error> { - Executor::new(&gem, dry_run) - .args(&["update", "--user-install"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - return Some(("RubyGems", success)); - } - } - None -} - -#[must_use] -pub fn run_emacs(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(emacs) = utils::which("emacs") { - if let Some(init_file) = base_dirs.home_dir().join(".emacs.d/init.el").if_exists() { - terminal.print_separator("Emacs"); - - let success = || -> Result<(), Error> { - Executor::new(&emacs, dry_run) - .args(&["--batch", "-l", init_file.to_str().unwrap(), "--eval", EMACS_UPGRADE]) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - return Some(("Emacs", success)); - } - } - None -} - -#[must_use] -#[cfg( - not( - any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly" - ) - ) -)] -pub fn run_apm(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(apm) = utils::which("apm") { - terminal.print_separator("Atom Package Manager"); - - let success = || -> Result<(), Error> { - Executor::new(&apm, dry_run) - .args(&["upgrade", "--confirm=false"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - return Some(("apm", success)); - } - - None -} - -#[must_use] -pub fn run_rustup(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(rustup) = utils::which("rustup") { - terminal.print_separator("rustup"); - - let success = || -> Result<(), Error> { - if rustup.is_descendant_of(base_dirs.home_dir()) { - Executor::new(&rustup, dry_run) - .args(&["self", "update"]) - .spawn()? - .wait()? - .check()?; - } - - Executor::new(&rustup, dry_run).arg("update").spawn()?.wait()?.check()?; - Ok(()) - }().is_ok(); - - return Some(("rustup", success)); - } - - None -} - -#[must_use] -pub fn run_opam_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(opam) = utils::which("opam") { - terminal.print_separator("OCaml Package Manager"); - - let success = || -> Result<(), Error> { - Executor::new(&opam, dry_run).arg("update").spawn()?.wait()?.check()?; - Executor::new(&opam, dry_run).arg("upgrade").spawn()?.wait()?.check()?; - Ok(()) - }().is_ok(); - - return Some(("OPAM", success)); - } - - None -} - -#[must_use] -pub fn run_custom_command(name: &str, command: &str, terminal: &mut Terminal, dry_run: bool) -> Result<(), Error> { - terminal.print_separator(name); - Executor::new("sh", dry_run) - .arg("-c") - .arg(command) - .spawn()? - .wait()? - .check()?; - - Ok(()) -} - -#[must_use] -pub fn run_composer_update( - base_dirs: &BaseDirs, - terminal: &mut Terminal, - dry_run: bool, -) -> Option<(&'static str, bool)> { - if let Some(composer) = utils::which("composer") { - let composer_home = || -> Result { - let output = Command::new(&composer) - .args(&["global", "config", "--absolute", "home"]) - .output()?; - output.status.check()?; - Ok(PathBuf::from(&String::from_utf8(output.stdout)?)) - }(); - - if let Ok(composer_home) = composer_home { - if composer_home.is_descendant_of(base_dirs.home_dir()) { - terminal.print_separator("Composer"); - - let success = || -> Result<(), Error> { - Executor::new(&composer, dry_run) - .args(&["global", "update"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Composer", success)); - } - } - } - - None -} diff --git a/src/linux.rs b/src/linux.rs deleted file mode 100644 index 5fb267f3..00000000 --- a/src/linux.rs +++ /dev/null @@ -1,314 +0,0 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::{which, Check}; -use failure; -use std::fs; -use std::path::PathBuf; -use walkdir::WalkDir; - -#[derive(Copy, Clone, Debug)] -pub enum Distribution { - Arch, - CentOS, - Fedora, - Debian, - Ubuntu, -} - -#[derive(Debug, Fail)] -#[fail(display = "Unknown Linux Distribution")] -struct UnknownLinuxDistribution; - -#[derive(Debug, Fail)] -#[fail(display = "Detected Python is not the system Python")] -struct NotSystemPython; - -impl Distribution { - pub fn detect() -> Result { - let content = fs::read_to_string("/etc/os-release")?; - - if content.contains("Arch") | content.contains("Manjaro") | content.contains("Antergos") { - return Ok(Distribution::Arch); - } - - if content.contains("CentOS") { - return Ok(Distribution::CentOS); - } - - if content.contains("Fedora") { - return Ok(Distribution::Fedora); - } - - if content.contains("Ubuntu") { - return Ok(Distribution::Ubuntu); - } - - if content.contains("Debian") { - return Ok(Distribution::Debian); - } - - Err(UnknownLinuxDistribution.into()) - } - - #[must_use] - pub fn upgrade( - self, - sudo: &Option, - terminal: &mut Terminal, - dry_run: bool, - ) -> Option<(&'static str, bool)> { - terminal.print_separator("System update"); - - let success = match self { - Distribution::Arch => upgrade_arch_linux(&sudo, terminal, dry_run), - Distribution::CentOS => upgrade_redhat(&sudo, terminal, dry_run), - Distribution::Fedora => upgrade_fedora(&sudo, terminal, dry_run), - Distribution::Ubuntu | Distribution::Debian => upgrade_debian(&sudo, terminal, dry_run), - }; - - Some(("System update", success.is_ok())) - } - - pub fn show_summary(self) { - if let Distribution::Arch = self { - show_pacnew(); - } - } -} - -pub fn show_pacnew() { - let mut iter = WalkDir::new("/etc") - .into_iter() - .filter_map(|e| e.ok()) - .filter(|f| { - f.path() - .extension() - .filter(|ext| ext == &"pacnew" || ext == &"pacsave") - .is_some() - }).peekable(); - - if iter.peek().is_some() { - println!("\nPacman backup configuration files found:"); - - for entry in iter { - println!("{}", entry.path().display()); - } - } -} - -fn upgrade_arch_linux(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { - if let Some(yay) = which("yay") { - if let Some(python) = which("python") { - if python != PathBuf::from("/usr/bin/python") { - terminal.print_warning(format!( - "Python detected at {:?}, which is probably not the system Python. -It's dangerous to run yay since Python based AUR packages will be installed in the wrong location", - python - )); - return Err(NotSystemPython.into()); - } - } - - Executor::new(yay, dry_run).spawn()?.wait()?.check()?; - } else if let Some(sudo) = &sudo { - Executor::new(&sudo, dry_run) - .args(&["/usr/bin/pacman", "-Syu"]) - .spawn()? - .wait()? - .check()?; - } else { - terminal.print_warning("No sudo or yay detected. Skipping system upgrade"); - } - - Ok(()) -} - -fn upgrade_redhat(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { - if let Some(sudo) = &sudo { - Executor::new(&sudo, dry_run) - .args(&["/usr/bin/yum", "upgrade"]) - .spawn()? - .wait()? - .check()?; - } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); - } - - Ok(()) -} - -fn upgrade_fedora(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { - if let Some(sudo) = &sudo { - Executor::new(&sudo, dry_run) - .args(&["/usr/bin/dnf", "upgrade"]) - .spawn()? - .wait()? - .check()?; - } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); - } - - Ok(()) -} - -fn upgrade_debian(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Result<(), failure::Error> { - if let Some(sudo) = &sudo { - Executor::new(&sudo, dry_run) - .args(&["/usr/bin/apt", "update"]) - .spawn()? - .wait()? - .check()?; - - Executor::new(&sudo, dry_run) - .args(&["/usr/bin/apt", "dist-upgrade"]) - .spawn()? - .wait()? - .check()?; - } else { - terminal.print_warning("No sudo detected. Skipping system upgrade"); - } - - Ok(()) -} - -#[must_use] -pub fn run_needrestart(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(sudo) = sudo { - if let Some(needrestart) = which("needrestart") { - terminal.print_separator("Check for needed restarts"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&sudo, dry_run) - .arg(needrestart) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - return Some(("Restarts", success)); - } - } - - None -} - -#[must_use] -pub fn run_fwupdmgr(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(fwupdmgr) = which("fwupdmgr") { - terminal.print_separator("Firmware upgrades"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&fwupdmgr, dry_run) - .arg("refresh") - .spawn()? - .wait()? - .check()?; - Executor::new(&fwupdmgr, dry_run) - .arg("get-updates") - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Firmware upgrade", success)); - } - - None -} - -#[must_use] -pub fn flatpak_user_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(flatpak) = which("flatpak") { - terminal.print_separator("Flatpak User Packages"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&flatpak, dry_run) - .args(&["update", "--user", "-y"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Flatpak User Packages", success)); - } - - None -} - -#[must_use] -pub fn flatpak_global_update( - sudo: &Option, - terminal: &mut Terminal, - dry_run: bool, -) -> Option<(&'static str, bool)> { - if let Some(sudo) = sudo { - if let Some(flatpak) = which("flatpak") { - terminal.print_separator("Flatpak Global Packages"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&sudo, dry_run) - .args(&[flatpak.to_str().unwrap(), "update", "-y"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Flatpak Global Packages", success)); - } - } - - None -} - -#[must_use] -pub fn run_snap(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(sudo) = sudo { - if let Some(snap) = which("snap") { - if PathBuf::from("/var/snapd.socket").exists() { - terminal.print_separator("snap"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&sudo, dry_run) - .args(&[snap.to_str().unwrap(), "refresh"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - return Some(("snap", success)); - } - } - } - - None -} - -#[must_use] -pub fn run_etc_update(sudo: &Option, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(sudo) = sudo { - if let Some(etc_update) = which("etc-update") { - terminal.print_separator("etc-update"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&sudo, dry_run) - .arg(&etc_update.to_str().unwrap()) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - return Some(("snap", success)); - } - } - - None -} diff --git a/src/macos.rs b/src/macos.rs deleted file mode 100644 index f30f017b..00000000 --- a/src/macos.rs +++ /dev/null @@ -1,20 +0,0 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::Check; -use failure; - -#[must_use] -pub fn upgrade_macos(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - terminal.print_separator("App Store"); - - let success = || -> Result<(), failure::Error> { - Executor::new("softwareupdate", dry_run) - .args(&["--install", "--all"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - Some(("App Store", success)) -} diff --git a/src/main.rs b/src/main.rs index 6a47c33c..5e6c3c1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,114 +1,72 @@ -extern crate directories; -extern crate failure; -extern crate which; -#[macro_use] -extern crate failure_derive; -extern crate toml; -#[macro_use] -extern crate serde_derive; -#[macro_use] -extern crate structopt; -extern crate serde; -extern crate shellexpand; -#[macro_use] -extern crate log; -extern crate console; -extern crate env_logger; -#[cfg(unix)] -extern crate nix; -#[cfg(unix)] -#[macro_use] -extern crate lazy_static; -extern crate term_size; -extern crate termcolor; -extern crate walkdir; - -#[cfg(target_os = "linux")] -mod linux; -#[cfg(target_os = "macos")] -mod macos; -#[cfg(unix)] -mod tmux; -#[cfg(unix)] -mod unix; -#[cfg(target_os = "windows")] -mod windows; - mod config; mod ctrlc; +mod error; mod executor; -mod generic; -mod git; -mod node; mod report; +#[cfg(feature = "self-update")] +mod self_update; +mod steps; mod terminal; mod utils; -mod vim; -use self::config::Config; -use self::git::{Git, Repositories}; +use self::config::{Config, Step}; +use self::error::{Error, ErrorKind}; use self::report::Report; -use self::terminal::Terminal; -use failure::Error; +use self::steps::*; +use self::terminal::*; +use failure::{Fail, ResultExt}; +use log::debug; use std::borrow::Cow; use std::env; -use std::io::ErrorKind; +use std::fmt::Debug; +use std::io; +#[cfg(windows)] +use std::path::PathBuf; use std::process::exit; -use structopt::StructOpt; -#[derive(Fail, Debug)] -#[fail(display = "A step failed")] -struct StepFailed; - -#[derive(Fail, Debug)] -#[fail(display = "Cannot find the user base directories")] -struct NoBaseDirectories; - -#[derive(Fail, Debug)] -#[fail(display = "Process Interrupted")] -pub struct Interrupted; - -struct ExecutionContext { - terminal: Terminal, -} - -fn execute<'a, F, M>(func: F, execution_context: &mut ExecutionContext) -> Result, Error> +fn execute<'a, F, M>(report: &mut Report<'a>, key: M, func: F, no_retry: bool) -> Result<(), Error> where - M: Into>, - F: Fn(&mut Terminal) -> Option<(M, bool)>, + F: Fn() -> Result<(), Error>, + M: Into> + Debug, { - while let Some((key, success)) = func(&mut execution_context.terminal) { - if success { - return Ok(Some((key, success))); - } + debug!("Executing {:?}", key); - let running = ctrlc::running(); - if !running { - ctrlc::set_running(true); - } - - let should_retry = execution_context.terminal.should_retry(running).map_err(|e| { - if e.kind() == ErrorKind::Interrupted { - Error::from(Interrupted) - } else { - Error::from(e) + loop { + match func() { + Ok(()) => { + report.push_result(Some((key, true))); + break; } - })?; + Err(ref e) if e.kind() == ErrorKind::SkipStep => { + break; + } + Err(_) => { + let interrupted = ctrlc::interrupted(); + if interrupted { + ctrlc::unset_interrupted(); + } - if !should_retry { - return Ok(Some((key, success))); + let should_ask = interrupted || !no_retry; + let should_retry = should_ask && should_retry(interrupted).context(ErrorKind::Retry)?; + + if !should_retry { + report.push_result(Some((key, false))); + break; + } + } } } - Ok(None) + Ok(()) } fn run() -> Result<(), Error> { ctrlc::set_handler(); - let opt = config::Opt::from_args(); + let base_dirs = directories::BaseDirs::new().ok_or(ErrorKind::NoBaseDirectories)?; + let config = Config::load(&base_dirs)?; - if opt.run_in_tmux && env::var("TMUX").is_err() { + if config.run_in_tmux() && env::var("TMUX").is_err() { #[cfg(unix)] { tmux::run_in_tmux(); @@ -116,23 +74,31 @@ fn run() -> Result<(), Error> { } env_logger::init(); - let base_dirs = directories::BaseDirs::new().ok_or(NoBaseDirectories)?; - let git = Git::new(); - let mut git_repos = Repositories::new(&git); - let mut execution_context = ExecutionContext { - terminal: Terminal::new(), - }; + let git = git::Git::new(); + let mut git_repos = git::Repositories::new(&git); - let config = Config::read(&base_dirs)?; let mut report = Report::new(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "freebsd", target_os = "linux"))] let sudo = utils::which("sudo"); + let run_type = executor::RunType::new(config.dry_run()); + + #[cfg(feature = "self-update")] + { + if !run_type.dry() && env::var("TOPGRADE_NO_SELF_UPGRADE").is_err() { + if let Err(e) = self_update::self_update() { + print_warning(format!("Self update error: {}", e)); + if let Some(cause) = e.cause() { + print_warning(format!("Caused by: {}", cause)); + } + } + } + } if let Some(commands) = config.pre_commands() { for (name, command) in commands { - generic::run_custom_command(&name, &command, &mut execution_context.terminal, opt.dry_run)?; + generic::run_custom_command(&name, &command, run_type).context(ErrorKind::PreCommand)?; } } @@ -140,59 +106,81 @@ fn run() -> Result<(), Error> { let powershell = windows::Powershell::new(); #[cfg(windows)] - report.push_result(execute( - |terminal| powershell.update_modules(terminal, opt.dry_run), - &mut execution_context, - )?); + let should_run_powershell = powershell.profile().is_some() && config.should_run(Step::Powershell); #[cfg(target_os = "linux")] let distribution = linux::Distribution::detect(); #[cfg(target_os = "linux")] { - if !opt.no_system { + if config.should_run(Step::System) { match &distribution { Ok(distribution) => { - report.push_result(execute( - |terminal| distribution.upgrade(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "System update", + || distribution.upgrade(&sudo, config.cleanup(), run_type), + config.no_retry(), + )?; } Err(e) => { println!("Error detecting current distribution: {}", e); } } - report.push_result(execute( - |terminal| linux::run_etc_update(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "etc-update", + || linux::run_etc_update(sudo.as_ref(), run_type), + config.no_retry(), + )?; } } #[cfg(windows)] - report.push_result(execute( - |terminal| windows::run_chocolatey(terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "Chocolatey", + || windows::run_chocolatey(run_type), + config.no_retry(), + )?; #[cfg(windows)] - report.push_result(execute( - |terminal| windows::run_scoop(terminal, opt.dry_run), - &mut execution_context, - )?); + execute(&mut report, "Scoop", || windows::run_scoop(run_type), config.no_retry())?; #[cfg(unix)] - report.push_result(execute( - |terminal| unix::run_homebrew(terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "brew", + || unix::run_homebrew(config.cleanup(), run_type), + config.no_retry(), + )?; + #[cfg(target_os = "freebsd")] + execute( + &mut report, + "FreeBSD Packages", + || freebsd::upgrade_packages(sudo.as_ref(), run_type), + config.no_retry(), + )?; + #[cfg(unix)] + execute(&mut report, "nix", || unix::run_nix(run_type), config.no_retry())?; - if !opt.no_emacs { + if config.should_run(Step::Emacs) { + #[cfg(unix)] git_repos.insert(base_dirs.home_dir().join(".emacs.d")); + + #[cfg(windows)] + { + git_repos.insert(base_dirs.data_dir().join(".emacs.d")); + if let Ok(home) = env::var("HOME") { + git_repos.insert(PathBuf::from(home).join(".emacs.d")); + } + } } - git_repos.insert(base_dirs.home_dir().join(".vim")); - git_repos.insert(base_dirs.home_dir().join(".config/nvim")); + if config.should_run(Step::Vim) { + git_repos.insert(base_dirs.home_dir().join(".vim")); + git_repos.insert(base_dirs.home_dir().join(".config/nvim")); + } #[cfg(unix)] { @@ -201,6 +189,8 @@ fn run() -> Result<(), Error> { git_repos.insert(base_dirs.home_dir().join(".tmux")); git_repos.insert(base_dirs.home_dir().join(".config/fish")); git_repos.insert(base_dirs.config_dir().join("openbox")); + git_repos.insert(base_dirs.config_dir().join("bspwm")); + git_repos.insert(base_dirs.config_dir().join("i3")); } #[cfg(windows)] @@ -210,7 +200,7 @@ fn run() -> Result<(), Error> { } } - if !opt.no_git_repos { + if config.should_run(Step::GitRepos) { if let Some(custom_git_repos) = config.git_repos() { for git_repo in custom_git_repos { git_repos.insert(git_repo); @@ -218,155 +208,232 @@ fn run() -> Result<(), Error> { } } for repo in git_repos.repositories() { - report.push_result(execute( - |terminal| git.pull(&repo, terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + format!("git: {}", utils::HumanizedPath::from(std::path::Path::new(&repo))), + || git.pull(&repo, run_type), + config.no_retry(), + )?; + } + + #[cfg(windows)] + { + if should_run_powershell { + execute( + &mut report, + "Powershell Modules Update", + || powershell.update_modules(run_type), + config.no_retry(), + )?; + } } #[cfg(unix)] { - report.push_result(execute( - |terminal| unix::run_zplug(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| unix::run_fisher(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| tmux::run_tpm(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "zplug", + || unix::run_zplug(&base_dirs, run_type), + config.no_retry(), + )?; + execute( + &mut report, + "fisher", + || unix::run_fisher(&base_dirs, run_type), + config.no_retry(), + )?; + execute( + &mut report, + "tmux", + || tmux::run_tpm(&base_dirs, run_type), + config.no_retry(), + )?; } - report.push_result(execute( - |terminal| generic::run_rustup(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_cargo_update(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "rustup", + || generic::run_rustup(&base_dirs, run_type), + config.no_retry(), + )?; + execute( + &mut report, + "cargo", + || generic::run_cargo_update(run_type), + config.no_retry(), + )?; - if !opt.no_emacs { - report.push_result(execute( - |terminal| generic::run_emacs(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); + if config.should_run(Step::Emacs) { + execute( + &mut report, + "Emacs", + || generic::run_emacs(&base_dirs, run_type), + config.no_retry(), + )?; } - report.push_result(execute( - |terminal| generic::run_opam_update(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| vim::upgrade_vim(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| vim::upgrade_neovim(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| node::run_npm_upgrade(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_composer_update(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| node::yarn_global_update(terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "opam", + || generic::run_opam_update(run_type), + config.no_retry(), + )?; + execute( + &mut report, + "vcpkg", + || generic::run_vcpkg_update(run_type), + config.no_retry(), + )?; + execute( + &mut report, + "pipx", + || generic::run_pipx_update(run_type), + config.no_retry(), + )?; + #[cfg(unix)] + execute(&mut report, "pearl", || unix::run_pearl(run_type), config.no_retry())?; + execute( + &mut report, + "jetpak", + || generic::run_jetpack(run_type), + config.no_retry(), + )?; - #[cfg( - not( - any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly" - ) - ) - )] - report.push_result(execute( - |terminal| generic::run_apm(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| generic::run_gem(&base_dirs, terminal, opt.dry_run), - &mut execution_context, - )?); + if config.should_run(Step::Vim) { + execute( + &mut report, + "vim", + || vim::upgrade_vim(&base_dirs, run_type), + config.no_retry(), + )?; + execute( + &mut report, + "Neovim", + || vim::upgrade_neovim(&base_dirs, run_type), + config.no_retry(), + )?; + } + + execute( + &mut report, + "NPM", + || node::run_npm_upgrade(&base_dirs, run_type), + config.no_retry(), + )?; + execute( + &mut report, + "composer", + || generic::run_composer_update(&base_dirs, run_type), + config.no_retry(), + )?; + execute( + &mut report, + "yarn", + || node::yarn_global_update(run_type), + config.no_retry(), + )?; + + #[cfg(not(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly" + )))] + execute(&mut report, "apm", || generic::run_apm(run_type), config.no_retry())?; + + if config.should_run(Step::Gem) { + execute( + &mut report, + "gem", + || generic::run_gem(&base_dirs, run_type), + config.no_retry(), + )?; + } #[cfg(target_os = "linux")] { - report.push_result(execute( - |terminal| linux::flatpak_user_update(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| linux::flatpak_global_update(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| linux::run_snap(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "Flatpak", + || linux::flatpak_update(run_type), + config.no_retry(), + )?; + execute( + &mut report, + "snap", + || linux::run_snap(sudo.as_ref(), run_type), + config.no_retry(), + )?; } if let Some(commands) = config.commands() { for (name, command) in commands { - report.push_result(execute( - |terminal| { - Some(( - name, - generic::run_custom_command(&name, &command, terminal, opt.dry_run).is_ok(), - )) - }, - &mut execution_context, - )?); + execute( + &mut report, + name, + || generic::run_custom_command(&name, &command, run_type), + config.no_retry(), + )?; } } #[cfg(target_os = "linux")] { - report.push_result(execute( - |terminal| linux::run_fwupdmgr(terminal, opt.dry_run), - &mut execution_context, - )?); - report.push_result(execute( - |terminal| linux::run_needrestart(&sudo, terminal, opt.dry_run), - &mut execution_context, - )?); + execute( + &mut report, + "Firmware upgrades", + || linux::run_fwupdmgr(run_type), + config.no_retry(), + )?; + execute( + &mut report, + "Restarts", + || linux::run_needrestart(sudo.as_ref(), run_type), + config.no_retry(), + )?; } #[cfg(target_os = "macos")] { - if !opt.no_system { - report.push_result(execute( - |terminal| macos::upgrade_macos(terminal, opt.dry_run), - &mut execution_context, - )?); + if config.should_run(Step::System) { + execute( + &mut report, + "App Store", + || macos::upgrade_macos(run_type), + config.no_retry(), + )?; + } + } + + #[cfg(target_os = "freebsd")] + { + if config.should_run(Step::System) { + execute( + &mut report, + "FreeBSD Upgrade", + || freebsd::upgrade_freebsd(sudo.as_ref(), run_type), + config.no_retry(), + )?; } } #[cfg(windows)] { - if !opt.no_system { - report.push_result(execute( - |terminal| powershell.windows_update(terminal, opt.dry_run), - &mut execution_context, - )?); + if config.should_run(Step::System) { + execute( + &mut report, + "Windows update", + || powershell.windows_update(run_type), + config.no_retry(), + )?; } } if !report.data().is_empty() { - execution_context.terminal.print_separator("Summary"); + print_separator("Summary"); for (key, succeeded) in report.data() { - execution_context.terminal.print_result(key, *succeeded); + print_result(key, *succeeded); } #[cfg(target_os = "linux")] @@ -375,12 +442,15 @@ fn run() -> Result<(), Error> { distribution.show_summary(); } } + + #[cfg(target_os = "freebsd")] + freebsd::audit_packages(&sudo).ok(); } if report.data().iter().all(|(_, succeeded)| *succeeded) { Ok(()) } else { - Err(StepFailed.into()) + Err(ErrorKind::StepFailed)? } } @@ -390,13 +460,21 @@ fn main() { exit(0); } Err(error) => { - match error - .downcast::() - .map(|_| ()) - .or_else(|error| error.downcast::().map(|_| ())) - { - Ok(_) => (), - Err(error) => println!("ERROR: {}", error), + let should_print = match error.kind() { + ErrorKind::StepFailed => false, + ErrorKind::Retry => error + .cause() + .and_then(|cause| cause.downcast_ref::()) + .filter(|io_error| io_error.kind() == io::ErrorKind::Interrupted) + .is_none(), + _ => true, + }; + + if should_print { + println!("Error: {}", error); + if let Some(cause) = error.cause() { + println!("Caused by: {}", cause); + } } exit(1); } diff --git a/src/node.rs b/src/node.rs deleted file mode 100644 index 7fe58613..00000000 --- a/src/node.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::{which, Check, PathExt}; -use directories::BaseDirs; -use failure; -use std::path::PathBuf; -use std::process::Command; - -struct NPM { - command: PathBuf, -} - -impl NPM { - fn new(command: PathBuf) -> Self { - Self { command } - } - - fn root(&self) -> Result { - let output = Command::new(&self.command).args(&["root", "-g"]).output()?; - - output.status.check()?; - - Ok(PathBuf::from(&String::from_utf8(output.stdout)?)) - } - - fn upgrade(&self, dry_run: bool) -> Result<(), failure::Error> { - Executor::new(&self.command, dry_run) - .args(&["update", "-g"]) - .spawn()? - .wait()? - .check()?; - - Ok(()) - } -} - -#[must_use] -pub fn run_npm_upgrade(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(npm) = which("npm").map(NPM::new) { - if let Ok(npm_root) = npm.root() { - if npm_root.is_descendant_of(base_dirs.home_dir()) { - terminal.print_separator("Node Package Manager"); - let success = npm.upgrade(dry_run).is_ok(); - return Some(("NPM", success)); - } - } - } - None -} - -#[must_use] -pub fn yarn_global_update(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(yarn) = which("yarn") { - terminal.print_separator("Yarn"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&yarn, dry_run) - .args(&["global", "upgrade", "-s"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("yarn", success)); - } - - None -} diff --git a/src/self_update.rs b/src/self_update.rs new file mode 100644 index 00000000..eb7725ef --- /dev/null +++ b/src/self_update.rs @@ -0,0 +1,54 @@ +use super::error::{Error, ErrorKind}; +use super::terminal::*; +use failure::ResultExt; +use self_update_crate; +use self_update_crate::backends::github::{GitHubUpdateStatus, Update}; +#[cfg(unix)] +use std::env; +#[cfg(unix)] +use std::os::unix::process::CommandExt; +#[cfg(unix)] +use std::process::Command; + +pub fn self_update() -> Result<(), Error> { + print_separator("Self update"); + #[cfg(unix)] + let current_exe = env::current_exe(); + + let target = self_update_crate::get_target().context(ErrorKind::SelfUpdate)?; + let result = Update::configure() + .and_then(|mut u| { + u.repo_owner("r-darwish") + .repo_name("topgrade") + .target(&target) + .bin_name(if cfg!(windows) { "topgrade.exe" } else { "topgrade" }) + .show_output(false) + .show_download_progress(true) + .current_version(self_update_crate::cargo_crate_version!()) + .no_confirm(true) + .build() + }) + .and_then(|u| u.update_extended()) + .context(ErrorKind::SelfUpdate)?; + + if let GitHubUpdateStatus::Updated(release) = &result { + println!("\nTopgrade upgraded to {}:\n", release.version()); + println!("{}", release.body); + } else { + println!("Topgrade is up-to-date"); + } + + #[cfg(unix)] + { + if result.updated() { + print_warning("Respawning..."); + let err = Command::new(current_exe.context(ErrorKind::SelfUpdate)?) + .args(env::args().skip(1)) + .env("TOPGRADE_NO_SELF_UPGRADE", "") + .exec(); + Err(err).context(ErrorKind::SelfUpdate)? + } + } + + Ok(()) +} diff --git a/src/emacs.el b/src/steps/emacs.el similarity index 100% rename from src/emacs.el rename to src/steps/emacs.el diff --git a/src/steps/generic.rs b/src/steps/generic.rs new file mode 100644 index 00000000..e44c6ffd --- /dev/null +++ b/src/steps/generic.rs @@ -0,0 +1,132 @@ +use crate::error::{Error, ErrorKind}; +use crate::executor::{CommandExt, RunType}; +use crate::terminal::print_separator; +use crate::utils::{self, PathExt}; +use directories::BaseDirs; +use failure::ResultExt; +use std::path::PathBuf; +use std::process::Command; + +const EMACS_UPGRADE: &str = include_str!("emacs.el"); + +pub fn run_cargo_update(run_type: RunType) -> Result<(), Error> { + let cargo_update = utils::require("cargo-install-update")?; + + print_separator("Cargo"); + + run_type + .execute(cargo_update) + .args(&["install-update", "--git", "--all"]) + .check_run() +} + +pub fn run_gem(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let gem = utils::require("gem")?; + base_dirs.home_dir().join(".gem").require()?; + + print_separator("RubyGems"); + + run_type.execute(&gem).args(&["update", "--user-install"]).check_run() +} + +pub fn run_emacs(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let emacs = utils::require("emacs")?; + let init_file = base_dirs.home_dir().join(".emacs.d/init.el").require()?; + + print_separator("Emacs"); + + run_type + .execute(&emacs) + .args(&["--batch", "-l", init_file.to_str().unwrap(), "--eval", EMACS_UPGRADE]) + .check_run() +} + +#[cfg(not(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly" +)))] +pub fn run_apm(run_type: RunType) -> Result<(), Error> { + let apm = utils::require("apm")?; + + print_separator("Atom Package Manager"); + + run_type.execute(&apm).args(&["upgrade", "--confirm=false"]).check_run() +} + +pub fn run_rustup(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let rustup = utils::require("rustup")?; + + print_separator("rustup"); + + if rustup + .canonicalize() + .context(ErrorKind::StepFailed)? + .is_descendant_of(base_dirs.home_dir()) + { + run_type.execute(&rustup).args(&["self", "update"]).check_run()?; + } + + run_type.execute(&rustup).arg("update").check_run() +} + +pub fn run_jetpack(run_type: RunType) -> Result<(), Error> { + let jetpack = utils::require("jetpack")?; + + print_separator("Jetpack"); + + run_type.execute(&jetpack).args(&["global", "update"]).check_run() +} + +pub fn run_opam_update(run_type: RunType) -> Result<(), Error> { + let opam = utils::require("opam")?; + + print_separator("OCaml Package Manager"); + + run_type.execute(&opam).arg("update").check_run()?; + run_type.execute(&opam).arg("upgrade").check_run() +} + +pub fn run_vcpkg_update(run_type: RunType) -> Result<(), Error> { + let vcpkg = utils::require("vcpkg")?; + print_separator("vcpkg"); + + run_type.execute(&vcpkg).args(&["upgrade", "--no-dry-run"]).check_run() +} + +pub fn run_pipx_update(run_type: RunType) -> Result<(), Error> { + let pipx = utils::require("pipx")?; + print_separator("pipx"); + + run_type.execute(&pipx).arg("upgrade-all").check_run() +} + +pub fn run_custom_command(name: &str, command: &str, run_type: RunType) -> Result<(), Error> { + print_separator(name); + run_type.execute("sh").arg("-c").arg(command).check_run() +} + +pub fn run_composer_update(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let composer = utils::require("composer")?; + let composer_home = Command::new(&composer) + .args(&["global", "config", "--absolute", "home"]) + .check_output() + .map_err(|_| Error::from(ErrorKind::SkipStep)) + .map(PathBuf::from) + .and_then(|p| p.require())?; + + if !composer_home.is_descendant_of(base_dirs.home_dir()) { + Err(ErrorKind::SkipStep)?; + } + + print_separator("Composer"); + + run_type.execute(&composer).args(&["global", "update"]).check_run()?; + + if let Some(valet) = utils::which("valet") { + run_type.execute(&valet).arg("install").check_run()?; + } + + Ok(()) +} diff --git a/src/git.rs b/src/steps/git.rs similarity index 59% rename from src/git.rs rename to src/steps/git.rs index cc6df9d8..4c066ccc 100644 --- a/src/git.rs +++ b/src/steps/git.rs @@ -1,16 +1,19 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::{which, Check}; -use failure::Error; +use crate::error::Error; +use crate::executor::{CommandExt, RunType}; +use crate::terminal::print_separator; +use crate::utils::{which, HumanizedPath}; +use log::{debug, error}; use std::collections::HashSet; use std::io; use std::path::{Path, PathBuf}; use std::process::Command; +#[derive(Debug)] pub struct Git { git: Option, } +#[derive(Debug)] pub struct Repositories<'a> { git: &'a Git, repositories: HashSet, @@ -37,15 +40,10 @@ impl Git { let output = Command::new(&git) .args(&["rev-parse", "--show-toplevel"]) .current_dir(path) - .output(); - - if let Ok(output) = output { - if !output.status.success() { - return None; - } - - return Some(String::from_utf8_lossy(&output.stdout).trim().to_string()); - } + .check_output() + .ok() + .map(|output| output.trim().to_string()); + return output; } } Err(e) => match e.kind() { @@ -57,32 +55,18 @@ impl Git { None } - pub fn pull>(&self, path: P, terminal: &mut Terminal, dry_run: bool) -> Option<(String, bool)> { + pub fn pull>(&self, path: P, run_type: RunType) -> Result<(), Error> { let path = path.as_ref(); - terminal.print_separator(format!("Pulling {}", path.display())); + print_separator(format!("Pulling {}", HumanizedPath::from(path))); let git = self.git.as_ref().unwrap(); - let success = || -> Result<(), Error> { - Executor::new(git, dry_run) - .args(&["pull", "--rebase", "--autostash"]) - .current_dir(&path) - .spawn()? - .wait()? - .check()?; - - Executor::new(git, dry_run) - .args(&["submodule", "update", "--init", "--recursive"]) - .current_dir(&path) - .spawn()? - .wait()? - .check()?; - - Ok(()) - }().is_ok(); - - Some((format!("git: {}", path.display()), success)) + run_type + .execute(git) + .args(&["pull", "--rebase", "--autostash"]) + .current_dir(&path) + .check_run() } } diff --git a/src/steps/mod.rs b/src/steps/mod.rs new file mode 100644 index 00000000..789ab6fd --- /dev/null +++ b/src/steps/mod.rs @@ -0,0 +1,9 @@ +pub mod generic; +pub mod git; +pub mod node; +pub mod os; +#[cfg(unix)] +pub mod tmux; +pub mod vim; + +pub use self::os::*; diff --git a/src/steps/node.rs b/src/steps/node.rs new file mode 100644 index 00000000..254edc34 --- /dev/null +++ b/src/steps/node.rs @@ -0,0 +1,48 @@ +use crate::error::{Error, ErrorKind}; +use crate::executor::{CommandExt, RunType}; +use crate::terminal::print_separator; +use crate::utils::{require, PathExt}; +use directories::BaseDirs; +use std::path::PathBuf; +use std::process::Command; + +struct NPM { + command: PathBuf, +} + +impl NPM { + fn new(command: PathBuf) -> Self { + Self { command } + } + + fn root(&self) -> Result { + Command::new(&self.command) + .args(&["root", "-g"]) + .check_output() + .map(PathBuf::from) + } + + fn upgrade(&self, run_type: RunType) -> Result<(), Error> { + run_type.execute(&self.command).args(&["update", "-g"]).check_run()?; + + Ok(()) + } +} + +pub fn run_npm_upgrade(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let npm = require("npm").map(NPM::new)?; + let npm_root = npm.root()?; + if !npm_root.is_descendant_of(base_dirs.home_dir()) { + Err(ErrorKind::SkipStep)?; + } + + print_separator("Node Package Manager"); + npm.upgrade(run_type) +} + +pub fn yarn_global_update(run_type: RunType) -> Result<(), Error> { + let yarn = require("yarn")?; + + print_separator("Yarn"); + run_type.execute(&yarn).args(&["global", "upgrade", "-s"]).check_run() +} diff --git a/src/steps/os/freebsd.rs b/src/steps/os/freebsd.rs new file mode 100644 index 00000000..1aed91b6 --- /dev/null +++ b/src/steps/os/freebsd.rs @@ -0,0 +1,35 @@ +use crate::error::{Error, ErrorKind}; +use crate::executor::RunType; +use crate::terminal::print_separator; +use crate::utils::require_option; +use failure::ResultExt; +use std::path::PathBuf; +use std::process::Command; + +pub fn upgrade_freebsd(sudo: Option<&PathBuf>, run_type: RunType) -> Result<(), Error> { + let sudo = require_option(sudo)?; + print_separator("FreeBSD Update"); + run_type + .execute(sudo) + .args(&["/usr/sbin/freebsd-update", "fetch", "install"]) + .check_run() +} + +pub fn upgrade_packages(sudo: Option<&PathBuf>, run_type: RunType) -> Result<(), Error> { + let sudo = require_option(sudo)?; + print_separator("FreeBSD Packages"); + run_type.execute(sudo).args(&["/usr/sbin/pkg", "upgrade"]).check_run() +} + +pub fn audit_packages(sudo: &Option) -> Result<(), Error> { + if let Some(sudo) = sudo { + println!(); + Command::new(sudo) + .args(&["/usr/sbin/pkg", "audit", "-Fr"]) + .spawn() + .context(ErrorKind::ProcessExecution)? + .wait() + .context(ErrorKind::ProcessExecution)?; + } + Ok(()) +} diff --git a/src/steps/os/linux.rs b/src/steps/os/linux.rs new file mode 100644 index 00000000..660b2dd1 --- /dev/null +++ b/src/steps/os/linux.rs @@ -0,0 +1,295 @@ +use crate::error::{Error, ErrorKind}; +use crate::executor::RunType; +use crate::terminal::{print_separator, print_warning}; +use crate::utils::{require, require_option, which}; +use failure::ResultExt; +use std::fs; +use std::path::PathBuf; +use walkdir::WalkDir; + +#[derive(Copy, Clone, Debug)] +pub enum Distribution { + Arch, + CentOS, + Fedora, + Debian, + Ubuntu, + Gentoo, + OpenSuse, + Void, +} + +impl Distribution { + pub fn detect() -> Result { + let content = fs::read_to_string("/etc/os-release").context(ErrorKind::UnknownLinuxDistribution)?; + + if content.contains("Arch") | content.contains("Manjaro") | content.contains("Antergos") { + return Ok(Distribution::Arch); + } + + if content.contains("CentOS") || content.contains("Oracle Linux") { + return Ok(Distribution::CentOS); + } + + if content.contains("Fedora") { + return Ok(Distribution::Fedora); + } + + if content.contains("Ubuntu") { + return Ok(Distribution::Ubuntu); + } + + if content.contains("Debian") { + return Ok(Distribution::Debian); + } + + if content.contains("openSUSE") { + return Ok(Distribution::OpenSuse); + } + + if content.contains("void") { + return Ok(Distribution::Void); + } + + if PathBuf::from("/etc/gentoo-release").exists() { + return Ok(Distribution::Gentoo); + } + + Err(ErrorKind::UnknownLinuxDistribution)? + } + + #[must_use] + pub fn upgrade(self, sudo: &Option, cleanup: bool, run_type: RunType) -> Result<(), Error> { + print_separator("System update"); + + match self { + Distribution::Arch => upgrade_arch_linux(&sudo, cleanup, run_type), + Distribution::CentOS => upgrade_redhat(&sudo, run_type), + Distribution::Fedora => upgrade_fedora(&sudo, run_type), + Distribution::Ubuntu | Distribution::Debian => upgrade_debian(&sudo, cleanup, run_type), + Distribution::Gentoo => upgrade_gentoo(&sudo, run_type), + Distribution::OpenSuse => upgrade_opensuse(&sudo, run_type), + Distribution::Void => upgrade_void(&sudo, run_type), + } + } + + pub fn show_summary(self) { + if let Distribution::Arch = self { + show_pacnew(); + } + } +} + +pub fn show_pacnew() { + let mut iter = WalkDir::new("/etc") + .into_iter() + .filter_map(|e| e.ok()) + .filter(|f| { + f.path() + .extension() + .filter(|ext| ext == &"pacnew" || ext == &"pacsave") + .is_some() + }) + .peekable(); + + if iter.peek().is_some() { + println!("\nPacman backup configuration files found:"); + + for entry in iter { + println!("{}", entry.path().display()); + } + } +} + +fn upgrade_arch_linux(sudo: &Option, cleanup: bool, run_type: RunType) -> Result<(), Error> { + if let Some(yay) = which("yay") { + if let Some(python) = which("python") { + if python != PathBuf::from("/usr/bin/python") { + print_warning(format!( + "Python detected at {:?}, which is probably not the system Python. +It's dangerous to run yay since Python based AUR packages will be installed in the wrong location", + python + )); + return Err(ErrorKind::NotSystemPython)?; + } + } + run_type.execute(yay).check_run()?; + } else if let Some(sudo) = &sudo { + run_type.execute(&sudo).args(&["/usr/bin/pacman", "-Syu"]).check_run()?; + } else { + print_warning("No sudo or yay detected. Skipping system upgrade"); + } + + if cleanup { + if let Some(sudo) = &sudo { + run_type.execute(&sudo).args(&["/usr/bin/pacman", "-Scc"]).check_run()?; + } + } + + Ok(()) +} + +fn upgrade_redhat(sudo: &Option, run_type: RunType) -> Result<(), Error> { + if let Some(sudo) = &sudo { + run_type.execute(&sudo).args(&["/usr/bin/yum", "upgrade"]).check_run()?; + } else { + print_warning("No sudo detected. Skipping system upgrade"); + } + + Ok(()) +} + +fn upgrade_opensuse(sudo: &Option, run_type: RunType) -> Result<(), Error> { + if let Some(sudo) = &sudo { + run_type + .execute(&sudo) + .args(&["/usr/bin/zypper", "refresh"]) + .check_run()?; + + run_type + .execute(&sudo) + .args(&["/usr/bin/zypper", "dist-upgrade"]) + .check_run()?; + } else { + print_warning("No sudo detected. Skipping system upgrade"); + } + + Ok(()) +} + +fn upgrade_void(sudo: &Option, run_type: RunType) -> Result<(), Error> { + if let Some(sudo) = &sudo { + run_type + .execute(&sudo) + .args(&["/usr/bin/xbps-install", "-Su"]) + .check_run()?; + } else { + print_warning("No sudo detected. Skipping system upgrade"); + } + + Ok(()) +} + +fn upgrade_fedora(sudo: &Option, run_type: RunType) -> Result<(), Error> { + if let Some(sudo) = &sudo { + run_type.execute(&sudo).args(&["/usr/bin/dnf", "upgrade"]).check_run()?; + } else { + print_warning("No sudo detected. Skipping system upgrade"); + } + + Ok(()) +} + +fn upgrade_gentoo(sudo: &Option, run_type: RunType) -> Result<(), Error> { + if let Some(sudo) = &sudo { + if let Some(layman) = which("layman") { + run_type.execute(&sudo).arg(layman).args(&["-s", "ALL"]).check_run()?; + } + + println!("Syncing portage"); + run_type + .execute(&sudo) + .arg("/usr/bin/emerge") + .args(&["-q", "--sync"]) + .check_run()?; + + if let Some(eix_update) = which("eix-update") { + run_type.execute(&sudo).arg(eix_update).check_run()?; + } + + run_type + .execute(&sudo) + .arg("/usr/bin/emerge") + .args(&["-uDNa", "world"]) + .check_run()?; + } else { + print_warning("No sudo detected. Skipping system upgrade"); + } + + Ok(()) +} + +fn upgrade_debian(sudo: &Option, cleanup: bool, run_type: RunType) -> Result<(), Error> { + if let Some(sudo) = &sudo { + run_type.execute(&sudo).args(&["/usr/bin/apt", "update"]).check_run()?; + + run_type + .execute(&sudo) + .args(&["/usr/bin/apt", "dist-upgrade"]) + .check_run()?; + + if cleanup { + run_type.execute(&sudo).args(&["/usr/bin/apt", "clean"]).check_run()?; + + run_type + .execute(&sudo) + .args(&["/usr/bin/apt", "autoremove"]) + .check_run()?; + } + } else { + print_warning("No sudo detected. Skipping system upgrade"); + } + + Ok(()) +} + +pub fn run_needrestart(sudo: Option<&PathBuf>, run_type: RunType) -> Result<(), Error> { + let sudo = require_option(sudo)?; + let needrestart = require("needrestart")?; + + print_separator("Check for needed restarts"); + + run_type.execute(&sudo).arg(needrestart).check_run()?; + + Ok(()) +} + +#[must_use] +pub fn run_fwupdmgr(run_type: RunType) -> Result<(), Error> { + let fwupdmgr = require("fwupdmgr")?; + + print_separator("Firmware upgrades"); + + run_type.execute(&fwupdmgr).arg("refresh").check_run()?; + run_type.execute(&fwupdmgr).arg("get-updates").check_run() +} + +#[must_use] +pub fn flatpak_update(run_type: RunType) -> Result<(), Error> { + let flatpak = require("flatpak")?; + print_separator("Flatpak User Packages"); + + run_type + .execute(&flatpak) + .args(&["update", "--user", "-y"]) + .check_run()?; + run_type + .execute(&flatpak) + .args(&["update", "--system", "-y"]) + .check_run() +} + +#[must_use] +pub fn run_snap(sudo: Option<&PathBuf>, run_type: RunType) -> Result<(), Error> { + let sudo = require_option(sudo)?; + let snap = require("snap")?; + + if !PathBuf::from("/var/snapd.socket").exists() { + Err(ErrorKind::SkipStep)?; + } + print_separator("snap"); + + run_type + .execute(sudo) + .args(&[snap.to_str().unwrap(), "refresh"]) + .check_run() +} + +#[must_use] +pub fn run_etc_update(sudo: Option<&PathBuf>, run_type: RunType) -> Result<(), Error> { + let sudo = require_option(sudo)?; + let etc_update = require("etc_update")?; + print_separator("etc-update"); + + run_type.execute(sudo).arg(&etc_update.to_str().unwrap()).check_run() +} diff --git a/src/steps/os/macos.rs b/src/steps/os/macos.rs new file mode 100644 index 00000000..150e3c2d --- /dev/null +++ b/src/steps/os/macos.rs @@ -0,0 +1,13 @@ +use crate::error::Error; +use crate::executor::RunType; +use crate::terminal::print_separator; + +#[must_use] +pub fn upgrade_macos(run_type: RunType) -> Result<(), Error> { + print_separator("App Store"); + + run_type + .execute("softwareupdate") + .args(&["--install", "--all"]) + .check_run() +} diff --git a/src/steps/os/mod.rs b/src/steps/os/mod.rs new file mode 100644 index 00000000..70d59b1c --- /dev/null +++ b/src/steps/os/mod.rs @@ -0,0 +1,10 @@ +#[cfg(target_os = "freebsd")] +pub mod freebsd; +#[cfg(target_os = "linux")] +pub mod linux; +#[cfg(target_os = "macos")] +pub mod macos; +#[cfg(unix)] +pub mod unix; +#[cfg(target_os = "windows")] +pub mod windows; diff --git a/src/steps/os/unix.rs b/src/steps/os/unix.rs new file mode 100644 index 00000000..b54415d9 --- /dev/null +++ b/src/steps/os/unix.rs @@ -0,0 +1,83 @@ +use crate::error::Error; +use crate::executor::{CommandExt, RunType}; +use crate::terminal::print_separator; +use crate::utils::{require, PathExt}; +use directories::BaseDirs; +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; + +pub fn run_zplug(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let zsh = require("zsh")?; + + env::var("ZPLUG_HOME") + .map(PathBuf::from) + .unwrap_or_else(|_| base_dirs.home_dir().join("zplug")) + .require()?; + + let zshrc = env::var("ZDOTDIR") + .map(|p| Path::new(&p).join(".zshrc")) + .unwrap_or_else(|_| base_dirs.home_dir().join(".zshrc")) + .require()?; + + print_separator("zplug"); + + let cmd = format!("source {} && zplug update", zshrc.display()); + run_type.execute(zsh).args(&["-c", cmd.as_str()]).check_run() +} + +pub fn run_fisher(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let fish = require("fish")?; + base_dirs + .home_dir() + .join(".config/fish/functions/fisher.fish") + .require()?; + run_type + .execute(&fish) + .args(&["-c", "fisher self-update"]) + .check_run()?; + run_type.execute(&fish).args(&["-c", "fisher"]).check_run() +} + +#[must_use] +pub fn run_homebrew(cleanup: bool, run_type: RunType) -> Result<(), Error> { + let brew = require("brew")?; + print_separator("Brew"); + + run_type.execute(&brew).arg("update").check_run()?; + run_type.execute(&brew).arg("upgrade").check_run()?; + + let cask_upgrade_exists = Command::new(&brew) + .args(&["--repository", "buo/cask-upgrade"]) + .check_output() + .map(|p| Path::new(p.trim()).exists())?; + + if cask_upgrade_exists { + run_type.execute(&brew).args(&["cu", "-ay"]).check_run()?; + } else { + run_type.execute(&brew).args(&["cask", "upgrade"]).check_run()?; + } + + if cleanup { + run_type.execute(&brew).arg("cleanup").check_run()?; + } + + Ok(()) +} + +#[must_use] +pub fn run_nix(run_type: RunType) -> Result<(), Error> { + let nix = require("nix")?; + let nix_env = require("nix_env")?; + + print_separator("Nix"); + run_type.execute(&nix).arg("upgrade-nix").check_run()?; + run_type.execute(&nix_env).arg("--upgrade").check_run() +} + +pub fn run_pearl(run_type: RunType) -> Result<(), Error> { + let pearl = require("pearl")?; + print_separator("pearl"); + + run_type.execute(&pearl).arg("update").check_run() +} diff --git a/src/steps/os/windows.rs b/src/steps/os/windows.rs new file mode 100644 index 00000000..c9115ee3 --- /dev/null +++ b/src/steps/os/windows.rs @@ -0,0 +1,82 @@ +use crate::error::{Error, ErrorKind}; +use crate::executor::{CommandExt, RunType}; +use crate::terminal::{is_dumb, print_separator}; +use crate::utils::{require, require_option, which}; +use std::path::PathBuf; +use std::process::Command; + +pub fn run_chocolatey(run_type: RunType) -> Result<(), Error> { + let choco = require("choco")?; + + print_separator("Chocolatey"); + run_type.execute(&choco).args(&["upgrade", "all"]).check_run() +} + +pub fn run_scoop(run_type: RunType) -> Result<(), Error> { + let scoop = require("scoop")?; + + print_separator("Scoop"); + + run_type.execute(&scoop).args(&["update"]).check_run()?; + run_type.execute(&scoop).args(&["update", "*"]).check_run() +} + +pub struct Powershell { + path: Option, + profile: Option, +} + +impl Powershell { + /// Returns a powershell instance. + /// + /// If the powershell binary is not found, or the current terminal is dumb + /// then the instance of this struct will skip all the powershell steps. + pub fn new() -> Self { + let path = which("powershell").filter(|_| !is_dumb()); + + let profile = path.as_ref().and_then(|path| { + Command::new(path) + .args(&["-Command", "echo $profile"]) + .check_output() + .map(|output| PathBuf::from(output.trim())) + .ok() + }); + + Powershell { path, profile } + } + + pub fn has_command(powershell: &PathBuf, command: &str) -> bool { + || -> Result<(), Error> { + Command::new(&powershell) + .args(&["-Command", &format!("Get-Command {}", command)]) + .check_output()?; + Ok(()) + }() + .is_ok() + } + + pub fn profile(&self) -> Option<&PathBuf> { + self.profile.as_ref() + } + + pub fn update_modules(&self, run_type: RunType) -> Result<(), Error> { + let powershell = require_option(self.path.as_ref())?; + + print_separator("Powershell Modules Update"); + run_type.execute(&powershell).args(&["Update-Module", "-v"]).check_run() + } + + pub fn windows_update(&self, run_type: RunType) -> Result<(), Error> { + let powershell = require_option(self.path.as_ref())?; + + if !Self::has_command(&powershell, "Install-WindowsUpdate") { + Err(ErrorKind::SkipStep)?; + } + print_separator("Windows Update"); + + run_type + .execute(&powershell) + .args(&["-Command", "Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose"]) + .check_run() + } +} diff --git a/src/tmux.rs b/src/steps/tmux.rs similarity index 68% rename from src/tmux.rs rename to src/steps/tmux.rs index e1286cf1..b51e432e 100644 --- a/src/tmux.rs +++ b/src/steps/tmux.rs @@ -1,32 +1,24 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::which; -use super::utils::{Check, PathExt}; +use crate::error::{Error, ErrorKind}; +use crate::executor::RunType; +use crate::terminal::print_separator; +use crate::utils::{which, Check, PathExt}; use directories::BaseDirs; -use failure::Error; +use failure::ResultExt; use std::env; use std::io; use std::os::unix::process::CommandExt; use std::path::Path; use std::process::Command; -pub fn run_tpm(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(tpm) = base_dirs +pub fn run_tpm(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let tpm = base_dirs .home_dir() .join(".tmux/plugins/tpm/bin/update_plugins") - .if_exists() - { - terminal.print_separator("tmux plugins"); + .require()?; - let success = || -> Result<(), Error> { - Executor::new(&tpm, dry_run).arg("all").spawn()?.wait()?.check()?; - Ok(()) - }().is_ok(); + print_separator("tmux plugins"); - return Some(("tmux", success)); - } - - None + run_type.execute(&tpm).arg("all").check_run() } fn has_session(tmux: &Path, session_name: &str) -> Result { @@ -40,8 +32,10 @@ fn has_session(tmux: &Path, session_name: &str) -> Result { fn run_in_session(tmux: &Path, command: &str) -> Result<(), Error> { Command::new(tmux) .args(&["new-window", "-a", "-t", "topgrade:1", command]) - .spawn()? - .wait()? + .spawn() + .context(ErrorKind::ProcessExecution)? + .wait() + .context(ErrorKind::ProcessExecution)? .check()?; Ok(()) @@ -70,7 +64,8 @@ pub fn run_in_tmux() -> ! { "set", "remain-on-exit", "on", - ]).exec(); + ]) + .exec(); panic!("{:?}", err); } diff --git a/src/vim.rs b/src/steps/vim.rs similarity index 53% rename from src/vim.rs rename to src/steps/vim.rs index 500f9f86..31ac13d0 100644 --- a/src/vim.rs +++ b/src/steps/vim.rs @@ -1,8 +1,8 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::{which, Check, PathExt}; +use crate::error::Error; +use crate::executor::RunType; +use crate::terminal::print_separator; +use crate::utils::{require, require_option, PathExt}; use directories::BaseDirs; -use failure; use std::fs; use std::path::PathBuf; @@ -54,13 +54,9 @@ fn nvimrc(base_dirs: &BaseDirs) -> Option { } #[must_use] -fn upgrade( - vim: &PathBuf, - vimrc: &PathBuf, - plugin_framework: PluginFramework, - dry_run: bool, -) -> Result<(), failure::Error> { - Executor::new(&vim, dry_run) +fn upgrade(vim: &PathBuf, vimrc: &PathBuf, plugin_framework: PluginFramework, run_type: RunType) -> Result<(), Error> { + run_type + .execute(&vim) .args(&[ "-N", "-u", @@ -72,9 +68,8 @@ fn upgrade( "-e", "-s", "-V1", - ]).spawn()? - .wait()? - .check()?; + ]) + .check_run()?; println!(); @@ -82,31 +77,21 @@ fn upgrade( } #[must_use] -pub fn upgrade_vim(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(vim) = which("vim") { - if let Some(vimrc) = vimrc(&base_dirs) { - if let Some(plugin_framework) = PluginFramework::detect(&vimrc) { - terminal.print_separator(&format!("Vim ({:?})", plugin_framework)); - let success = upgrade(&vim, &vimrc, plugin_framework, dry_run).is_ok(); - return Some(("vim", success)); - } - } - } +pub fn upgrade_vim(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let vim = require("vim")?; + let vimrc = require_option(vimrc(&base_dirs))?; + let plugin_framework = require_option(PluginFramework::detect(&vimrc))?; - None + print_separator(&format!("Vim ({:?})", plugin_framework)); + upgrade(&vim, &vimrc, plugin_framework, run_type) } #[must_use] -pub fn upgrade_neovim(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(nvim) = which("nvim") { - if let Some(nvimrc) = nvimrc(&base_dirs) { - if let Some(plugin_framework) = PluginFramework::detect(&nvimrc) { - terminal.print_separator(&format!("Neovim ({:?})", plugin_framework)); - let success = upgrade(&nvim, &nvimrc, plugin_framework, dry_run).is_ok(); - return Some(("Neovim", success)); - } - } - } +pub fn upgrade_neovim(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { + let nvim = require("nvim")?; + let nvimrc = require_option(nvimrc(&base_dirs))?; + let plugin_framework = require_option(PluginFramework::detect(&nvimrc))?; - None + print_separator(&format!("Neovim ({:?})", plugin_framework)); + upgrade(&nvim, &nvimrc, plugin_framework, run_type) } diff --git a/src/terminal.rs b/src/terminal.rs index c4ecae2e..1e9dca34 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,95 +1,140 @@ -use console::Term; +use console::{style, Term}; +use lazy_static::lazy_static; use std::cmp::{max, min}; use std::io::{self, Write}; -use term_size; -use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; +use std::sync::Mutex; -pub struct Terminal { - width: Option, - stdout: StandardStream, +lazy_static! { + static ref TERMINAL: Mutex = Mutex::new(Terminal::new()); +} + +struct Terminal { + width: Option, + term: Term, } impl Terminal { - pub fn new() -> Self { + fn new() -> Self { + let term = Term::stdout(); Self { - width: term_size::dimensions().map(|(w, _)| w), - stdout: StandardStream::stdout(ColorChoice::Auto), + width: term.size_checked().map(|(_, w)| w), + term, } } - pub fn print_separator>(&mut self, message: P) { + fn print_separator>(&mut self, message: P) { let message = message.as_ref(); match self.width { Some(width) => { - let _ = self - .stdout - .set_color(ColorSpec::new().set_fg(Some(Color::White)).set_bold(true)); - let _ = writeln!( - &mut self.stdout, - "\n―― {} {:―^border$}", - message, - "", - border = max(2, min(80, width as usize) - 3 - message.len()) - ); - let _ = self.stdout.reset(); - let _ = self.stdout.flush(); + self.term + .write_fmt(format_args!( + "{}\n", + style(format_args!( + "\n―― {} {:―^border$}", + message, + "", + border = max( + 2, + min(80, width as usize) + .checked_sub(3) + .and_then(|e| e.checked_sub(message.len())) + .unwrap_or(0) + ) + )) + .bold() + )) + .ok(); } None => { - let _ = writeln!(&mut self.stdout, "―― {} ――", message); + self.term.write_fmt(format_args!("―― {} ――\n", message)).ok(); } } } #[allow(dead_code)] - pub fn print_warning>(&mut self, message: P) { + fn print_warning>(&mut self, message: P) { let message = message.as_ref(); - - let _ = self - .stdout - .set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true)); - let _ = writeln!(&mut self.stdout, "{}", message); - let _ = self.stdout.reset(); - let _ = self.stdout.flush(); + self.term + .write_fmt(format_args!("{}\n", style(message).yellow().bold())) + .ok(); } - pub fn print_result>(&mut self, key: P, succeeded: bool) { + fn print_result>(&mut self, key: P, succeeded: bool) { let key = key.as_ref(); - let _ = write!(&mut self.stdout, "{}: ", key); - let _ = self.stdout.set_color( - ColorSpec::new() - .set_fg(Some(if succeeded { Color::Green } else { Color::Red })) - .set_bold(true), - ); - - let _ = writeln!(&mut self.stdout, "{}", if succeeded { "OK" } else { "FAILED" }); - - let _ = self.stdout.reset(); - let _ = self.stdout.flush(); + self.term + .write_fmt(format_args!( + "{}: {}\n", + key, + if succeeded { + style("OK").bold().green() + } else { + style("FAILED").bold().red() + } + )) + .ok(); } - pub fn should_retry(&mut self, running: bool) -> Result { + fn should_retry(&mut self, interrupted: bool) -> Result { if self.width.is_none() { return Ok(false); } - println!(); - loop { - let _ = self - .stdout - .set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true)); - let _ = write!(&mut self.stdout, "Retry? [y/N] "); - if !running { - write!(&mut self.stdout, "(Press Ctrl+C again to stop Topgrade) "); - } - let _ = self.stdout.reset(); - let _ = self.stdout.flush(); + self.term + .write_fmt(format_args!( + "\n{}", + style(format!( + "Retry? [y/N] {}", + if interrupted { + "(Press Ctrl+C again to stop Topgrade) " + } else { + "" + } + )) + .yellow() + .bold() + )) + .ok(); - match Term::stdout().read_char()? { - 'y' | 'Y' => return Ok(true), - 'n' | 'N' | '\r' | '\n' => return Ok(false), + let answer = loop { + match self.term.read_char()? { + 'y' | 'Y' => break Ok(true), + 'n' | 'N' | '\r' | '\n' => break Ok(false), _ => (), } - } + }; + + self.term.write_str("\n").ok(); + + answer } } + +impl Default for Terminal { + fn default() -> Self { + Self::new() + } +} + +pub fn should_retry(interrupted: bool) -> Result { + TERMINAL.lock().unwrap().should_retry(interrupted) +} + +pub fn print_separator>(message: P) { + TERMINAL.lock().unwrap().print_separator(message) +} + +#[allow(dead_code)] +pub fn print_warning>(message: P) { + TERMINAL.lock().unwrap().print_warning(message) +} + +pub fn print_result>(key: P, succeeded: bool) { + TERMINAL.lock().unwrap().print_result(key, succeeded) +} + +#[cfg(windows)] +/// Tells whether the terminal is dumb. +pub fn is_dumb() -> bool { + TERMINAL.lock().unwrap().width.is_none() +} diff --git a/src/unix.rs b/src/unix.rs deleted file mode 100644 index c86f5158..00000000 --- a/src/unix.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::{which, Check}; -use directories::BaseDirs; -use failure::Error; - -pub fn run_zplug(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(zsh) = which("zsh") { - if base_dirs.home_dir().join(".zplug").exists() { - terminal.print_separator("zplug"); - - let success = || -> Result<(), Error> { - Executor::new(zsh, dry_run) - .args(&["-c", "source ~/.zshrc && zplug update"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("zplug", success)); - } - } - - None -} - -pub fn run_fisher(base_dirs: &BaseDirs, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(fish) = which("fish") { - if base_dirs.home_dir().join(".config/fish/functions/fisher.fish").exists() { - terminal.print_separator("fisher"); - - let success = || -> Result<(), Error> { - Executor::new(&fish, dry_run) - .args(&["-c", "fisher self-update"]) - .spawn()? - .wait()? - .check()?; - Executor::new(&fish, dry_run) - .args(&["-c", "fisher"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("fisher", success)); - } - } - - None -} - -#[must_use] -pub fn run_homebrew(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(brew) = which("brew") { - terminal.print_separator("Brew"); - - let inner = || -> Result<(), Error> { - Executor::new(&brew, dry_run).arg("update").spawn()?.wait()?.check()?; - Executor::new(&brew, dry_run).arg("upgrade").spawn()?.wait()?.check()?; - Ok(()) - }; - - return Some(("Brew", inner().is_ok())); - } - - None -} diff --git a/src/utils.rs b/src/utils.rs index 16efdba8..ceaf3842 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,13 +1,10 @@ -use failure::Error; +use super::error::{Error, ErrorKind}; +use log::{debug, error}; use std::ffi::OsStr; -use std::fmt::Debug; -use std::path::{Path, PathBuf}; +use std::fmt::{self, Debug}; +use std::path::{Component, Path, PathBuf}; use std::process::{ExitStatus, Output}; -use which as which_mod; - -#[derive(Fail, Debug)] -#[fail(display = "Process failed")] -pub struct ProcessFailed; +use which_crate; pub trait Check { fn check(self) -> Result<(), Error>; @@ -18,7 +15,7 @@ impl Check for ExitStatus { if self.success() { Ok(()) } else { - Err(Error::from(ProcessFailed {})) + Err(ErrorKind::ProcessFailed(self))? } } } @@ -35,6 +32,9 @@ where { fn if_exists(self) -> Option; fn is_descendant_of(&self, ancestor: &Path) -> bool; + + /// Returns the path if it exists or ErrorKind::SkipStep otherwise + fn require(self) -> Result; } impl PathExt for PathBuf { @@ -49,17 +49,25 @@ impl PathExt for PathBuf { fn is_descendant_of(&self, ancestor: &Path) -> bool { self.iter().zip(ancestor.iter()).all(|(a, b)| a == b) } + + fn require(self) -> Result { + if self.exists() { + Ok(self) + } else { + Err(ErrorKind::SkipStep)? + } + } } pub fn which + Debug>(binary_name: T) -> Option { - match which_mod::which(&binary_name) { + match which_crate::which(&binary_name) { Ok(path) => { debug!("Detected {:?} as {:?}", &path, &binary_name); Some(path) } Err(e) => { match e.kind() { - which_mod::ErrorKind::CannotFindBinaryPath => { + which_crate::ErrorKind::CannotFindBinaryPath => { debug!("Cannot find {:?}", &binary_name); } _ => { @@ -71,3 +79,113 @@ pub fn which + Debug>(binary_name: T) -> Option { } } } + +/// `std::fmt::Display` implementation for `std::path::Path`. +/// +/// This struct differs from `std::path::Display` in that in Windows it takes care of printing backslashes +/// instead of slashes and don't print the `\\?` prefix in long paths. +pub struct HumanizedPath<'a> { + path: &'a Path, +} + +impl<'a> From<&'a Path> for HumanizedPath<'a> { + fn from(path: &'a Path) -> Self { + Self { path } + } +} + +impl<'a> fmt::Display for HumanizedPath<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if cfg!(windows) { + let mut iterator = self.path.components().peekable(); + + while let Some(component) = iterator.next() { + let mut print_seperator = iterator.peek().is_some(); + + match &component { + Component::Normal(c) if *c == "?" => { + print_seperator = false; + } + Component::RootDir | Component::CurDir => { + print_seperator = false; + } + Component::ParentDir => { + write!(f, "..")?; + } + Component::Prefix(p) => { + write!(f, "{}", p.as_os_str().to_string_lossy())?; + print_seperator = true; + } + Component::Normal(c) => { + write!(f, "{}", c.to_string_lossy())?; + } + }; + + if print_seperator { + write!(f, "{}", std::path::MAIN_SEPARATOR)?; + } + } + } else { + write!(f, "{}", self.path.display())?; + } + + Ok(()) + } +} + +#[cfg(test)] +#[cfg(windows)] +mod tests { + use super::*; + + fn humanize>(path: P) -> String { + format!("{}", HumanizedPath::from(path.as_ref())) + } + + #[test] + fn test_just_drive() { + assert_eq!("C:\\", humanize("C:\\")); + } + + #[test] + fn test_path() { + assert_eq!("C:\\hi", humanize("C:\\hi")); + } + + #[test] + fn test_unc() { + assert_eq!("\\\\server\\share\\", humanize("\\\\server\\share")); + } + + #[test] + fn test_long_path() { + assert_eq!("C:\\hi", humanize("//?/C:/hi")); + } +} + +pub fn require + Debug>(binary_name: T) -> Result { + match which_crate::which(&binary_name) { + Ok(path) => { + debug!("Detected {:?} as {:?}", &path, &binary_name); + Ok(path) + } + Err(e) => match e.kind() { + which_crate::ErrorKind::CannotFindBinaryPath => { + debug!("Cannot find {:?}", &binary_name); + Err(ErrorKind::SkipStep)? + } + _ => { + panic!("Detecting {:?} failed: {}", &binary_name, e); + } + }, + } +} + +#[allow(dead_code)] +pub fn require_option(option: Option) -> Result { + if let Some(value) = option { + Ok(value) + } else { + Err(ErrorKind::SkipStep)? + } +} diff --git a/src/windows.rs b/src/windows.rs deleted file mode 100644 index 4dd7e32e..00000000 --- a/src/windows.rs +++ /dev/null @@ -1,133 +0,0 @@ -use super::executor::Executor; -use super::terminal::Terminal; -use super::utils::{self, which, Check}; -use failure; -use std::path::PathBuf; -use std::process::Command; - -#[must_use] -pub fn run_chocolatey(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(choco) = utils::which("choco") { - terminal.print_separator("Chocolatey"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&choco, dry_run) - .args(&["upgrade", "all"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Chocolatey", success)); - } - - None -} - -#[must_use] -pub fn run_scoop(terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(scoop) = utils::which("scoop") { - terminal.print_separator("Scoop"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&scoop, dry_run) - .args(&["update"]) - .spawn()? - .wait()? - .check()?; - Executor::new(&scoop, dry_run) - .args(&["update", "*"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Scoop", success)); - } - - None -} - -pub struct Powershell { - path: Option, -} - -impl Powershell { - pub fn new() -> Self { - Powershell { - path: which("powershell"), - } - } - - pub fn has_command(powershell: &PathBuf, command: &str) -> bool { - || -> Result<(), failure::Error> { - Command::new(&powershell) - .args(&["-Command", &format!("Get-Command {}", command)]) - .output()? - .check()?; - Ok(()) - }().is_ok() - } - - pub fn profile(&self) -> Option { - if let Some(powershell) = &self.path { - let result = || -> Result { - let output = Command::new(powershell).args(&["-Command", "echo $profile"]).output()?; - output.status.check()?; - Ok(PathBuf::from( - String::from_utf8_lossy(&output.stdout).trim().to_string(), - )) - }(); - - match result { - Err(e) => error!("Error getting Powershell profile: {}", e), - Ok(path) => return Some(path), - } - } - None - } - - #[must_use] - pub fn update_modules(&self, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(powershell) = &self.path { - terminal.print_separator("Powershell Modules Update"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&powershell, dry_run) - .arg("Update-Module") - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Powershell Modules Update", success)); - } - - None - } - - #[must_use] - pub fn windows_update(&self, terminal: &mut Terminal, dry_run: bool) -> Option<(&'static str, bool)> { - if let Some(powershell) = &self.path { - if Self::has_command(&powershell, "Install-WindowsUpdate") { - terminal.print_separator("Windows Update"); - - let success = || -> Result<(), failure::Error> { - Executor::new(&powershell, dry_run) - .args(&["-Command", "Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose"]) - .spawn()? - .wait()? - .check()?; - Ok(()) - }().is_ok(); - - return Some(("Windows Update", success)); - } - } - - None - } -}