diff --git a/Cargo.lock b/Cargo.lock index 555c2aa5..267b9263 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,6 +74,41 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "clicolors-control" +version = "0.2.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)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "console" +version = "0.6.2" +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)", + "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 = "directories" version = "1.0.2" @@ -115,6 +150,20 @@ dependencies = [ "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "humantime" version = "1.1.1" @@ -132,6 +181,11 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazy_static" version = "1.1.0" @@ -145,6 +199,15 @@ name = "libc" version = "0.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lock_api" +version = "0.1.4" +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)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.4.5" @@ -163,6 +226,47 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nix" +version = "0.11.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)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "owning_ref" +version = "0.3.3" +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)", +] + +[[package]] +name = "parking_lot" +version = "0.6.4" +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)", +] + +[[package]] +name = "parking_lot_core" +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)", + "rand 0.5.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)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.20" @@ -184,6 +288,31 @@ dependencies = [ "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.5.5" +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)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.2" +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)", +] + +[[package]] +name = "rand_core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "redox_syscall" version = "0.1.40" @@ -222,6 +351,14 @@ name = "rustc-demangle" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "same-file" version = "1.0.3" @@ -230,6 +367,24 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "1.0.79" @@ -250,6 +405,19 @@ name = "shellexpand" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "smallvec" +version = "0.6.5" +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 = "strsim" version = "0.7.0" @@ -333,6 +501,14 @@ dependencies = [ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +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)", +] + [[package]] name = "textwrap" version = "0.10.0" @@ -361,11 +537,14 @@ dependencies = [ name = "topgrade" version = "0.16.0" dependencies = [ + "console 0.6.2 (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)", "shellexpand 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -392,6 +571,14 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" version = "1.0.1" @@ -407,6 +594,11 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.2.5" @@ -482,28 +674,48 @@ dependencies = [ "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 clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum clicolors-control 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f84dec9bc083ce2503908cd305af98bd363da6f54bf8d4bf0ac14ee749ad5d1" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum console 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd48adf136733979b49e15bc3b4c43cc0d3c85ece7bd08e6daa414c6fcb13e6" "checksum 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 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 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 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 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 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 scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" "checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" "checksum 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 stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ca85f2c9a5a1e2d5ac686fc0be48e40f8ad803f5bbe31f692ff71eb2dd8aad45" "checksum structopt-derive 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "1383e5db585da799a5c4acc496c5c868e18bf82e658c00c75cc91038fa26b55f" @@ -513,15 +725,18 @@ dependencies = [ "checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" "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 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 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 winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/Cargo.toml b/Cargo.toml index 8bb25870..f5dee46b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,11 @@ env_logger = "0.5.13" term_size = "0.3.1" termcolor = "1.0.4" walkdir = "2.2.5" +console = "0.6.2" + +[target.'cfg(unix)'.dependencies] +nix = "0.11" +lazy_static = "1.1.0" [profile.release] lto = true diff --git a/src/ctrlc/mod.rs b/src/ctrlc/mod.rs new file mode 100644 index 00000000..25cf5bb3 --- /dev/null +++ b/src/ctrlc/mod.rs @@ -0,0 +1,9 @@ +#[cfg(unix)] +mod unix; +#[cfg(unix)] +pub use self::unix::*; + +#[cfg(windows)] +mod windows; +#[cfg(windows)] +pub use self::windows::*; diff --git a/src/ctrlc/unix.rs b/src/ctrlc/unix.rs new file mode 100644 index 00000000..329f807d --- /dev/null +++ b/src/ctrlc/unix.rs @@ -0,0 +1,29 @@ +use nix::sys::signal; +use std::sync::atomic::{AtomicBool, Ordering}; + +lazy_static! { + static ref RUNNING: AtomicBool = AtomicBool::new(true); +} + +pub fn running() -> bool { + RUNNING.load(Ordering::SeqCst) +} + +pub fn set_running(value: bool) { + RUNNING.store(value, Ordering::SeqCst) +} + +extern "C" fn handle_sigint(_: i32) { + set_running(false); +} + +pub fn set_handler() { + let sig_action = signal::SigAction::new( + signal::SigHandler::Handler(handle_sigint), + signal::SaFlags::empty(), + signal::SigSet::empty(), + ); + unsafe { + signal::sigaction(signal::SIGINT, &sig_action).unwrap(); + } +} diff --git a/src/ctrlc/windows.rs b/src/ctrlc/windows.rs new file mode 100644 index 00000000..83f9d380 --- /dev/null +++ b/src/ctrlc/windows.rs @@ -0,0 +1,7 @@ +pub fn running() -> bool { + true +} + +pub fn set_running(_value: bool) {} + +pub fn set_handler() {} diff --git a/src/main.rs b/src/main.rs index 7e017e9f..dd9c635b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,13 @@ 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; @@ -29,6 +35,7 @@ mod unix; mod windows; mod config; +mod ctrlc; mod executor; mod generic; mod git; @@ -45,6 +52,7 @@ use self::terminal::Terminal; use failure::Error; use std::borrow::Cow; use std::env; +use std::io::ErrorKind; use std::process::exit; use structopt::StructOpt; @@ -56,24 +64,48 @@ struct StepFailed; #[fail(display = "Cannot find the user base directories")] struct NoBaseDirectories; -fn execute<'a, F, M>(func: F, terminal: &mut Terminal) -> Option<(M, bool)> +#[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> where M: Into>, F: Fn(&mut Terminal) -> Option<(M, bool)>, { - while let Some((key, success)) = func(terminal) { + while let Some((key, success)) = func(&mut execution_context.terminal) { if success { - return Some((key, success)); + return Ok(Some((key, success))); } - if !terminal.should_retry() { - return Some((key, success)); + 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) + } + })?; + + if !should_retry { + return Ok(Some((key, success))); } } - None + + Ok(None) } fn run() -> Result<(), Error> { + ctrlc::set_handler(); + let opt = config::Opt::from_args(); if opt.run_in_tmux && env::var("TMUX").is_err() { @@ -87,7 +119,11 @@ fn run() -> Result<(), Error> { let base_dirs = directories::BaseDirs::new().ok_or(NoBaseDirectories)?; let git = Git::new(); let mut git_repos = Repositories::new(&git); - let mut terminal = Terminal::new(); + + let mut execution_context = ExecutionContext { + terminal: Terminal::new(), + }; + let config = Config::read(&base_dirs)?; let mut report = Report::new(); @@ -96,7 +132,7 @@ fn run() -> Result<(), Error> { if let Some(commands) = config.pre_commands() { for (name, command) in commands { - generic::run_custom_command(&name, &command, &mut terminal, opt.dry_run)?; + generic::run_custom_command(&name, &command, &mut execution_context.terminal, opt.dry_run)?; } } @@ -106,8 +142,8 @@ fn run() -> Result<(), Error> { #[cfg(windows)] report.push_result(execute( |terminal| powershell.update_modules(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); #[cfg(target_os = "linux")] let distribution = linux::Distribution::detect(); @@ -119,8 +155,8 @@ fn run() -> Result<(), Error> { Ok(distribution) => { report.push_result(execute( |terminal| distribution.upgrade(&sudo, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } Err(e) => { println!("Error detecting current distribution: {}", e); @@ -128,22 +164,22 @@ fn run() -> Result<(), Error> { } report.push_result(execute( |terminal| linux::run_etc_update(&sudo, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } } #[cfg(windows)] report.push_result(execute( |terminal| windows::run_chocolatey(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); #[cfg(unix)] report.push_result(execute( |terminal| unix::run_homebrew(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); if !opt.no_emacs { git_repos.insert(base_dirs.home_dir().join(".emacs.d")); @@ -178,66 +214,66 @@ fn run() -> Result<(), Error> { for repo in git_repos.repositories() { report.push_result(execute( |terminal| git.pull(&repo, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } #[cfg(unix)] { report.push_result(execute( |terminal| unix::run_zplug(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| unix::run_fisher(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| tmux::run_tpm(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } report.push_result(execute( |terminal| generic::run_rustup(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| generic::run_cargo_update(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); if !opt.no_emacs { report.push_result(execute( |terminal| generic::run_emacs(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } report.push_result(execute( |terminal| generic::run_opam_update(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| vim::upgrade_vim(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| vim::upgrade_neovim(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| node::run_npm_upgrade(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| generic::run_composer_update(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| node::yarn_global_update(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); #[cfg( not( @@ -251,27 +287,27 @@ fn run() -> Result<(), Error> { )] report.push_result(execute( |terminal| generic::run_apm(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| generic::run_gem(&base_dirs, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); #[cfg(target_os = "linux")] { report.push_result(execute( |terminal| linux::flatpak_user_update(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| linux::flatpak_global_update(&sudo, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| linux::run_snap(&sudo, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } if let Some(commands) = config.commands() { @@ -283,8 +319,8 @@ fn run() -> Result<(), Error> { generic::run_custom_command(&name, &command, terminal, opt.dry_run).is_ok(), )) }, - &mut terminal, - )); + &mut execution_context, + )?); } } @@ -292,12 +328,12 @@ fn run() -> Result<(), Error> { { report.push_result(execute( |terminal| linux::run_fwupdmgr(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); report.push_result(execute( |terminal| linux::run_needrestart(&sudo, terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } #[cfg(target_os = "macos")] @@ -305,8 +341,8 @@ fn run() -> Result<(), Error> { if !opt.no_system { report.push_result(execute( |terminal| macos::upgrade_macos(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } } @@ -315,16 +351,16 @@ fn run() -> Result<(), Error> { if !opt.no_system { report.push_result(execute( |terminal| powershell.windows_update(terminal, opt.dry_run), - &mut terminal, - )); + &mut execution_context, + )?); } } if !report.data().is_empty() { - terminal.print_separator("Summary"); + execution_context.terminal.print_separator("Summary"); for (key, succeeded) in report.data() { - terminal.print_result(key, *succeeded); + execution_context.terminal.print_result(key, *succeeded); } #[cfg(target_os = "linux")] @@ -348,10 +384,14 @@ fn main() { exit(0); } Err(error) => { - match error.downcast::() { + match error + .downcast::() + .map(|_| ()) + .or_else(|error| error.downcast::().map(|_| ())) + { Ok(_) => (), Err(error) => println!("ERROR: {}", error), - }; + } exit(1); } } diff --git a/src/terminal.rs b/src/terminal.rs index bdd0b42f..9a2ff41d 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,5 +1,6 @@ +use console::Term; use std::cmp::{max, min}; -use std::io::{stdin, Write}; +use std::io::{self, Write}; use term_size; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; @@ -67,29 +68,27 @@ impl Terminal { let _ = self.stdout.flush(); } - pub fn should_retry(&mut self) -> bool { + pub fn should_retry(&mut self, running: bool) -> Result { if self.width.is_none() { - return false; + return Ok(false); } + println!(); loop { - let mut result = String::new(); - 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(); - if stdin().read_line(&mut result).is_ok() { - match result.as_str().trim() { - "y" | "Y" => return true, - "n" | "N" | "" => return false, - _ => (), - } - } else { - return false; + match Term::stdout().read_char()? { + 'y' | 'Y' => return Ok(true), + 'n' | 'N' | '\n' => return Ok(false), + _ => (), } } }