diff --git a/Cargo.lock b/Cargo.lock index f5b70fa..3d43bb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -13,18 +13,28 @@ name = "anyhow" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "arc-swap" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.1.0" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -34,13 +44,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossterm" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossterm_winapi 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossterm_winapi" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (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.2.1 (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 = "heck" version = "0.3.1" @@ -51,12 +106,30 @@ dependencies = [ [[package]] name = "homer" -version = "0.2.0" +version = "0.2.1" dependencies = [ "anyhow 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "crossterm 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +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 = "lazy_static" version = "1.4.0" @@ -67,6 +140,83 @@ name = "libc" version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "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.4 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (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.34 (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.34 (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 = "net2" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-error" version = "1.0.2" @@ -107,6 +257,45 @@ dependencies = [ "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "signal-hook" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "signal-hook-registry" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arc-swap 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (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 = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.8.0" @@ -189,13 +378,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.7" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -206,19 +405,50 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "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)", +] + [metadata] "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum anyhow 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" +"checksum arc-swap 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum crossterm 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2a880035bfe4707e344da9acf50cc94d003fe337f50afd94c8722c1bb4e0a933" +"checksum crossterm_winapi 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "057b7146d02fb50175fd7dbe5158f6097f33d02831f43b4ee8ae4ddf67b68f5c" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)" = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" +"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" +"checksum parking_lot_core 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" "checksum proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" "checksum proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" "checksum proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" "checksum quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +"checksum signal-hook 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0893246f276ba1aac4983fb8711dad108e2886fd76bf618a382ab4e30e5bec" +"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" "checksum structopt-derive 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" @@ -230,6 +460,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"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-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/Cargo.toml b/Cargo.toml index b41820c..2fb0f57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "homer" -version = "0.2.0" +version = "0.2.1" authors = ["Christian Mutti "] edition = "2018" [dependencies] structopt = "0.3.14" anyhow = "1.0.28" +crossterm = "0.17.4" diff --git a/README.md b/README.md index ded908d..57ea42c 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ An action plan will always be shown, and then the user can choose to accept the or reject them (you can pass the `--force` flag to auto-accept the prompt). ``` -homer 0.2.0 +homer 0.2.1 "Doh!" A CLI for managing your dotfiles! USAGE: @@ -75,9 +75,9 @@ FLAGS: OPTIONS: -i, --input Directory containing files to link into user's home directory [default: ./home] - -o, --output Directory the files will be linked to, defaults to $HOME + -o, --output Directory the files will be linked to, defaults to $HOME [env: HOME] --scripts Directory containing scripts that will be run after the plan is completed. If force flag - is passed, no confirmation prompt will be shown [default: ./scripts] + is passed, no confirmation prompt will be shown ``` ### This could be a bash script!!1! diff --git a/__test__/not_folder/not_folder b/__test__/not_folder/not_folder new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs index 4cd6603..013129f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,12 @@ -use std::fmt::Display; use std::io::Write; use std::path::PathBuf; use std::process::Command; -use std::{fs, io, os::unix, process}; - -use structopt::StructOpt; +use std::{fs, io, os::unix}; use anyhow::{anyhow, Context, Result}; +use crossterm::execute; +use crossterm::style::{Attribute, Color, Print, SetAttribute, SetForegroundColor}; +use structopt::StructOpt; /// "Doh!" A CLI for managing your dotfiles! #[derive(StructOpt)] @@ -23,8 +23,8 @@ struct Opt { /// Directory containing scripts that will be run after the plan is completed. /// If force flag is passed, no confirmation prompt will be shown. - #[structopt(long, parse(from_os_str), default_value = "./scripts")] - scripts: PathBuf, + #[structopt(long, parse(from_os_str))] + scripts: Option, /// Directory containing files to link into user's home directory. #[structopt(short, long, parse(from_os_str), default_value = "./home")] @@ -35,18 +35,16 @@ struct Opt { output: PathBuf, } -fn main() { +fn main() -> Result<()> { let opt = Opt::from_args(); - if let Err(e) = run_linking(opt.input, opt.output, !opt.no_backup, opt.force) { - eprintln!("{}", e); - process::exit(1); - } + run_linking(opt.input, opt.output, !opt.no_backup, opt.force)?; - if let Err(e) = run_scripts(opt.scripts, opt.force) { - eprintln!("{}", e); - process::exit(1); + if let Some(scripts) = opt.scripts { + run_scripts(scripts, opt.force)?; } + + Ok(()) } /// Create and execute action plan for the linking process. @@ -67,8 +65,7 @@ fn run_linking(input: PathBuf, output: PathBuf, backup: bool, force: bool) -> Re } // Show the plan to the user, this substitute a verbose option, as it's always shown. - println!("The following actions will be performed: \n"); - plan.show(); + plan.show()?; if !force { // User was prompted, but did not accept the plan. @@ -105,9 +102,21 @@ fn run_scripts(path: PathBuf, force: bool) -> Result<()> { return Ok(()); } - println!("The following scripts will execute: \n"); + // Skip one line after the linking output. + println!(); for script in &scripts { - println!("\t {:?}", script) + // Show scripts that will execute, formatted. + execute!( + io::stdout(), + SetForegroundColor(Color::Green), + SetAttribute(Attribute::Bold), + Print("- run: "), + SetAttribute(Attribute::Reset), + SetForegroundColor(Color::Green), + Print(format!("{}", script.display())), + Print("\n"), + SetForegroundColor(Color::Reset), + )?; } if !force { @@ -143,8 +152,14 @@ fn canonicalize_dir(path: PathBuf) -> Result { /// Prompt user with a confirmation message and wait for the response. /// The result will be `true` if the user accepts the prompt. fn prompt_user() -> Result { - print!("\nPerform these actions? (y/N) "); - io::stdout().flush()?; + execute!( + io::stdout(), + Print("\n"), + Print("Perform these actions? "), + SetAttribute(Attribute::Dim), + Print("(y/N) "), + SetAttribute(Attribute::Reset), + )?; let mut input = String::new(); io::stdin().read_line(&mut input)?; @@ -197,12 +212,7 @@ impl Plan { for entry in entries { let entry = entry?; - let dest = dest.join( - entry - .path() - .strip_prefix(path) - .expect("Path to be root of file"), - ); + let dest = dest.join(entry.path().strip_prefix(path)?); children.push(Plan::new(&entry.path(), &dest, backup)?); } @@ -213,11 +223,10 @@ impl Plan { // When dealing with files, they will be equal if their `path`s canonicalized // are equal, meaning that `dest` is a link to `path`. - let file_equality = dest.exists() & path.is_file() - && path.canonicalize().expect("path is always valid") - == dest.canonicalize().expect("dest is always valid"); + let file_equality = + dest.exists() & path.is_file() && path.canonicalize()? == dest.canonicalize()?; - // If their equal, no action is needed. + // If they're equal, no action is needed. if dir_equality || file_equality { return Ok(Plan::Noop { path: path.into(), @@ -236,28 +245,20 @@ impl Plan { /// Check if an action plan is empty, this is done by checking if the plan is `Plan::Noop`, /// and all it's children are also `empty`. - fn is_empty(self: &Self) -> bool { + fn is_empty(&self) -> bool { match self { Plan::Noop { children, .. } => children.iter().all(Plan::is_empty), _ => false, } } - /// Show the plan, recursing and displaying all it's children aswell. - fn show(self: &Self) { - match self { - Plan::Noop { children, .. } => children.iter().for_each(Plan::show), - _ => println!("{}", self), - } - } - /// Execute the current plan. /// This will modify the disk. This function is unix-only. /// /// When dealing with `Plan::Link`, we need to be careful about replacing blocking /// files in the destination directory, they can be backed-up to a safe location or /// deleted from dist. This will recurse and call `Plan::execute` on plan's children. - fn execute(self: &Self) -> Result<()> { + fn execute(&self) -> Result<()> { match self { Plan::Link { path, @@ -278,10 +279,9 @@ impl Plan { Plan::Noop { children, .. } => children.iter().try_for_each(Plan::execute), } } -} -impl Display for Plan { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// Show the plan, recursing and displaying all it's children aswell. + fn show(self: &Self) -> Result<()> { match self { Plan::Link { path, @@ -290,14 +290,53 @@ impl Display for Plan { backup, } => { if *replace && *backup { - writeln!(f, "\t Move: {:?} -> {:?}", dest, dest.with_extension("bkp"))? + // Show backup formatted text + execute!( + io::stdout(), + SetForegroundColor(Color::Magenta), + SetAttribute(Attribute::Bold), + Print("~ mv: "), + SetAttribute(Attribute::Reset), + SetForegroundColor(Color::Magenta), + Print(format!( + "{} -> {}", + dest.display(), + dest.with_extension("bkp").display() + )), + Print("\n"), + SetForegroundColor(Color::Reset), + )?; } else if *replace { - writeln!(f, "\t Delete: {:?}", dest)? + // Show remove formatted text + execute!( + io::stdout(), + SetForegroundColor(Color::Red), + SetAttribute(Attribute::Bold), + Print("- rm: "), + SetAttribute(Attribute::Reset), + SetForegroundColor(Color::Red), + Print(format!("{}", dest.display())), + Print("\n"), + SetForegroundColor(Color::Reset), + )?; } - write!(f, "\t Symlink: {:?} -> {:?}", dest, path) + // Show link formatted text + execute!( + io::stdout(), + SetForegroundColor(Color::Cyan), + SetAttribute(Attribute::Bold), + Print("~ ln: "), + SetAttribute(Attribute::Reset), + SetForegroundColor(Color::Cyan), + Print(format!("{} -> {}", dest.display(), path.display())), + Print("\n"), + SetForegroundColor(Color::Reset), + )?; + + Ok(()) } - _ => Ok(()), + Plan::Noop { children, .. } => children.iter().try_for_each(Plan::show), } } } @@ -398,4 +437,25 @@ mod tests { assert!(plan.is_ok(), "everything should be fine"); assert_eq!(plan.unwrap(), expected); } + + #[test] + fn not_folder() { + let path: PathBuf = "./__test__/not_folder".into(); + let dest: PathBuf = "./__test__/output".into(); + + let expected = Plan::Noop { + path: path.clone(), + dest: dest.clone(), + children: vec![Plan::Link { + path: path.join("not_folder"), + dest: dest.join("not_folder"), + backup: false, + replace: true, + }], + }; + + let plan = Plan::new(&path, &dest, false); + assert!(plan.is_ok(), "everything should be fine"); + assert_eq!(plan.unwrap(), expected); + } }