diff --git a/Cargo.lock b/Cargo.lock index c053bd3..a61a83d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,42 +108,6 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "ash" -version = "0.37.2+1.3.238" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03" -dependencies = [ - "libloading", -] - [[package]] name = "atty" version = "0.2.14" @@ -163,9 +127,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "bit-set" @@ -205,35 +169,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" - -[[package]] -name = "bytemuck" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "byteorder" -version = "1.4.3" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytes" @@ -289,9 +227,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.7" +version = "4.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +checksum = "80672091db20273a15cf9fdd4e47ed43b5091ec9841bf4c6145c9dfbbcae09ed" dependencies = [ "clap_builder", "clap_derive", @@ -300,9 +238,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.7" +version = "4.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636" dependencies = [ "anstream", "anstyle", @@ -313,112 +251,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] name = "clap_lex" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" - -[[package]] -name = "clipboard-win" -version = "4.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" -dependencies = [ - "error-code", - "str-buf", - "winapi", -] - -[[package]] -name = "clipboard_macos" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145a7f9e9b89453bc0a5e32d166456405d389cea5b578f57f1274b1397588a95" -dependencies = [ - "objc", - "objc-foundation", - "objc_id", -] - -[[package]] -name = "clipboard_wayland" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6364a9f7a66f2ac1a1a098aa1c7f6b686f2496c6ac5e5c0d773445df912747" -dependencies = [ - "smithay-clipboard", -] - -[[package]] -name = "clipboard_x11" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983a7010836ecd04dde2c6d27a0cb56ec5d21572177e782bdcb24a600124e921" -dependencies = [ - "thiserror", - "x11rb", -] - -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - -[[package]] -name = "cocoa" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "core-foundation", - "core-graphics", - "foreign-types 0.3.2", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" -dependencies = [ - "bitflags", - "block", - "core-foundation", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", - "objc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "colorchoice" @@ -428,81 +275,22 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "console" -version = "0.15.5" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.42.0", -] - -[[package]] -name = "const_panic" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags", - "core-foundation", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation", - "foreign-types 0.3.2", - "libc", -] - -[[package]] -name = "core-text" -version = "19.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" -dependencies = [ - "core-foundation", - "core-graphics", - "foreign-types 0.3.2", - "libc", + "windows-sys 0.45.0", ] [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" dependencies = [ "libc", ] @@ -646,9 +434,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -675,41 +463,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading", -] - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "dwrote" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" -dependencies = [ - "lazy_static", - "libc", - "serde", - "serde_derive", - "winapi", - "wio", -] - [[package]] name = "dyn-clone" version = "1.0.11" @@ -840,15 +593,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "find-crate" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2" -dependencies = [ - "toml", -] - [[package]] name = "flate2" version = "1.0.26" @@ -909,9 +653,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -995,7 +739,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1059,120 +803,15 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", "wasi", ] -[[package]] -name = "glam" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815" - -[[package]] -name = "glow" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyph_brush" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edefd123f28a0b1d41ec4a489c2b43020b369180800977801611084f342978d" -dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "ordered-float", - "rustc-hash", - "twox-hash", -] - -[[package]] -name = "glyph_brush_draw_cache" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6010675390f6889e09a21e2c8b575b3ee25667ea8237a8d59423f73cb8c28610" -dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" -dependencies = [ - "ab_glyph", - "approx", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" -dependencies = [ - "bitflags", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" -dependencies = [ - "bitflags", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags", -] - -[[package]] -name = "guillotiere" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" -dependencies = [ - "euclid", - "svg_fmt", -] - [[package]] name = "h2" version = "0.3.19" @@ -1318,9 +957,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" dependencies = [ "http", "hyper", @@ -1455,9 +1094,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1475,11 +1114,12 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.3" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" +checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" dependencies = [ "console", + "instant", "number_prefix", "portable-atomic 0.3.20", "unicode-segmentation", @@ -1509,16 +1149,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", ] [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", @@ -1549,17 +1186,11 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1583,23 +1214,13 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" - -[[package]] -name = "libloading" -version = "0.7.4" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "libprotonup" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "dirs", @@ -1617,36 +1238,17 @@ dependencies = [ "xz2", ] -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" - -[[package]] -name = "lock_api" -version = "0.4.9" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lzma-sys" @@ -1721,12 +1323,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1739,92 +1335,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", - "windows-sys 0.45.0", -] - -[[package]] -name = "naga" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262d2840e72dbe250e8cf2f522d080988dfca624c4112c096238a4845f591707" -dependencies = [ - "bit-set", - "bitflags", - "codespan-reporting", - "hexf-parse", - "indexmap", - "log", - "num-traits", - "rustc-hash", - "spirv", - "termcolor", - "thiserror", - "unicode-xid", -] - -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags", - "jni-sys", - "ndk-sys", - "num_enum", - "raw-window-handle 0.5.2", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-glue" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" -dependencies = [ - "libc", - "log", - "ndk", - "ndk-context", - "ndk-macro", - "ndk-sys", - "once_cell", - "parking_lot 0.12.1", -] - -[[package]] -name = "ndk-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1977,9 +1494,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "option-ext" @@ -2079,9 +1602,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "phf" @@ -2143,49 +1666,11 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" -[[package]] -name = "png" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" -dependencies = [ - "bitflags", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "portable-atomic" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" -dependencies = [ - "portable-atomic 1.3.2", -] - -[[package]] -name = "portable-atomic" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59d1bcc64fc5d021d67521f818db868368028108d37f0e98d74e33f68297b5" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] +checksum = "767eb9f07d4a5ebcb39bbf2d452058a93c011373abf6832e24194a1c3f004794" [[package]] name = "proc-macro-error" @@ -2213,9 +1698,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.57" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" dependencies = [ "unicode-ident", ] @@ -2239,9 +1724,9 @@ dependencies = [ [[package]] name = "protonup-rs" -version = "0.5.0" +version = "0.6.0" dependencies = [ - "clap 4.2.7", + "clap 4.3.4", "indicatif", "inquire", "libprotonup", @@ -2250,9 +1735,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -2369,17 +1854,11 @@ dependencies = [ "thiserror", ] -[[package]] -name = "renderdoc-sys" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" - [[package]] name = "reqwest" -version = "0.11.17" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ "base64", "bytes", @@ -2431,17 +1910,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustix" -version = "0.37.7" +version = "0.37.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" +checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" dependencies = [ "bitflags", "errno", @@ -2453,14 +1926,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -2472,6 +1945,16 @@ dependencies = [ "base64", ] +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.13" @@ -2509,36 +1992,24 @@ dependencies = [ "untrusted", ] -[[package]] -name = "sctk-adwaita" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61270629cc6b4d77ec1907db1033d5c2e1a404c412743621981a871dc9c12339" -dependencies = [ - "crossfont", - "log", - "smithay-client-toolkit", - "tiny-skia", -] - [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2587,9 +2058,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -2754,9 +2225,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -2821,32 +2292,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", -] - -[[package]] -name = "tiny-skia" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642680569bb895b16e4b9d181c60be1ed136fa0c9c7f11d004daf053ba89bf82" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "bytemuck", - "cfg-if", - "png", - "safe_arch", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c114d32f0c2ee43d585367cb013dfaba967ab9f62b90d9af0d696e955e70fa6c" -dependencies = [ - "arrayref", - "bytemuck", + "syn 2.0.18", ] [[package]] @@ -2866,9 +2312,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.1" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ "autocfg", "bytes", @@ -2889,18 +2335,17 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", - "webpki", ] [[package]] @@ -3006,9 +2451,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -3045,9 +2490,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -3074,11 +2519,10 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -3090,9 +2534,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3100,24 +2544,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -3127,9 +2571,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3137,22 +2581,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-streams" @@ -3167,99 +2611,11 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wayland-client" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" -dependencies = [ - "bitflags", - "downcast-rs", - "libc", - "nix 0.24.3", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys", -] - -[[package]] -name = "wayland-commons" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" -dependencies = [ - "nix 0.24.3", - "once_cell", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-cursor" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" -dependencies = [ - "nix 0.24.3", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" -dependencies = [ - "bitflags", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", -] - [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -3457,21 +2813,6 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.45.0" diff --git a/Cargo.toml b/Cargo.toml index da1a31f..53ea940 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -resolver="2" +resolver = "2" members = ["libprotonup", "protonup-rs", "protonup-gui"] diff --git a/README.md b/README.md index d9e3b5b..a004b4b 100644 --- a/README.md +++ b/README.md @@ -4,32 +4,29 @@ Lib, CLI and GUI(wip) program to automate the installation and update of Proton- > **NOTE**: This has no relations with the original ProtonUp project, and I am glad it was created. > ~~This is not nearly as feature complete as the original Protonup~~. -> -> I've create it because the original project had a few issues with its Python dependencies (that most likely got fixed already). +> +> I've create it because the original project had a few issues with its Python dependencies (that most likely got fixed already). > I wanted to to re-create it in rust, in a way it could be used as a lib and a CLI. > ~~If this repo gets to a stable and feature rich state, I will publish it to Cargo and other repositories.~~ I guess it got there! Thanks! -[![asciicast](https://asciinema.org/a/rEO6Oipjn4rBkTWAtH1IFf3Xe.svg)](https://asciinema.org/a/rEO6Oipjn4rBkTWAtH1IFf3Xe) +[![asciicast](https://asciinema.org/a/QZ97c4yRwQ6YczTliB1ziZy5Z.svg)](https://asciinema.org/a/QZ97c4yRwQ6YczTliB1ziZy5Z) ## Usage The default way is to simply invoke the cli, and navigate the text interface. + ```bash protonup-rs ``` -To run a quick update and get the latest GE Proton version without navigating the TUI, you can use the quick flags: -```bash - -q, --quick-download Download latest directly - -f, --quick-download-flatpak Download latest for Steam FlatPak - -l, --lutris-quick-download Download latest Wine GE for Lutris - -L, --lutris-quick-download-flatpak Download latest Wine GE for Lutris FlatPak - -h, --help Print help -``` -You can also combine them and get all the latest version running: +To run a quick update and get the latest GE Proton version without navigating the TUI, you can use the quick flag: ```bash -protonup-rs -q -f -l -L +Usage: protonup-rs [OPTIONS] + +Options: + -q, --quick-download Skip Menu, auto detect apps and download using default parameters + -h, --help Print help ``` --- @@ -42,7 +39,7 @@ protonup-rs -q -f -l -L wget https://github.com/auyer/Protonup-rs/releases/latest/download/protonup-rs-linux-amd64.tar.gz -O - | tar -xz && zenity --password | sudo -S mv protonup-rs /usr/bin/ ``` -This assumes `/usr/bin` is in your path. You may change this to any other location (in your path ```echo $PATH```). +This assumes `/usr/bin` is in your path. You may change this to any other location (in your path `echo $PATH`). ### Or manually: @@ -53,12 +50,12 @@ It is a single binary. You can just run it, or add it to your path so you can ca Quick way to add it to your path: or download the zip from the releases page + ``` cd Downloads sudo unzip protonup-rs-linux-amd64.zip -d /usr/bin ``` - ## Building from source You can install from source using the last released version in Crates.io: @@ -75,10 +72,8 @@ cargo build -p protonup-rs --release mv ./target/release/protonup-rs "your path" ``` - ## GUI Not ready for usage. The GUI is in its [early stages](https://github.com/auyer/Protonup-rs/tree/feature/gui). My current plan is to develop it in the iced framework, but GUI development is not my forte. - diff --git a/libprotonup/Cargo.toml b/libprotonup/Cargo.toml index 9c3af25..66af31b 100644 --- a/libprotonup/Cargo.toml +++ b/libprotonup/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libprotonup" -version = "0.5.0" +version = "0.6.0" edition = "2021" authors = ["Auyer "] repository = "https://github.com/auyer/protonup-rs" @@ -30,4 +30,4 @@ tar = "0.4" xz2 = "0.1" [dev-dependencies] -tokio = { version = "1.27", features = ["macros", "rt"] } +tokio = { version = "1.28", features = ["macros", "rt"] } diff --git a/libprotonup/src/apps.rs b/libprotonup/src/apps.rs new file mode 100644 index 0000000..0f9e19a --- /dev/null +++ b/libprotonup/src/apps.rs @@ -0,0 +1,132 @@ +use crate::{ + files::{self, list_folders_in_path}, + variants::Variant, +}; +use std::fmt; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum App { + Steam, + Lutris, + // TODO: HeroicGamesLauncher, +} + +// APP_VARIANTS is a shorthand to all app variants +pub static APP_VARIANTS: &[App] = &[App::Steam, App::Lutris]; + +impl fmt::Display for App { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::Steam => write!(f, "Steam"), + Self::Lutris => write!(f, "Lutris"), + } + } +} + +impl App { + pub fn app_available_variants(&self) -> Vec { + match *self { + Self::Steam => vec![Variant::GEProton], + Self::Lutris => vec![Variant::WineGE, Variant::GEProton], + } + } + + pub fn app_default_variant(&self) -> Variant { + match *self { + Self::Steam => Variant::GEProton, + Self::Lutris => Variant::WineGE, + } + } + + pub fn app_installations(&self) -> Vec { + match *self { + Self::Steam => vec![AppInstallations::Steam, AppInstallations::SteamFlatpak], + Self::Lutris => vec![AppInstallations::Lutris, AppInstallations::LutrisFlatpak], + } + } + + pub fn detect_installation_method(&self) -> Vec { + match *self { + Self::Steam => { + detect_installations(&[AppInstallations::Steam, AppInstallations::SteamFlatpak]) + } + Self::Lutris => { + detect_installations(&[AppInstallations::Lutris, AppInstallations::LutrisFlatpak]) + } + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum AppInstallations { + Steam, + SteamFlatpak, + Lutris, + LutrisFlatpak, +} + +impl fmt::Display for AppInstallations { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::Steam => write!(f, "Steam \"Native\" "), + Self::SteamFlatpak => write!(f, "Steam Flatpak"), + Self::Lutris => write!(f, "Lutris \"Native\""), + Self::LutrisFlatpak => write!(f, "Lutris Flatpak"), + } + } +} + +impl AppInstallations { + pub fn default_install_dir(&self) -> &'static str { + match *self { + Self::Steam => "~/.steam/steam/compatibilitytools.d/", + Self::SteamFlatpak => { + "~/.var/app/com.valvesoftware.Steam/data/Steam/compatibilitytools.d/" + } + Self::Lutris => "~/.local/share/lutris/runners/wine/", + Self::LutrisFlatpak => "~/.var/app/net.lutris.Lutris/data/lutris/runners/wine/", + } + } + + pub fn app_base_dir(&self) -> &'static str { + match *self { + Self::Steam => "~/.steam/steam/", + Self::SteamFlatpak => "~/.var/app/com.valvesoftware.Steam/data/Steam/", + Self::Lutris => "~/.local/share/lutris/", + Self::LutrisFlatpak => "~/.var/app/net.lutris.Lutris/data/lutris/", + } + } + + pub fn list_installed_versions(&self) -> Result, anyhow::Error> { + list_folders_in_path(self.default_install_dir()) + } + + pub fn into_app(&self) -> App { + match *self { + Self::Steam | Self::SteamFlatpak => App::Steam, + Self::Lutris | Self::LutrisFlatpak => App::Lutris, + } + } +} + +/// list_installed_apps returns a vector of App variants that are installed +pub fn list_installed_apps() -> Vec { + detect_installations(APP_INSTALLATIONS_VARIANTS) +} + +/// detect_installations returns a vector of App variants that are detected based on the provided +fn detect_installations(app_installations: &[AppInstallations]) -> Vec { + app_installations + .iter() + .filter(|app| files::check_if_exists(app.app_base_dir(), "")) + .cloned() + .collect() +} + +// APP_INSTALLATIONS_VARIANTS contains the subset of variants of the App enum that are actual apps +pub static APP_INSTALLATIONS_VARIANTS: &[AppInstallations] = &[ + AppInstallations::Steam, + AppInstallations::SteamFlatpak, + AppInstallations::Lutris, + AppInstallations::LutrisFlatpak, +]; diff --git a/libprotonup/src/constants.rs b/libprotonup/src/constants.rs index 58f641f..d33867e 100644 --- a/libprotonup/src/constants.rs +++ b/libprotonup/src/constants.rs @@ -1,11 +1,5 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION"); -pub const DEFAULT_STEAM_INSTALL_DIR: &str = "~/.steam/steam/compatibilitytools.d/"; -pub const DEFAULT_STEAM_INSTALL_DIR_FLATPAK: &str = - "~/.var/app/com.valvesoftware.Steam/data/Steam/compatibilitytools.d/"; -pub const DEFAULT_LUTRIS_INSTALL_DIR: &str = "~/.local/share/lutris/runners/wine/"; -pub const DEFAULT_LUTRIS_INSTALL_DIR_FLATPAK: &str = - "~/.var/app/net.lutris.Lutris/data/lutris/runners/wine/"; pub const TEMP_DIR: &str = "/tmp/"; pub const GITHUB_URL: &str = "https://api.github.com/repos"; diff --git a/libprotonup/src/file.rs b/libprotonup/src/files.rs similarity index 80% rename from libprotonup/src/file.rs rename to libprotonup/src/files.rs index f44142b..9f08c2e 100644 --- a/libprotonup/src/file.rs +++ b/libprotonup/src/files.rs @@ -23,6 +23,7 @@ fn path_result(path: &Path) -> String { } } +// decompress will detect the extension and decompress the file with the appropriate function pub fn decompress(from_path: &Path, destination_path: &Path) -> Result<()> { let path_str = from_path.as_os_str().to_string_lossy(); @@ -84,13 +85,40 @@ pub fn create_progress_trackers() -> (Arc, Arc) { ) } -/// Check if the Proton/Wine version (tag) exists at path +// check_if_exists checks if a folder exists in a path pub fn check_if_exists(path: &str, tag: &str) -> bool { - let f_path = utils::expand_tilde(format!("{path}/{tag}")).unwrap(); - let p = std::path::Path::new(&f_path); + let f_path = utils::expand_tilde(format!("{path}{tag}/")).unwrap(); + let p = f_path.as_path(); p.is_dir() } +// list_folders_in_path returns a vector of strings of the folders in a path +pub fn list_folders_in_path(path: &str) -> Result, anyhow::Error> { + let f_path = utils::expand_tilde(path).unwrap(); + let p = f_path.as_path(); + let paths: Vec = p + .read_dir() + .with_context(|| format!("Failed to read directory : {}", path_result(p)))? + .filter_map(|e| e.ok()) + .filter(|e| e.path().is_dir()) + .map(|e| { + let path = e.path(); + let name = path.file_name().unwrap(); + name.to_str().unwrap().to_string() + }) + .collect(); + Ok(paths) +} + +// removes a directory and all its contents +pub fn remove_dir_all(path: &str) -> Result<()> { + let f_path = utils::expand_tilde(path).unwrap(); + let p = f_path.as_path(); + std::fs::remove_dir_all(p) + .with_context(|| format!("[Remove] Failed to remove directory : {}", path_result(p)))?; + Ok(()) +} + /// requires pointers to store the progress, and another to store "done" status /// Create them with `create_progress_trackers` pub async fn download_file_progress( @@ -140,8 +168,7 @@ pub async fn download_file_progress( Ok(()) } -/// Downloads sha512 hash returned as Result to verify download integrity -pub async fn download_sha512_into_memory(url: &String) -> Result { +pub async fn download_file_into_memory(url: &String) -> Result { let client = reqwest::Client::new(); let res = client .get(url) diff --git a/libprotonup/src/github.rs b/libprotonup/src/github.rs index 1532e74..3a2bc48 100644 --- a/libprotonup/src/github.rs +++ b/libprotonup/src/github.rs @@ -1,5 +1,5 @@ use crate::constants; -use crate::parameters::VariantParameters; +use crate::variants::VariantParameters; use anyhow::Result; use serde::{Deserialize, Serialize}; @@ -95,7 +95,7 @@ pub async fn fetch_data_from_tag( #[cfg(test)] mod tests { - use crate::parameters; + use crate::variants; use super::*; @@ -103,12 +103,12 @@ mod tests { async fn test_fetch_data_from_tag() { let conditions = &[ ( - parameters::Variant::WineGE.parameters(), + variants::Variant::WineGE.parameters(), "latest", "Get Steam", ), ( - parameters::Variant::GEProton.parameters(), + variants::Variant::GEProton.parameters(), "latest", "Download Lutris", ), @@ -150,8 +150,8 @@ mod tests { #[tokio::test] async fn test_list_releases() { let conditions = &[ - (parameters::Variant::WineGE.parameters(), "List WineGE"), - (parameters::Variant::GEProton.parameters(), "List GEProton"), + (variants::Variant::WineGE.parameters(), "List WineGE"), + (variants::Variant::GEProton.parameters(), "List GEProton"), ]; for (source_parameters, desc) in conditions { @@ -188,8 +188,8 @@ mod tests { }; let conditions = &[ - (parameters::Variant::WineGE.parameters(), "Get WineGE"), - (parameters::Variant::GEProton.parameters(), "Get GEProton"), + (variants::Variant::WineGE.parameters(), "Get WineGE"), + (variants::Variant::GEProton.parameters(), "Get GEProton"), ]; for (source_parameters, desc) in conditions { let url = format!( diff --git a/libprotonup/src/lib.rs b/libprotonup/src/lib.rs index 0d59783..d5a4355 100644 --- a/libprotonup/src/lib.rs +++ b/libprotonup/src/lib.rs @@ -1,5 +1,6 @@ +pub mod apps; pub mod constants; -pub mod file; +pub mod files; pub mod github; -pub mod parameters; pub mod utils; +pub mod variants; diff --git a/libprotonup/src/parameters.rs b/libprotonup/src/variants.rs similarity index 95% rename from libprotonup/src/parameters.rs rename to libprotonup/src/variants.rs index 8dc6d22..9f681d6 100644 --- a/libprotonup/src/parameters.rs +++ b/libprotonup/src/variants.rs @@ -37,6 +37,7 @@ impl VariantParameters { } /// Variant is an enum with all supported "Proton" versions +#[derive(Debug, Clone)] pub enum Variant { GEProton, WineGE, @@ -91,3 +92,6 @@ impl Variant { } } } + +// ALL_VARIANTS is a shorthand to all app variants +pub static ALL_VARIANTS: &[Variant] = &[Variant::GEProton, Variant::WineGE]; diff --git a/protonup-rs/Cargo.toml b/protonup-rs/Cargo.toml index c9b1e9e..843df26 100644 --- a/protonup-rs/Cargo.toml +++ b/protonup-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "protonup-rs" -version = "0.5.0" +version = "0.6.0" edition = "2021" authors = ["Auyer "] repository = "https://github.com/auyer/protonup-rs" @@ -14,13 +14,11 @@ description = "TUI Program for Custom Proton Download and installation written i # Use this to use the local changes in libprotonup. libprotonup = { path = "../libprotonup" } # This is necessary to publish to crates.io -# libprotonup = { version = "0.5.0" } +# libprotonup = { version = "0.6.0" } inquire = { version = "0.6", default-features = false, features = ["termion"] } indicatif = { version = "0.17", features = [ "improved_unicode", "unicode-segmentation", ] } -tokio = { version = "1.27", features = ["macros", "rt-multi-thread"] } -clap = { version = "4.2.1", features = ["derive"] } - - +tokio = { version = "1.28", features = ["macros", "rt-multi-thread"] } +clap = { version = "4.3", features = ["derive"] } diff --git a/protonup-rs/src/download.rs b/protonup-rs/src/download.rs new file mode 100644 index 0000000..f67b23b --- /dev/null +++ b/protonup-rs/src/download.rs @@ -0,0 +1,111 @@ +use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; + +use std::fs; +use std::path::{Path, PathBuf}; +use std::{ + sync::{atomic::Ordering, Arc}, + thread, + time::Duration, +}; + +use libprotonup::{constants, files, github, utils, variants}; + +pub(crate) async fn download_file( + tag: &str, + source: &variants::VariantParameters, +) -> Result { + let mut temp_dir = utils::expand_tilde(constants::TEMP_DIR).unwrap(); + + let download = match github::fetch_data_from_tag(tag, source).await { + Ok(data) => data, + Err(e) => { + eprintln!("Failed to fetch GitHub data, make sure you're connected to the internet\nError: {}", e); + std::process::exit(1) + } + }; + + temp_dir.push(if download.download.ends_with("tar.gz") { + format!("{}.tar.gz", &download.version) + } else if download.download.ends_with("tar.xz") { + format!("{}.tar.xz", &download.version) + } else { + eprintln!("Downloaded file wasn't of the expected type. (tar.(gz/xz)"); + std::process::exit(1) + }); + + let git_hash = files::download_file_into_memory(&download.sha512sum) + .await + .unwrap(); + + if temp_dir.exists() { + fs::remove_file(&temp_dir).unwrap(); + } + + let (progress, done) = files::create_progress_trackers(); + let progress_read = Arc::clone(&progress); + let done_read = Arc::clone(&done); + let url = String::from(&download.download); + let tmp_dir = String::from(temp_dir.to_str().unwrap()); + + // start ProgressBar in another thread + thread::spawn(move || { + let pb = ProgressBar::with_draw_target( + Some(download.size), + ProgressDrawTarget::stderr_with_hz(20), + ); + pb.set_style(ProgressStyle::default_bar() + .template("{msg}\n{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec})").unwrap() + .progress_chars("#>-")); + pb.set_message(format!("Downloading {}", url.split('/').last().unwrap())); + let wait_time = Duration::from_millis(50); // 50ms wait is about 20Hz + loop { + let newpos = progress_read.load(Ordering::Relaxed); + pb.set_position(newpos as u64); + if done_read.load(Ordering::Relaxed) { + break; + } + thread::sleep(wait_time); + } + pb.set_message(format!("Downloaded {url} to {tmp_dir}")); + pb.abandon(); // closes progress bar without blanking terminal + + println!("Checking file integrity"); // This is being printed here because the progress bar needs to be closed before printing. + }); + + files::download_file_progress( + download.download, + download.size, + temp_dir.clone().as_path(), + progress, + done, + ) + .await + .unwrap(); + + if !files::hash_check_file(temp_dir.to_str().unwrap().to_string(), git_hash).unwrap() { + return Err("Failed checking file hash".to_string()); + } + + Ok(temp_dir) +} + +pub(crate) async fn unpack_file( + dowaload_path: &Path, + install_path: &str, + source: &variants::VariantParameters, +) -> Result<(), String> { + let install_dir = utils::expand_tilde(install_path).unwrap(); + + fs::create_dir_all(&install_dir).unwrap(); + + println!("Unpacking files into install location. Please wait"); + files::decompress(dowaload_path, install_dir.as_path()).unwrap(); + let source_type = source.variant_type(); + println!( + "Done! Restart {}. {} installed in {}", + source_type.intended_application(), + source_type, + install_dir.to_string_lossy(), + ); + Ok(()) +} diff --git a/protonup-rs/src/helper_menus.rs b/protonup-rs/src/helper_menus.rs new file mode 100644 index 0000000..d6721fe --- /dev/null +++ b/protonup-rs/src/helper_menus.rs @@ -0,0 +1,26 @@ +use inquire::{Confirm, InquireError, MultiSelect}; +use libprotonup::apps::AppInstallations; + +pub(crate) fn tag_menu(message: &str, options: Vec) -> Result, InquireError> { + MultiSelect::new(message, options) + .with_default(&[0_usize]) + .prompt() +} + +pub(crate) fn variants_menu( + message: &str, + options: Vec, +) -> Result, InquireError> { + MultiSelect::new(message, options) + .with_default(&[0_usize]) + .prompt() +} + +pub(crate) fn confirm_menu(text: String, help_text: String, default: bool) -> bool { + let answer = Confirm::new(&text) + .with_default(default) + .with_help_message(&help_text) + .prompt(); + + answer.unwrap_or(false) +} diff --git a/protonup-rs/src/main.rs b/protonup-rs/src/main.rs index 98531e1..325fcb3 100644 --- a/protonup-rs/src/main.rs +++ b/protonup-rs/src/main.rs @@ -1,335 +1,225 @@ use clap::Parser; -use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; -use inquire::{Confirm, MultiSelect, Select, Text}; + +use inquire::{Select, Text}; + use std::fmt; -use std::fs; -use std::fs::create_dir_all; -use std::sync::atomic::Ordering; -use std::thread; -use std::{sync::Arc, time::Duration}; + +use libprotonup::{apps, files, github, variants}; + +mod download; mod file_path; +mod helper_menus; +mod manage_apps; -use libprotonup::{constants, file, github, parameters, utils}; +use download::{download_file, unpack_file}; +use helper_menus::{confirm_menu, tag_menu, variants_menu}; +use manage_apps::manage_apps_routine; #[derive(Debug, Parser)] struct Opt { - /// Skip Menu and download latest directly + /// Skip Menu, auto detect apps and download using default parameters #[arg(short, long)] quick_download: bool, - #[arg(short = 'f', long)] - quick_download_flatpak: bool, - /// Download latest Wine GE for Lutris - #[arg(short, long)] - lutris_quick_download: bool, - #[arg(short = 'L', long)] - lutris_quick_download_flatpak: bool, } #[derive(Debug, Copy, Clone)] #[allow(clippy::upper_case_acronyms)] -enum Menu { +enum InitialMenu { QuickUpdate, - QuickUpdateFlatpak, - QuickUpdateLutris, - QuickUpdateLutrisFlatpak, - ChoseReleases, - ChoseReleasesFlatpak, - ChoseReleasesCustomDir, - ChoseReleasesLutris, - ChoseReleasesLutrisFlatpak, + DoanloadForSteam, + DoanloadForLutris, + DownloadIntoCustomLocation, + ManageExistingInstallations, } -impl Menu { +impl InitialMenu { // could be generated by macro - const VARIANTS: &'static [Menu] = &[ + const VARIANTS: &'static [InitialMenu] = &[ Self::QuickUpdate, - Self::QuickUpdateFlatpak, - Self::QuickUpdateLutris, - Self::QuickUpdateLutrisFlatpak, - Self::ChoseReleases, - Self::ChoseReleasesFlatpak, - Self::ChoseReleasesCustomDir, - Self::ChoseReleasesLutris, - Self::ChoseReleasesLutrisFlatpak, + Self::DoanloadForSteam, + Self::DoanloadForLutris, + Self::DownloadIntoCustomLocation, + Self::ManageExistingInstallations, ]; } -impl fmt::Display for Menu { +impl fmt::Display for InitialMenu { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Self::QuickUpdate => write!(f, "Quick Update Steam (download latest GE Proton)"), - Self::QuickUpdateFlatpak => write!( - f, - "Quick Update (download latest GE Proton) for Flatpak Steam" - ), - Self::QuickUpdateLutris => write!(f, "Quick Update Lutris (download latest Wine GE)"), - Self::QuickUpdateLutrisFlatpak => { - write!(f, "Quick Update Lutris Flatpak (download latest Wine GE)") - } - Self::ChoseReleases => write!(f, "Choose GE Proton releases from list"), - Self::ChoseReleasesFlatpak => { - write!(f, "Choose GE Proton releases from list for Flatpak Steam") - } - Self::ChoseReleasesCustomDir => write!( - f, - "Choose GE Proton releases and install to custom directory" - ), - Self::ChoseReleasesLutris => write!(f, "Choose Wine GE releases for Lutris"), - Self::ChoseReleasesLutrisFlatpak => { - write!(f, "Choose Wine GE releases for Flatpak Lutris") + Self::QuickUpdate => write!(f, "Quick Update (detect apps and auto download)"), + Self::DoanloadForSteam => write!(f, "Download GE-Proton for Steam"), + Self::DoanloadForLutris => write!(f, "Download GE-Proton/Wine-GE for Lutris"), + Self::DownloadIntoCustomLocation => { + write!(f, "Download GE-Proton/Wine-GE into custom location") } + Self::ManageExistingInstallations => write!(f, "Manage Existing Proton Installations"), } } } -fn tag_menu(options: Vec) -> Vec { - let answer = MultiSelect::new("Select the versions you want to download :", options) - .with_default(&[0_usize]) - .prompt(); - - match answer { - Ok(list) => list, - - Err(_) => { - println!("The tag list could not be processed"); - vec![] - } - } -} - -fn confirm_menu(text: String) -> bool { - let answer = Confirm::new(&text) - .with_default(false) - .with_help_message("If you choose yes, we will re-install it.") - .prompt(); - - answer.unwrap_or(false) -} - #[tokio::main] async fn main() { - // run quick downloads and skip menu + // run quick downloads and skip InitialMenu if run_quick_downloads().await { return; } // Default Parameters - let source: parameters::VariantParameters; - let mut install_dir = constants::DEFAULT_STEAM_INSTALL_DIR.to_string(); - let mut tags: Vec = vec![String::from("latest")]; + let source: variants::VariantParameters; + let mut install_dirs: Vec = vec![]; + let mut tags: Vec = vec![]; let mut should_open_tag_selector = false; let mut should_open_dir_selector = false; - - let answer: Menu = Select::new("ProtonUp Menu: Chose your action:", Menu::VARIANTS.to_vec()) - .with_page_size(9) - .prompt() - .unwrap_or_else(|_| std::process::exit(0)); + let mut manage_existing_versions = false; + let mut should_detect_apps = false; + let mut apps_to_use: Vec = vec![]; + let mut selected_app: Option = None; + + let answer: InitialMenu = Select::new( + "ProtonUp Menu: Chose your action:", + InitialMenu::VARIANTS.to_vec(), + ) + .with_page_size(10) + .prompt() + .unwrap_or_else(|_| std::process::exit(0)); // Set parameters based on users choice match answer { - Menu::QuickUpdate => { - // let tag = match github::fetch_data_from_tag("latest", false).await { - // Ok(data) => data, - // Err(e) => { - // eprintln!("Failed to fetch Github data, make sure you're connected to the internet.\nError: {}", e); - // std::process::exit(1) - // } - // }; - // - // if file::check_if_exists( - // constants::DEFAULT_STEAM_INSTALL_DIR.to_owned(), - // tag.version.clone(), - // ) && !confirm_menu(format!( - // "Version {} exists in installation path. Overwrite?", - // tag.version - // )) { - // return; - // } - // - // download_file( - // "latest", - // constants::DEFAULT_STEAM_INSTALL_DIR.to_string(), - // false, - // ) - // .await - // .unwrap(); - // } - // Menu::QuickUpdateFlatpak => { - // let tag = match github::fetch_data_from_tag("latest", false).await { - // Ok(data) => data, - // Err(e) => { - // eprintln!("Failed to fetch Github data, make sure you're connected to the internet.\nError: {}", e); - // std::process::exit(1) - // } - // }; - // - // if file::check_if_exists( - // constants::DEFAULT_STEAM_INSTALL_DIR_FLATPAK.to_owned(), - // tag.version.clone(), - // ) && !confirm_menu(format!( - // "Version {} exists in installation path. Overwrite?", - // tag.version - // )) { - // return; - // } - // - // download_file( - // "latest", - // constants::DEFAULT_STEAM_INSTALL_DIR_FLATPAK.to_string(), - // false, - // ) - // .await - // .unwrap(); - source = parameters::Variant::GEProton.parameters(); - install_dir = constants::DEFAULT_STEAM_INSTALL_DIR.to_owned(); + InitialMenu::QuickUpdate => { + should_detect_apps = true; } - Menu::QuickUpdateFlatpak => { - source = parameters::Variant::GEProton.parameters(); - install_dir = constants::DEFAULT_STEAM_INSTALL_DIR_FLATPAK.to_owned(); - } - Menu::QuickUpdateLutris => { - source = parameters::Variant::WineGE.parameters(); - install_dir = constants::DEFAULT_LUTRIS_INSTALL_DIR.to_owned(); - } - Menu::QuickUpdateLutrisFlatpak => { - source = parameters::Variant::WineGE.parameters(); - install_dir = constants::DEFAULT_LUTRIS_INSTALL_DIR_FLATPAK.to_owned(); - } - Menu::ChoseReleases => { - // let release_list = match github::list_releases(false).await { - // Ok(data) => data, - // Err(e) => { - // eprintln!("Failed to fetch Github data, make sure you're connected to the internet.\nError: {}", e); - // std::process::exit(1) - // } - // }; - // let tag_list: Vec = release_list.into_iter().map(|r| (r.tag_name)).collect(); - // let list = tag_menu(tag_list); - // for tag in list.iter() { - // if file::check_if_exists( - // constants::DEFAULT_STEAM_INSTALL_DIR.to_owned(), - // tag.to_owned(), - // ) && !confirm_menu(format!( - // "Version {tag} exists in installation path. Overwrite?" - // )) { - // return; - // } - // download_file(tag, constants::DEFAULT_STEAM_INSTALL_DIR.to_string(), false) - // .await - // .unwrap(); - // } - // } - // Menu::ChoseReleasesFlatpak => { - // let release_list = match github::list_releases(false).await { - // Ok(data) => data, - // Err(e) => { - // eprintln!("Failed to fetch Github data, make sure you're connected to the internet.\nError: {}", e); - // std::process::exit(1) - // } - // }; - // let tag_list: Vec = release_list.into_iter().map(|r| (r.tag_name)).collect(); - // let list = tag_menu(tag_list); - // for tag in list.iter() { - // if file::check_if_exists( - // constants::DEFAULT_STEAM_INSTALL_DIR_FLATPAK.to_owned(), - // tag.to_owned(), - // ) && !confirm_menu(format!( - // "Version {tag} exists in installation path. Overwrite?" - // )) { - // return; - // } - // download_file( - // tag, - // constants::DEFAULT_STEAM_INSTALL_DIR_FLATPAK.to_string(), - // false, - // ) - // .await - // .unwrap(); - // } - // } - // Menu::ChoseReleasesCustomDir => { - // let current_dir = std::env::current_dir().unwrap(); - // let help_message = format!("Current directory: {}", current_dir.to_string_lossy()); - // let answer = Text::new("Installation path:") - // .with_autocomplete(file_path::FilePathCompleter::default()) - // .with_help_message(&help_message) - // .prompt(); - // - // let chosen_path = match answer { - // Ok(path) => path, - // Err(error) => { - // println!("Error choosing custom path. Using the default. Error: {error:?}"); - // constants::DEFAULT_STEAM_INSTALL_DIR.to_string() - // } - // }; - // let release_list = match github::list_releases(false).await { - // Ok(data) => data, - // Err(e) => { - // eprintln!("Failed to fetch Github data, make sure you're connected to the internet.\nError: {}", e); - // std::process::exit(1) - // } - // }; - // let tag_list: Vec = release_list.into_iter().map(|r| (r.tag_name)).collect(); - // let list = tag_menu(tag_list); - // for tag in list.iter() { - // if file::check_if_exists( - // constants::DEFAULT_STEAM_INSTALL_DIR.to_owned(), - // tag.to_owned(), - // ) && !confirm_menu(format!( - // "Version {tag} exists in installation path. Overwrite?" - // )) { - // return; - // } - // - // download_file(tag, chosen_path.clone(), false) - // .await - // .unwrap(); - // } - source = parameters::Variant::GEProton.parameters(); - install_dir = constants::DEFAULT_STEAM_INSTALL_DIR.to_owned(); + InitialMenu::DoanloadForSteam => { + selected_app = Some(apps::App::Steam); should_open_tag_selector = true; } - Menu::ChoseReleasesFlatpak => { - source = parameters::Variant::GEProton.parameters(); - install_dir = constants::DEFAULT_STEAM_INSTALL_DIR_FLATPAK.to_owned(); + InitialMenu::DoanloadForLutris => { + selected_app = Some(apps::App::Lutris); should_open_tag_selector = true; } - Menu::ChoseReleasesCustomDir => { - source = parameters::Variant::GEProton.parameters(); + InitialMenu::DownloadIntoCustomLocation => { should_open_dir_selector = true; should_open_tag_selector = true; } - Menu::ChoseReleasesLutris => { - source = parameters::Variant::WineGE.parameters(); - install_dir = constants::DEFAULT_LUTRIS_INSTALL_DIR.to_owned(); - should_open_tag_selector = true; - } - Menu::ChoseReleasesLutrisFlatpak => { - source = parameters::Variant::WineGE.parameters(); - install_dir = constants::DEFAULT_LUTRIS_INSTALL_DIR_FLATPAK.to_owned(); - should_open_tag_selector = true; - } + InitialMenu::ManageExistingInstallations => manage_existing_versions = true, } // This is where the execution happens + // If the user wants to manage existing installations, we skip the rest of the menu + if manage_existing_versions { + manage_apps_routine(); + return; + } + + if should_detect_apps { + apps_to_use = apps::list_installed_apps(); + if apps_to_use.is_empty() { + println!("Could not find any version of Steam or Lutris. Please install at least one app before using this feature."); + return; + } + println!( + "Found the following apps: {}", + apps_to_use + .iter() + .map(|app| app.to_string()) + .collect::>() + .join(", ") + ); + + // TODO: this should be done in a single place. But here we use the default for every app, and in the other part we install all selected tags for all selected apps + for app_inst in &apps_to_use { + let variant = app_inst.into_app().app_default_variant(); + let destination = app_inst.default_install_dir().to_string(); + println!( + "\nQuick Download: {} for {} into -> {}\n", + variant, + app_inst.into_app(), + destination + ); + let file = download_file("latest", &variant.parameters()) + .await + .unwrap(); + unpack_file(&file, &destination, &variant.parameters()) + .await + .unwrap_or_else(|_| std::process::exit(0)); + } + return; + } + + // the rest of th execution is for updating/installing new versions if should_open_dir_selector { - let current_dir = std::env::current_dir().unwrap(); - let help_message = format!("Current directory: {}", current_dir.to_string_lossy()); + let current_dir = std::env::current_dir().unwrap_or_else(|_| std::process::exit(0)); + let help_message = format!("Current directory: {}", ¤t_dir.to_string_lossy()); let answer = Text::new("Installation path:") .with_autocomplete(file_path::FilePathCompleter::default()) .with_help_message(&help_message) + .with_default(¤t_dir.to_string_lossy()) .prompt(); match answer { - Ok(path) => install_dir = path, + Ok(path) => { + println!("Will use the custom path: {}", path); + install_dirs.push(path) + } Err(error) => { println!("Error choosing custom path. Using the default. Error: {error:?}"); } }; } + let source_options = match selected_app { + Some(app) => app.app_available_variants(), + None => variants::ALL_VARIANTS.to_vec(), + }; + + if source_options.len() == 1 { + source = source_options[0].parameters(); + } else { + source = Select::new("Chose the variant you want to install:", source_options) + .prompt() + .map(|variant| variant.parameters()) + .unwrap_or_else(|_| std::process::exit(0)); + }; + + // if empty, no apps were detected, so we ask the user to chose one + if apps_to_use.is_empty() && selected_app.is_some() { + apps_to_use = apps::list_installed_apps(); + if !apps_to_use.is_empty() { + // filter detected app installations that match selected app + apps_to_use.retain(|app_inst| app_inst.into_app() == selected_app.unwrap()); + apps_to_use.retain(|app_inst| { + confirm_menu( + format!("Detected {app_inst} installation. Use it?"), + String::from("If you have multiple install options, you can chose all of them"), + true, + ) + }) + } + + // if apps_to_use is empty, list default options + if apps_to_use.is_empty() { + apps_to_use = variants_menu( + "Chose the app you want to install for:", + selected_app.unwrap().app_installations(), + ) + .unwrap_or_else(|_| std::process::exit(0)); + } + } + + // if still no apps were selected + if apps_to_use.is_empty() && selected_app.is_some() { + return; + } + + // past this point, either a path was manually selected or selected_app is not empty + if install_dirs.is_empty() { + install_dirs = apps_to_use + .iter() + .map(|app_inst| app_inst.default_install_dir().to_string()) + .collect(); + } + if should_open_tag_selector { tags = vec![]; let release_list = match github::list_releases(&source).await { @@ -340,24 +230,43 @@ async fn main() { } }; let tag_list: Vec = release_list.into_iter().map(|r| (r.tag_name)).collect(); - let list = tag_menu(tag_list); + let list = match tag_menu("Select the versions you want to download :", tag_list) { + Ok(tags) => tags, + Err(e) => { + eprintln!("The tag list could not be processed.\nError: {}", e); + vec![] + } + }; for tag_iter in list.iter() { let tag = String::from(tag_iter); tags.push(tag); } + } else { + let tag = match github::fetch_data_from_tag("latest", &source).await { + Ok(data) => data, + Err(e) => { + eprintln!("Failed to fetch Github data, make sure you're connected to the internet.\nError: {}", e); + std::process::exit(1) + } + }; + tags.push(tag.version) } tags.retain(|tag_name| { // Check if versions exist in disk. // If they do, ask the user if it should be overwritten - !(file::check_if_exists(&install_dir, &tag_name) - && !confirm_menu(format!( - "Version {tag_name} exists in installation path. Overwrite?" - ))) + !(install_dirs + .iter() + .any(|install_dir| files::check_if_exists(install_dir, tag_name)) + && !confirm_menu( + format!("Version {tag_name} exists in the installation path. Overwrite?"), + String::from("If you choose yes, you will re-install it."), + false, + )) }); - // install the versions that are in the tags array - for tag_name in tags { + // install the versions that are in the tags array, into the locations that are in the install_dirs array + for tag_name in tags.clone() { let tag = match github::fetch_data_from_tag(&tag_name, &source).await { Ok(data) => data, Err(e) => { @@ -366,8 +275,13 @@ async fn main() { } }; - match download_file(&tag_name, &install_dir, &source).await { - Ok(_) => {} + match download_file(&tag_name, &source).await { + Ok(file) => { + // TODO: should just upack once and copy to all folders + for install_path in &install_dirs { + unpack_file(&file, install_path, &source).await.unwrap(); + } + } Err(e) => { eprintln!( "Error downloading {}, make sure you're connected to the internet\nError: {}", @@ -378,163 +292,48 @@ async fn main() { } } -pub async fn download_file( - tag: &str, - install_path: &str, - source: ¶meters::VariantParameters, -) -> Result<(), String> { - let install_dir = utils::expand_tilde(install_path).unwrap(); - let mut temp_dir = utils::expand_tilde(constants::TEMP_DIR).unwrap(); - - let download = match github::fetch_data_from_tag(tag, &source).await { - Ok(data) => data, - Err(e) => { - eprintln!("Failed to fetch GitHub data, make sure you're connected to the internet\nError: {}", e); - std::process::exit(1) - } - }; - - temp_dir.push(if download.download_url.ends_with("tar.gz") { - format!("{}.tar.gz", &download.version) - } else if download.download_url.ends_with("tar.xz") { - format!("{}.tar.xz", &download.version) - } else { - eprintln!("Downloaded file wasn't of the expected type. tar.(gz/xz)"); - std::process::exit(1) - }); - - // install_dir - create_dir_all(&install_dir).unwrap(); - - let git_hash = file::download_sha512_into_memory(&download.sha512sum_url) - .await - .unwrap(); - - if temp_dir.exists() { - fs::remove_file(&temp_dir).unwrap(); - } - - let (progress, done) = file::create_progress_trackers(); - let progress_read = Arc::clone(&progress); - let done_read = Arc::clone(&done); - let url = String::from(&download.download_url); - let tmp_dir = String::from(temp_dir.to_str().unwrap()); - - // start ProgressBar in another thread - thread::spawn(move || { - let pb = ProgressBar::with_draw_target( - Some(download.size), - ProgressDrawTarget::stderr_with_hz(20), - ); - pb.set_style(ProgressStyle::default_bar() - .template("{msg}\n{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec})").unwrap() - .progress_chars("#>-")); - pb.set_message(format!("Downloading {}", url.split('/').last().unwrap())); - let wait_time = Duration::from_millis(50); // 50ms wait is about 20Hz - loop { - let newpos = progress_read.load(Ordering::Relaxed); - pb.set_position(newpos as u64); - if done_read.load(Ordering::Relaxed) { - break; - } - thread::sleep(wait_time); - } - pb.set_message(format!("Downloaded {url} to {tmp_dir}")); - pb.abandon(); // closes progress bar without blanking terminal - - println!("Checking file integrity"); // This is being printed here because the progress bar needs to be closed before printing. - }); - - file::download_file_progress( - download.download_url, - download.size, - temp_dir.clone().as_path(), - progress, - done, - ) - .await - .unwrap(); - if !file::hash_check_file(temp_dir.to_str().unwrap().to_string(), git_hash).unwrap() { - return Err("Failed checking file hash".to_string()); - } - println!("Unpacking files into install location. Please wait"); - file::decompress(temp_dir.as_path(), install_dir.clone().as_path()).unwrap(); - let source_type = source.variant_type(); - println!( - "Done! Restart {}. {} installed in {}", - source_type.intended_application(), - source_type.to_string(), - install_dir.to_string_lossy(), - ); - Ok(()) -} - async fn run_quick_downloads() -> bool { - let Opt { - quick_download, - quick_download_flatpak, - lutris_quick_download, - lutris_quick_download_flatpak, - } = Opt::parse(); + let Opt { quick_download } = Opt::parse(); if quick_download { - let source = parameters::Variant::GEProton; - let destination = constants::DEFAULT_STEAM_INSTALL_DIR.to_string(); - println!( - "\nQuick Download: {} / {} into -> {}\n", - source.to_string(), - source.intended_application(), - destination - ); - download_file("latest", &destination, &source.parameters()) - .await - .unwrap(); - } - - if quick_download_flatpak { - let source = parameters::Variant::GEProton; - let destination = constants::DEFAULT_STEAM_INSTALL_DIR_FLATPAK.to_string(); - println!( - "\nQuick Download: {} / {} into -> {}\n", - source.to_string(), - source.intended_application(), - destination - ); - download_file("latest", &destination, &source.parameters()) - .await - .unwrap(); - } - - if lutris_quick_download { - let source = parameters::Variant::WineGE; - let destination = constants::DEFAULT_LUTRIS_INSTALL_DIR.to_string(); + let found_apps = apps::list_installed_apps(); + if found_apps.is_empty() { + println!("No apps found. Please install at least one app before using this feature."); + return false; + } println!( - "\nQuick Download: {} / {} into -> {}\n", - source.to_string(), - source.intended_application(), - destination + "Found the following apps: {}", + found_apps + .iter() + .map(|app| app.to_string()) + .collect::>() + .join(", ") ); - download_file("latest", &destination, &source.parameters()) - .await - .unwrap(); - } - if lutris_quick_download_flatpak { - let source = parameters::Variant::WineGE; - let destination = constants::DEFAULT_LUTRIS_INSTALL_DIR_FLATPAK.to_string(); - println!( - "\nQuick Download: {} / {} into -> {}\n", - source.to_string(), - source.intended_application(), - destination - ); - download_file("latest", &destination, &source.parameters()) - .await - .unwrap(); + for app_inst in &found_apps { + let variant = app_inst.into_app().app_default_variant(); + let destination = app_inst.default_install_dir().to_string(); + println!( + "\nQuick Download: {} for {} into -> {}", + variant, + app_inst.into_app(), + destination + ); + let file = download_file("latest", &variant.parameters()) + .await + .unwrap(); + unpack_file(&file, &destination, &variant.parameters()) + .await + .unwrap_or_else(|e| { + eprintln!( + "Failed unpacking file {} into {}. Error: {}", + file.to_string_lossy(), + destination, + e + ); + }); + } } - return quick_download - || quick_download_flatpak - || lutris_quick_download - || lutris_quick_download_flatpak; + quick_download } diff --git a/protonup-rs/src/manage_apps.rs b/protonup-rs/src/manage_apps.rs new file mode 100644 index 0000000..7a5d04f --- /dev/null +++ b/protonup-rs/src/manage_apps.rs @@ -0,0 +1,106 @@ +use inquire::MultiSelect; +use libprotonup::{apps, files}; +use std::fmt; + +use super::helper_menus::{confirm_menu, tag_menu}; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub(crate) enum ManageAppsMenuOptions { + DetectAll, + AppInstallations(apps::AppInstallations), +} + +// APP_VARIANTS_WITH_DETECT contains all variants of the App enum including the DetectAll variant +static APP_VARIANTS_WITH_DETECT: &[ManageAppsMenuOptions] = &[ + ManageAppsMenuOptions::DetectAll, + ManageAppsMenuOptions::AppInstallations(apps::AppInstallations::Steam), + ManageAppsMenuOptions::AppInstallations(apps::AppInstallations::SteamFlatpak), + ManageAppsMenuOptions::AppInstallations(apps::AppInstallations::Lutris), + ManageAppsMenuOptions::AppInstallations(apps::AppInstallations::LutrisFlatpak), +]; + +impl fmt::Display for ManageAppsMenuOptions { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self { + Self::DetectAll => write!(f, "Detect All"), + Self::AppInstallations(app_inst) => write!(f, "{}", app_inst), + } + } +} + +fn manage_menu() -> Vec { + let answer = MultiSelect::new( + "Select the Applications you want to manage :", + APP_VARIANTS_WITH_DETECT.to_vec(), + ) + .with_default(&[0_usize]) + .prompt(); + + match answer { + Ok(list) => list, + + Err(_) => { + println!("The tag list could not be processed"); + vec![] + } + } +} + +pub(crate) fn manage_apps_routine() { + let mut apps = vec![]; + + let choices = manage_menu(); + + if choices.contains(&ManageAppsMenuOptions::DetectAll) { + apps = apps::APP_INSTALLATIONS_VARIANTS.to_vec(); + } + for app in apps { + let versions = match app.list_installed_versions() { + Ok(versions) => versions, + Err(_) => { + println!("App {} not found in your system, skipping... ", app); + continue; + } + }; + if versions.is_empty() { + println!("No versions found for {}, skipping... ", app); + continue; + } + let delete_versions = match tag_menu( + &format!("Select the versions you want to DELETE from {}", app), + versions, + ) { + Ok(versions) => versions, + Err(_) => { + vec![] + } + }; + + if delete_versions.is_empty() { + println!("Zero versions selected for {}, skipping...\n", app); + continue; + } + if confirm_menu( + format!("Are you sure you want to delete {:?} ?", delete_versions), + format!("If you choose yes, you will them from {}", app), + true, + ) { + for version in delete_versions { + files::remove_dir_all(&format!("{}{}", &app.default_install_dir(), &version)) + .map_or_else( + |e| { + eprintln!( + "Error deleting {}{}: {}", + &app.default_install_dir(), + &version, + e + ) + }, + |_| { + println!("{} {} deleted successfully", &app, &version); + }, + ); + } + } + } +}