From d021100ed5dd728e72797b077539ddcadcee0a58 Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 24 Feb 2026 10:49:42 +0300 Subject: [PATCH 01/15] feat(rclone.exe): added Strict for rclone This strict will help to install rclone in bin dependencies of my project --- src/rcloneInstall.rs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/rcloneInstall.rs diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs new file mode 100644 index 0000000..e63bd42 --- /dev/null +++ b/src/rcloneInstall.rs @@ -0,0 +1,6 @@ +pub struct RcloneApp { + rclone_path: PathBuf, +} + +impl RcloneApp { +} From c43d4fdf9c44a9fd6fc3b00a73fcd789987371a2 Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 24 Feb 2026 10:56:48 +0300 Subject: [PATCH 02/15] feat(rclone.exe): Function new() This function first of all created app object by 1) Defining the application directory 2) Creating dirs if they are not exists 3) Defining ways for rclone by yours os 4) Define rclone or install it --- src/rcloneInstall.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs index e63bd42..7cacb94 100644 --- a/src/rcloneInstall.rs +++ b/src/rcloneInstall.rs @@ -1,6 +1,28 @@ +use std::fs; +use std::path::PathBuf; +use std::process::Command; + pub struct RcloneApp { rclone_path: PathBuf, } impl RcloneApp { + pub fn new() -> Result> { + let app_dir = dirs::data_dir() + .ok_or("Не удалось найти папку для данных")? + .join("rclone-ui"); + + fs::create_dir_all(&app_dir)?; + let rclone_path = if cfg!(windows) { + app_dir.join("rclone.exe") + } else { + app_dir.join("rclone") + }; + + if !rclone_path.exists() { + Self::extract_rclone(&rclone_path)?; + } + + Ok(Self { rclone_path }) + } } From 281406a92033d4874f6fe7b334a1362acb9b3527 Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 24 Feb 2026 11:03:23 +0300 Subject: [PATCH 03/15] feat(rclone.exe): method extract_rclone(): extracts the internal binary --- src/rcloneInstall.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs index 7cacb94..7534c18 100644 --- a/src/rcloneInstall.rs +++ b/src/rcloneInstall.rs @@ -25,4 +25,31 @@ impl RcloneApp { Ok(Self { rclone_path }) } + + fn extract_rclone(dest_path: &PathBuf) -> Result<(), Box> { + println!("Устанавливаю rclone в {:?}", dest_path); + + let rclone_bytes = if cfg!(windows) { + include_bytes!("../bin/rclone.exe") + } else if cfg!(target_os = "linux") { + include_bytes!("../bin/rclone") + } else if cfg!(target_os = "macos") { + include_bytes!("../bin/rclone") + } else { + panic!("Неподдерживаемая ОС"); + }; + + fs::write(dest_path, rclone_bytes)?; + + #[cfg(not(windows))] + { + use std::os::unix::fs::PermissionsExt; + let mut perms = fs::metadata(dest_path)?.permissions(); + perms.set_mode(0o755); // rwxr-xr-x + fs::set_permissions(dest_path, perms)?; + } + + println!("rclone успешно установлен!"); + Ok(()) + } } From 5ccc7739b0f4b32768e8ea90f85bcb88396a1fb1 Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 24 Feb 2026 11:05:30 +0300 Subject: [PATCH 04/15] feat(rclone.exe): method run_command Added for executes command to rclone utility --- src/rcloneInstall.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs index 7534c18..7011e11 100644 --- a/src/rcloneInstall.rs +++ b/src/rcloneInstall.rs @@ -52,4 +52,23 @@ impl RcloneApp { println!("rclone успешно установлен!"); Ok(()) } + + pub fn run_command(&self, args: &[&str]) -> Result { + println!( + "Запускаю: {} {}", + self.rclone_path.display(), + args.join(" ") + ); + + let output = Command::new(&self.rclone_path) + .args(args) + .output() + .map_err(|e| format!("Ошибка запуска: {}", e))?; + + if output.status.success() { + Ok(String::from_utf8_lossy(&output.stdout).to_string()) + } else { + Err(String::from_utf8_lossy(&output.stderr).to_string()) + } + } } From ac8169955657ec8c196dd274171505bb80691779 Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 24 Feb 2026 11:07:11 +0300 Subject: [PATCH 05/15] sys: Added dependencies data --- Cargo.lock | 358 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + 2 files changed, 360 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 10a8126..4faefdd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,3 +5,361 @@ version = 4 [[package]] name = "UIrclone" version = "0.1.0" +dependencies = [ + "dirs", + "which", +] + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" diff --git a/Cargo.toml b/Cargo.toml index 529232a..0ba83c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] +dirs = "5.0" +which = "6.0" From 2efac086d0dc4fba3679daa39ebf4e10a0ea73b4 Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 24 Feb 2026 11:26:16 +0300 Subject: [PATCH 06/15] feat(rclone.exe): Rewrite rclone This rewriting is important because the old version of code can`t use system rclone (if it hed been installed already) --- src/rcloneInstall.rs | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs index 7011e11..4b568f4 100644 --- a/src/rcloneInstall.rs +++ b/src/rcloneInstall.rs @@ -4,10 +4,20 @@ use std::process::Command; pub struct RcloneApp { rclone_path: PathBuf, + using_system_rclone: bool, } impl RcloneApp { pub fn new() -> Result> { + if let Some(system_rclone) = Self::check_system_rclone() { + println!("Найден системный rclone: {:?}", system_rclone); + return Ok(Self { + rclone_path: system_rclone, + using_system_rclone: true, + }); + } + println!("Системный rclone не найден, использую встроенную версию"); + let app_dir = dirs::data_dir() .ok_or("Не удалось найти папку для данных")? .join("rclone-ui"); @@ -23,7 +33,25 @@ impl RcloneApp { Self::extract_rclone(&rclone_path)?; } - Ok(Self { rclone_path }) + Ok(Self { + rclone_path, + using_system_rclone: false, + }) + } + + fn check_system_rclone() -> Option { + if let Ok(path) = which::which("rclone") { + return Some(path); + } + + #[cfg(windows)] + { + if let Ok(path) = which::which("rclone.exe") { + return Some(path); + } + } + + None } fn extract_rclone(dest_path: &PathBuf) -> Result<(), Box> { @@ -45,7 +73,7 @@ impl RcloneApp { { use std::os::unix::fs::PermissionsExt; let mut perms = fs::metadata(dest_path)?.permissions(); - perms.set_mode(0o755); // rwxr-xr-x + perms.set_mode(0o755); fs::set_permissions(dest_path, perms)?; } @@ -53,13 +81,7 @@ impl RcloneApp { Ok(()) } - pub fn run_command(&self, args: &[&str]) -> Result { - println!( - "Запускаю: {} {}", - self.rclone_path.display(), - args.join(" ") - ); - + fn run_command(&self, args: &[&str]) -> Result { let output = Command::new(&self.rclone_path) .args(args) .output() From d3321bc672ada9f19302cc7ae623e67a489a12f6 Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 24 Feb 2026 11:30:24 +0300 Subject: [PATCH 07/15] feat(main): Added code for check by ci --- src/main.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index e7a11a9..a978930 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,13 @@ +mod rcloneInstall; + +use rcloneInstall::RcloneApp; + fn main() { - println!("Hello, world!"); + let _app = match RcloneApp::new() { + Ok(app) => app, + Err(e) => { + eprintln!("Ошибка инициализации: {}", e); + panic!("{}", e); + } + }; } From cac7ce922e26b4b877c3e2a7f5cc12cf0f73f375 Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 27 Feb 2026 16:43:00 +0300 Subject: [PATCH 08/15] feat(rclone.exe): Install rclone from github --- Cargo.lock | 1638 +++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 7 + src/main.rs | 16 +- src/rcloneInstall.rs | 256 ++++++- 4 files changed, 1890 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4faefdd..acf5771 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,21 +7,208 @@ name = "UIrclone" version = "0.1.0" dependencies = [ "dirs", + "flate2", + "futures", + "reqwest", + "serde_json", + "tar", + "tokio", "which", + "zip", ] +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.13+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.2.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "dirs" version = "5.0.1" @@ -43,12 +230,38 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.14" @@ -59,6 +272,146 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "filetime" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +dependencies = [ + "cfg-if", + "libc", + "libredox", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -70,6 +423,52 @@ dependencies = [ "wasi", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.12" @@ -79,6 +478,231 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4eacb0641a310445a4c513f2a5e23e19952e269c6a38887254d5f837a305506" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.182" @@ -91,8 +715,9 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags", + "bitflags 2.11.0", "libc", + "redox_syscall 0.7.1", ] [[package]] @@ -101,12 +726,163 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "proc-macro2" version = "1.0.106" @@ -125,30 +901,331 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.17", "libredox", "thiserror", ] +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustix" version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.15", "windows-sys 0.59.0", ] +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.117" @@ -160,6 +1237,55 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -180,18 +1306,271 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.6.2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d7d0fce354c88b7982aec4400b3e7fcf723c32737cef571bd165f7613557ee" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee85afca410ac4abba5b584b12e77ea225db6ee5471d0aebaae0861166f9378a" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55839b71ba921e4f75b674cb16f843f4b1f3b26ddfcb3454de1cf65cc021ec0f" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf2e969c2d60ff52e7e98b7392ff1588bffdd1ccd4769eba27222fd3d621571" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0861f0dcdf46ea819407495634953cdcc8a8c7215ab799a7a7ce366be71c7b30" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10053fbf9a374174094915bbce141e87a6bf32ecd9a002980db4b638405e8962" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "which" version = "6.0.3" @@ -200,7 +1579,7 @@ checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" dependencies = [ "either", "home", - "rustix", + "rustix 0.38.44", "winsafe", ] @@ -219,6 +1598,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -228,6 +1616,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -261,13 +1658,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -280,6 +1694,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -292,6 +1712,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -304,12 +1730,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -322,6 +1760,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -334,6 +1778,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -346,6 +1796,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -358,8 +1814,178 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "winsafe" version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix 1.1.4", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 0ba83c3..6d8312a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,12 @@ version = "0.1.0" edition = "2024" [dependencies] +tokio = { version = "1.0", features = ["full"] } +reqwest = { version = "0.11", default-features = false, features = ["rustls-tls", "json", "stream"] } +futures = "0.3" +flate2 = "1.0" +tar = "0.4" +zip = "0.6" dirs = "5.0" which = "6.0" +serde_json = "1.0" diff --git a/src/main.rs b/src/main.rs index a978930..fe86e97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,11 @@ mod rcloneInstall; -use rcloneInstall::RcloneApp; +//use rcloneInstall::RcloneApp; -fn main() { - let _app = match RcloneApp::new() { - Ok(app) => app, - Err(e) => { - eprintln!("Ошибка инициализации: {}", e); - panic!("{}", e); - } - }; +use tokio::runtime::Runtime; + +fn main() -> Result<(), Box> { + let rt = Runtime::new()?; + rt.block_on(rcloneInstall::install_latest_rclone())?; + Ok(()) } diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs index 4b568f4..8843d01 100644 --- a/src/rcloneInstall.rs +++ b/src/rcloneInstall.rs @@ -1,6 +1,11 @@ +use flate2::read::GzDecoder; +use reqwest; use std::fs; +use std::io::Cursor; use std::path::PathBuf; use std::process::Command; +use tar::Archive; +use tokio; pub struct RcloneApp { rclone_path: PathBuf, @@ -29,9 +34,9 @@ impl RcloneApp { app_dir.join("rclone") }; - if !rclone_path.exists() { + /*if !rclone_path.exists() { Self::extract_rclone(&rclone_path)?; - } + }*/ Ok(Self { rclone_path, @@ -54,17 +59,20 @@ impl RcloneApp { None } - fn extract_rclone(dest_path: &PathBuf) -> Result<(), Box> { + /*fn extract_rclone(dest_path: &PathBuf) -> Result<(), Box> { println!("Устанавливаю rclone в {:?}", dest_path); - let rclone_bytes = if cfg!(windows) { - include_bytes!("../bin/rclone.exe") - } else if cfg!(target_os = "linux") { - include_bytes!("../bin/rclone") - } else if cfg!(target_os = "macos") { - include_bytes!("../bin/rclone") - } else { - panic!("Неподдерживаемая ОС"); + let rclone_bytes = unsafe { + // unsafe блок, возвращающий значение + if cfg!(windows) { + include_bytes!("../bin/rclone.exe") + } else if cfg!(target_os = "linux") { + include_bytes!("../bin/rclone") + } else if cfg!(target_os = "macos") { + include_bytes!("../bin/rclone") + } else { + panic!("Неподдерживаемая ОС"); + } }; fs::write(dest_path, rclone_bytes)?; @@ -79,7 +87,7 @@ impl RcloneApp { println!("rclone успешно установлен!"); Ok(()) - } + }*/ fn run_command(&self, args: &[&str]) -> Result { let output = Command::new(&self.rclone_path) @@ -94,3 +102,227 @@ impl RcloneApp { } } } + +/// Асинхронная функция для проверки наличия и версии rclone +/// Возвращает: +/// 0 - rclone установлен и актуален +/// 1 - требуется установка или обновление +pub async fn check_rclone_status_async() -> Result> { + if let Some(system_rclone) = RcloneApp::check_system_rclone() { + println!("Найден системный rclone: n{:?}", system_rclone); + + let output = Command::new(&system_rclone) + .arg("version") + .output() + .map_err(|e| format!("Ошибка получения версии: {}", e))?; + + if output.status.success() { + let version_output = String::from_utf8_lossy(&output.stdout); + println!("Версия rclone: {}", version_output); + + if is_version_recent(&version_output) { + return Ok(0); + } else { + println!("Версия rclone устарела, требуется обновление"); + return Ok(1); + } + } + } + + let app_dir = dirs::data_dir() + .ok_or("Не удалось найти папку для данных")? + .join("rclone-ui"); + + let rclone_path = if cfg!(windows) { + app_dir.join("rclone.exe") + } else { + app_dir.join("rclone") + }; + + if rclone_path.exists() { + println!("Найден rclone в директории приложения"); + + let output = Command::new(&rclone_path) + .arg("version") + .output() + .map_err(|e| format!("Ошибка получения версии: {}", e))?; + + if output.status.success() { + let version_output = String::from_utf8_lossy(&output.stdout); + + if is_version_recent(&version_output) { + return Ok(0); + } else { + println!("Версия rclone в директории приложения устарела"); + return Ok(1); + } + } + } + + println!("rclone не найден, требуется установка"); + Ok(1) +} + +/// Вспомогательная функция для проверки актуальности версии +fn is_version_recent(version_output: &str) -> bool { + !version_output.contains("rclone v1.55") +} + +/// Асинхронная функция для установки последней версии rclone из GitHub +pub async fn install_latest_rclone() -> Result> { + println!("Начинаю установку последней версии rclone..."); + + let os = if cfg!(target_os = "linux") { + "linux" + } else if cfg!(target_os = "macos") { + "osx" + } else if cfg!(target_os = "windows") { + "windows" + } else { + return Err("Неподдерживаемая операционная система".into()); + }; + + let arch = if cfg!(target_arch = "x86_64") { + "amd64" + } else if cfg!(target_arch = "aarch64") { + "arm64" + } else if cfg!(target_arch = "arm") { + "arm" + } else { + return Err("Неподдерживаемая архитектура".into()); + }; + + // Получаем актуальную версию через API GitHub + let client = reqwest::Client::new(); + let latest_release: serde_json::Value = client + .get("https://api.github.com/repos/rclone/rclone/releases/latest") + .header("User-Agent", "rclone-ui-installer") + .send() + .await? + .json() + .await?; + + let version = latest_release["tag_name"] + .as_str() + .ok_or("Не удалось получить версию")? + .trim_start_matches('v'); // Убираем 'v' из начала версии если есть + + // Всегда используем .zip формат для всех ОС + let download_url = format!( + "https://github.com/rclone/rclone/releases/download/v{}/rclone-v{}-{}-{}.zip", + version, version, os, arch + ); + + println!("Скачиваю rclone с: {}", download_url); + + let response = client.get(&download_url).send().await?; + + if !response.status().is_success() { + return Err(format!("Ошибка скачивания: HTTP {}", response.status()).into()); + } + + let bytes = response.bytes().await?; + + let app_dir = dirs::data_dir() + .ok_or("Не удалось найти папку для данных")? + .join("rclone-ui"); + + fs::create_dir_all(&app_dir)?; + + // Определяем имя исполняемого файла в зависимости от ОС + let rclone_filename = if cfg!(windows) { + "rclone.exe" + } else { + "rclone" + }; + let rclone_path = app_dir.join(rclone_filename); + + // Распаковываем zip архив (для всех ОС) + use std::io::Cursor; + use zip::read::ZipArchive; + + let cursor = Cursor::new(bytes); + let mut archive = ZipArchive::new(cursor)?; + + let mut extracted = false; + + for i in 0..archive.len() { + let mut file = archive.by_index(i)?; + let file_name = file.name().to_string(); // Сохраняем имя в отдельную переменную + + // Ищем файл rclone или rclone.exe в архиве + if file_name.ends_with("rclone") || file_name.ends_with("rclone.exe") { + // Определяем путь для распаковки + let output_path = if file_name.contains('/') || file_name.contains('\\') { + // Если файл в подпапке, создаем временный путь + let temp_path = app_dir.join("temp_rclone"); + fs::create_dir_all(&temp_path)?; + temp_path.join( + file_name + .split(|c| c == '/' || c == '\\') + .last() + .unwrap_or(rclone_filename), + ) + } else { + app_dir.join(&file_name) + }; + + // Распаковываем файл + let mut contents = Vec::new(); + std::io::copy(&mut file, &mut contents)?; + fs::write(&output_path, contents)?; + + // Перемещаем в нужное место если необходимо + if output_path != rclone_path { + if rclone_path.exists() { + fs::remove_file(&rclone_path)?; + } + fs::rename(output_path, &rclone_path)?; + } + + extracted = true; + println!("Найден и распакован: {}", file_name); + break; + } + } + + if !extracted { + return Err("Не удалось найти исполняемый файл rclone в архиве".into()); + } + + // Удаляем временную папку если она была создана + let temp_path = app_dir.join("temp_rclone"); + if temp_path.exists() { + fs::remove_dir_all(temp_path)?; + } + + // Устанавливаем права на выполнение для Unix систем + #[cfg(not(windows))] + { + use std::os::unix::fs::PermissionsExt; + let mut perms = fs::metadata(&rclone_path)?.permissions(); + perms.set_mode(0o755); + fs::set_permissions(&rclone_path, perms)?; + } + + println!("rclone успешно установлен в {:?}", rclone_path); + + // Проверяем установку + let output = Command::new(&rclone_path) + .arg("version") + .output() + .map_err(|e| format!("Ошибка проверки установки: {}", e))?; + + if output.status.success() { + let version_output = String::from_utf8_lossy(&output.stdout); + println!("Установленная версия rclone:\n{}", version_output); + } else { + let error = String::from_utf8_lossy(&output.stderr); + return Err(format!("Ошибка при проверке версии rclone: {}", error).into()); + } + + Ok(RcloneApp { + rclone_path, + using_system_rclone: false, + }) +} From a8af4b4abfb68050a3874b566a46fb3509d5eb9d Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 27 Feb 2026 17:19:11 +0300 Subject: [PATCH 09/15] ci: Added based ci --- .forgejo/workflows/main.yaml | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .forgejo/workflows/main.yaml diff --git a/.forgejo/workflows/main.yaml b/.forgejo/workflows/main.yaml new file mode 100644 index 0000000..68e39d6 --- /dev/null +++ b/.forgejo/workflows/main.yaml @@ -0,0 +1,40 @@ +name: Rust CI +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal + echo "$HOME/.cargo/bin" >> $GITHUB_PATH + + - name: Verify Rust installation + run: | + rustc --version + cargo --version + + - name: Build + run: cargo build --verbose + + - name: Test + run: cargo test --verbose + + - name: Build documentation + run: cargo doc --no-deps --document-private-items + + - name: Upload documentation as artifact + uses: actions/upload-artifact@v4 + with: + name: rust-documentation + path: target/doc/ + retention-days: 30 + if-no-files-found: error From 5c26c57efe2e9800e11ac084a605a0cca3b94497 Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 27 Feb 2026 17:20:42 +0300 Subject: [PATCH 10/15] fix: Fix some logic 1) Now code checking lockal rclone before install it 2) fix function to install rclone on device if it doesn`t exists --- src/rcloneInstall.rs | 376 ++++++++++++++----------------------------- 1 file changed, 125 insertions(+), 251 deletions(-) diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs index 8843d01..6884c8e 100644 --- a/src/rcloneInstall.rs +++ b/src/rcloneInstall.rs @@ -13,7 +13,8 @@ pub struct RcloneApp { } impl RcloneApp { - pub fn new() -> Result> { + pub async fn new() -> Result> { + // Сначала проверяем системный rclone if let Some(system_rclone) = Self::check_system_rclone() { println!("Найден системный rclone: {:?}", system_rclone); return Ok(Self { @@ -21,27 +22,29 @@ impl RcloneApp { using_system_rclone: true, }); } - println!("Системный rclone не найден, использую встроенную версию"); + // Проверяем в директории приложения let app_dir = dirs::data_dir() .ok_or("Не удалось найти папку для данных")? .join("rclone-ui"); - fs::create_dir_all(&app_dir)?; let rclone_path = if cfg!(windows) { app_dir.join("rclone.exe") } else { app_dir.join("rclone") }; - /*if !rclone_path.exists() { - Self::extract_rclone(&rclone_path)?; - }*/ + if rclone_path.exists() { + println!("Найден rclone в директории приложения: {:?}", rclone_path); + return Ok(Self { + rclone_path, + using_system_rclone: false, + }); + } - Ok(Self { - rclone_path, - using_system_rclone: false, - }) + // Если ничего не найдено - устанавливаем + println!("rclone не найден. Начинаю установку..."); + Self::install_latest_rclone().await } fn check_system_rclone() -> Option { @@ -59,35 +62,126 @@ impl RcloneApp { None } - /*fn extract_rclone(dest_path: &PathBuf) -> Result<(), Box> { - println!("Устанавливаю rclone в {:?}", dest_path); + async fn install_latest_rclone() -> Result> { + println!("Начинаю установку последней версии rclone..."); - let rclone_bytes = unsafe { - // unsafe блок, возвращающий значение - if cfg!(windows) { - include_bytes!("../bin/rclone.exe") - } else if cfg!(target_os = "linux") { - include_bytes!("../bin/rclone") - } else if cfg!(target_os = "macos") { - include_bytes!("../bin/rclone") - } else { - panic!("Неподдерживаемая ОС"); - } + // Определяем ОС и архитектуру + let os = if cfg!(target_os = "linux") { + "linux" + } else if cfg!(target_os = "macos") { + "osx" + } else if cfg!(target_os = "windows") { + "windows" + } else { + return Err("Неподдерживаемая операционная система".into()); }; - fs::write(dest_path, rclone_bytes)?; + let arch = if cfg!(target_arch = "x86_64") { + "amd64" + } else if cfg!(target_arch = "aarch64") { + "arm64" + } else if cfg!(target_arch = "arm") { + "arm" + } else { + return Err("Неподдерживаемая архитектура".into()); + }; + // Получаем информацию о последнем релизе + let client = reqwest::Client::new(); + let latest_release: serde_json::Value = client + .get("https://api.github.com/repos/rclone/rclone/releases/latest") + .header("User-Agent", "rclone-ui-installer") + .send() + .await? + .json() + .await?; + + let version = latest_release["tag_name"] + .as_str() + .ok_or("Не удалось получить версию")? + .trim_start_matches('v'); + + // Формируем URL для скачивания + let download_url = format!( + "https://github.com/rclone/rclone/releases/download/v{}/rclone-v{}-{}-{}.zip", + version, version, os, arch + ); + + println!("Скачиваю rclone версии {} с: {}", version, download_url); + + // Скачиваем архив + let response = client.get(&download_url).send().await?; + if !response.status().is_success() { + return Err(format!("Ошибка скачивания: HTTP {}", response.status()).into()); + } + + let bytes = response.bytes().await?; + + // Создаем директорию приложения + let app_dir = dirs::data_dir() + .ok_or("Не удалось найти папку для данных")? + .join("rclone-ui"); + fs::create_dir_all(&app_dir)?; + + // Определяем имя исполняемого файла + let rclone_filename = if cfg!(windows) { + "rclone.exe" + } else { + "rclone" + }; + let rclone_path = app_dir.join(rclone_filename); + + // Распаковываем архив + use zip::read::ZipArchive; + let cursor = Cursor::new(bytes); + let mut archive = ZipArchive::new(cursor)?; + + let mut extracted = false; + for i in 0..archive.len() { + let mut file = archive.by_index(i)?; + let file_name = file.name().to_string(); + + if file_name.ends_with("rclone") || file_name.ends_with("rclone.exe") { + let mut contents = Vec::new(); + std::io::copy(&mut file, &mut contents)?; + fs::write(&rclone_path, contents)?; + extracted = true; + println!("Найден и распакован: {}", file_name); + break; + } + } + + if !extracted { + return Err("Не удалось найти исполняемый файл rclone в архиве".into()); + } + + // Устанавливаем права на выполнение для Unix систем #[cfg(not(windows))] { use std::os::unix::fs::PermissionsExt; - let mut perms = fs::metadata(dest_path)?.permissions(); + let mut perms = fs::metadata(&rclone_path)?.permissions(); perms.set_mode(0o755); - fs::set_permissions(dest_path, perms)?; + fs::set_permissions(&rclone_path, perms)?; } - println!("rclone успешно установлен!"); - Ok(()) - }*/ + println!("rclone успешно установлен в {:?}", rclone_path); + + // Проверяем установку + let output = Command::new(&rclone_path) + .arg("version") + .output() + .map_err(|e| format!("Ошибка проверки установки: {}", e))?; + + if output.status.success() { + let version_output = String::from_utf8_lossy(&output.stdout); + println!("Установленная версия rclone:\n{}", version_output); + } + + Ok(Self { + rclone_path, + using_system_rclone: false, + }) + } fn run_command(&self, args: &[&str]) -> Result { let output = Command::new(&self.rclone_path) @@ -101,228 +195,8 @@ impl RcloneApp { Err(String::from_utf8_lossy(&output.stderr).to_string()) } } -} -/// Асинхронная функция для проверки наличия и версии rclone -/// Возвращает: -/// 0 - rclone установлен и актуален -/// 1 - требуется установка или обновление -pub async fn check_rclone_status_async() -> Result> { - if let Some(system_rclone) = RcloneApp::check_system_rclone() { - println!("Найден системный rclone: n{:?}", system_rclone); - - let output = Command::new(&system_rclone) - .arg("version") - .output() - .map_err(|e| format!("Ошибка получения версии: {}", e))?; - - if output.status.success() { - let version_output = String::from_utf8_lossy(&output.stdout); - println!("Версия rclone: {}", version_output); - - if is_version_recent(&version_output) { - return Ok(0); - } else { - println!("Версия rclone устарела, требуется обновление"); - return Ok(1); - } - } - } - - let app_dir = dirs::data_dir() - .ok_or("Не удалось найти папку для данных")? - .join("rclone-ui"); - - let rclone_path = if cfg!(windows) { - app_dir.join("rclone.exe") - } else { - app_dir.join("rclone") - }; - - if rclone_path.exists() { - println!("Найден rclone в директории приложения"); - - let output = Command::new(&rclone_path) - .arg("version") - .output() - .map_err(|e| format!("Ошибка получения версии: {}", e))?; - - if output.status.success() { - let version_output = String::from_utf8_lossy(&output.stdout); - - if is_version_recent(&version_output) { - return Ok(0); - } else { - println!("Версия rclone в директории приложения устарела"); - return Ok(1); - } - } - } - - println!("rclone не найден, требуется установка"); - Ok(1) -} - -/// Вспомогательная функция для проверки актуальности версии -fn is_version_recent(version_output: &str) -> bool { - !version_output.contains("rclone v1.55") -} - -/// Асинхронная функция для установки последней версии rclone из GitHub -pub async fn install_latest_rclone() -> Result> { - println!("Начинаю установку последней версии rclone..."); - - let os = if cfg!(target_os = "linux") { - "linux" - } else if cfg!(target_os = "macos") { - "osx" - } else if cfg!(target_os = "windows") { - "windows" - } else { - return Err("Неподдерживаемая операционная система".into()); - }; - - let arch = if cfg!(target_arch = "x86_64") { - "amd64" - } else if cfg!(target_arch = "aarch64") { - "arm64" - } else if cfg!(target_arch = "arm") { - "arm" - } else { - return Err("Неподдерживаемая архитектура".into()); - }; - - // Получаем актуальную версию через API GitHub - let client = reqwest::Client::new(); - let latest_release: serde_json::Value = client - .get("https://api.github.com/repos/rclone/rclone/releases/latest") - .header("User-Agent", "rclone-ui-installer") - .send() - .await? - .json() - .await?; - - let version = latest_release["tag_name"] - .as_str() - .ok_or("Не удалось получить версию")? - .trim_start_matches('v'); // Убираем 'v' из начала версии если есть - - // Всегда используем .zip формат для всех ОС - let download_url = format!( - "https://github.com/rclone/rclone/releases/download/v{}/rclone-v{}-{}-{}.zip", - version, version, os, arch - ); - - println!("Скачиваю rclone с: {}", download_url); - - let response = client.get(&download_url).send().await?; - - if !response.status().is_success() { - return Err(format!("Ошибка скачивания: HTTP {}", response.status()).into()); - } - - let bytes = response.bytes().await?; - - let app_dir = dirs::data_dir() - .ok_or("Не удалось найти папку для данных")? - .join("rclone-ui"); - - fs::create_dir_all(&app_dir)?; - - // Определяем имя исполняемого файла в зависимости от ОС - let rclone_filename = if cfg!(windows) { - "rclone.exe" - } else { - "rclone" - }; - let rclone_path = app_dir.join(rclone_filename); - - // Распаковываем zip архив (для всех ОС) - use std::io::Cursor; - use zip::read::ZipArchive; - - let cursor = Cursor::new(bytes); - let mut archive = ZipArchive::new(cursor)?; - - let mut extracted = false; - - for i in 0..archive.len() { - let mut file = archive.by_index(i)?; - let file_name = file.name().to_string(); // Сохраняем имя в отдельную переменную - - // Ищем файл rclone или rclone.exe в архиве - if file_name.ends_with("rclone") || file_name.ends_with("rclone.exe") { - // Определяем путь для распаковки - let output_path = if file_name.contains('/') || file_name.contains('\\') { - // Если файл в подпапке, создаем временный путь - let temp_path = app_dir.join("temp_rclone"); - fs::create_dir_all(&temp_path)?; - temp_path.join( - file_name - .split(|c| c == '/' || c == '\\') - .last() - .unwrap_or(rclone_filename), - ) - } else { - app_dir.join(&file_name) - }; - - // Распаковываем файл - let mut contents = Vec::new(); - std::io::copy(&mut file, &mut contents)?; - fs::write(&output_path, contents)?; - - // Перемещаем в нужное место если необходимо - if output_path != rclone_path { - if rclone_path.exists() { - fs::remove_file(&rclone_path)?; - } - fs::rename(output_path, &rclone_path)?; - } - - extracted = true; - println!("Найден и распакован: {}", file_name); - break; - } + pub fn version(&self) -> Result { + self.run_command(&["version"]) } - - if !extracted { - return Err("Не удалось найти исполняемый файл rclone в архиве".into()); - } - - // Удаляем временную папку если она была создана - let temp_path = app_dir.join("temp_rclone"); - if temp_path.exists() { - fs::remove_dir_all(temp_path)?; - } - - // Устанавливаем права на выполнение для Unix систем - #[cfg(not(windows))] - { - use std::os::unix::fs::PermissionsExt; - let mut perms = fs::metadata(&rclone_path)?.permissions(); - perms.set_mode(0o755); - fs::set_permissions(&rclone_path, perms)?; - } - - println!("rclone успешно установлен в {:?}", rclone_path); - - // Проверяем установку - let output = Command::new(&rclone_path) - .arg("version") - .output() - .map_err(|e| format!("Ошибка проверки установки: {}", e))?; - - if output.status.success() { - let version_output = String::from_utf8_lossy(&output.stdout); - println!("Установленная версия rclone:\n{}", version_output); - } else { - let error = String::from_utf8_lossy(&output.stderr); - return Err(format!("Ошибка при проверке версии rclone: {}", error).into()); - } - - Ok(RcloneApp { - rclone_path, - using_system_rclone: false, - }) } From 700f4a171635479b05b1b1ef65b07ff3c76f9e36 Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 27 Feb 2026 17:24:41 +0300 Subject: [PATCH 11/15] fix: Rewrite main for CI --- src/main.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index fe86e97..bbf2a21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,17 @@ mod rcloneInstall; -//use rcloneInstall::RcloneApp; - use tokio::runtime::Runtime; fn main() -> Result<(), Box> { let rt = Runtime::new()?; - rt.block_on(rcloneInstall::install_latest_rclone())?; - Ok(()) + + let rclone = rt.block_on(async { + let rclone = rcloneInstall::RcloneApp::new().await?; + println!("rclone готов к использованию"); + Ok::<_, Box>(rclone) + })?; + + let v = rclone.version(); + println!("Rclone: {:?}", v); + Ok::<_, Box>(()) } From 265ee15846d7f62c875e0d13d7e893f46f61194b Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 27 Feb 2026 17:25:26 +0300 Subject: [PATCH 12/15] ci: fix saved Ci doks --- .forgejo/workflows/main.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/main.yaml b/.forgejo/workflows/main.yaml index 68e39d6..d995eba 100644 --- a/.forgejo/workflows/main.yaml +++ b/.forgejo/workflows/main.yaml @@ -30,11 +30,14 @@ jobs: - name: Build documentation run: cargo doc --no-deps --document-private-items - + + - name: Create docs directory + run: mkdir -p ./docs-output && cp -r target/doc/* ./docs-output/ + - name: Upload documentation as artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 # Понижена версия для совместимости с GHES with: name: rust-documentation - path: target/doc/ + path: ./docs-output/ retention-days: 30 if-no-files-found: error From de9232750ed7d44571372c8cc10e6ce6a5bbca0d Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 2 Mar 2026 13:45:35 +0300 Subject: [PATCH 13/15] feat(rclone.exe): added Setters, Getters, and Intialization Constructor --- src/rcloneInstall.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/rcloneInstall.rs b/src/rcloneInstall.rs index 6884c8e..5fefd96 100644 --- a/src/rcloneInstall.rs +++ b/src/rcloneInstall.rs @@ -47,7 +47,33 @@ impl RcloneApp { Self::install_latest_rclone().await } - fn check_system_rclone() -> Option { + // Публичный конструктор для тестов и создания экземпляра с заданными параметрами + pub fn new_with_path(rclone_path: PathBuf, using_system_rclone: bool) -> Self { + Self { + rclone_path, + using_system_rclone, + } + } + + // Геттеры + pub fn get_rclone_path(&self) -> &PathBuf { + &self.rclone_path + } + + pub fn is_using_system_rclone(&self) -> bool { + self.using_system_rclone + } + + // Сеттеры + pub fn set_rclone_path(&mut self, path: PathBuf) { + self.rclone_path = path; + } + + pub fn set_using_system_rclone(&mut self, value: bool) { + self.using_system_rclone = value; + } + + pub fn check_system_rclone() -> Option { if let Ok(path) = which::which("rclone") { return Some(path); } From c537893773c0732724e0a044e0b00c74d08bca56 Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 2 Mar 2026 13:46:42 +0300 Subject: [PATCH 14/15] tests: Added tests for installing rclone --- Cargo.lock | 344 ++++++++++++++++++++++++++++++++++-- Cargo.toml | 5 + src/tests.rs | 4 + src/tests/rclone_install.rs | 190 ++++++++++++++++++++ 4 files changed, 530 insertions(+), 13 deletions(-) create mode 100644 src/tests.rs create mode 100644 src/tests/rclone_install.rs diff --git a/Cargo.lock b/Cargo.lock index acf5771..da75339 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,9 +9,12 @@ dependencies = [ "dirs", "flate2", "futures", + "mockito", "reqwest", "serde_json", + "serial_test", "tar", + "tempfile", "tokio", "which", "zip", @@ -34,6 +37,31 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "base64" version = "0.21.7" @@ -133,6 +161,15 @@ dependencies = [ "inout", ] +[[package]] +name = "colored" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -189,6 +226,19 @@ dependencies = [ "typenum", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "deranged" version = "0.5.8" @@ -272,6 +322,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "filetime" version = "0.2.27" @@ -446,7 +502,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap", "slab", "tokio", @@ -454,6 +510,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.4.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.16.1" @@ -489,6 +570,16 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -496,7 +587,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.4.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -522,9 +636,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -536,6 +650,28 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2 0.4.13", + "http 1.4.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -543,13 +679,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.32", "rustls", "tokio", "tokio-rustls", ] +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "bytes", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", + "pin-project-lite", + "tokio", +] + [[package]] name = "icu_collections" version = "2.1.1" @@ -659,7 +809,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", ] [[package]] @@ -703,6 +853,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.182" @@ -786,6 +942,31 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "mockito" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90820618712cab19cfc46b274c6c22546a82affcb3c3bdf0f29e3db8e1bb92c0" +dependencies = [ + "assert-json-diff", + "bytes", + "colored", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "log", + "pin-project-lite", + "rand", + "regex", + "serde_json", + "serde_urlencoded", + "similar", + "tokio", +] + [[package]] name = "num-conv" version = "0.2.0" @@ -834,7 +1015,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -862,6 +1043,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.32" @@ -883,6 +1070,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -907,12 +1103,41 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -942,6 +1167,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + [[package]] name = "reqwest" version = "0.11.27" @@ -953,10 +1207,10 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", "hyper-rustls", "ipnet", "js-sys", @@ -1138,6 +1392,31 @@ dependencies = [ "serde", ] +[[package]] +name = "serial_test" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" +dependencies = [ + "dashmap", + "futures", + "lazy_static", + "log", + "parking_lot", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha1" version = "0.10.6" @@ -1182,6 +1461,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + [[package]] name = "slab" version = "0.4.12" @@ -1286,6 +1571,19 @@ dependencies = [ "xattr", ] +[[package]] +name = "tempfile" +version = "3.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -1881,6 +2179,26 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zerofrom" version = "0.1.6" diff --git a/Cargo.toml b/Cargo.toml index 6d8312a..49f4eab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,8 @@ zip = "0.6" dirs = "5.0" which = "6.0" serde_json = "1.0" + +[dev-dependencies] +tempfile = "3.8" +serial_test = "2.0" +mockito = "1.0" diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..b14e8b8 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,4 @@ +#[cfg(test)] +mod rclone_install; + + diff --git a/src/tests/rclone_install.rs b/src/tests/rclone_install.rs new file mode 100644 index 0000000..612d56b --- /dev/null +++ b/src/tests/rclone_install.rs @@ -0,0 +1,190 @@ +#[cfg(test)] +mod tests { + use crate::rcloneInstall::RcloneApp; + use std::fs; + use std::env; + use tempfile::tempdir; + use serial_test::serial; + + fn setup_test_dir() -> tempfile::TempDir { + tempdir().expect("Failed to create temp dir") + } + + #[test] + fn test_new_with_path_constructor() { + let temp_dir = setup_test_dir(); + let rclone_path = temp_dir.path().join("rclone"); + + let app = RcloneApp::new_with_path(rclone_path.clone(), true); + + assert_eq!(app.get_rclone_path(), &rclone_path); + assert!(app.is_using_system_rclone()); + } + + #[test] + fn test_getters() { + let temp_dir = setup_test_dir(); + let rclone_path = temp_dir.path().join("rclone"); + + let app = RcloneApp::new_with_path(rclone_path.clone(), true); + + assert_eq!(app.get_rclone_path(), &rclone_path); + assert!(app.is_using_system_rclone()); + } + + #[test] + fn test_setters() { + let temp_dir = setup_test_dir(); + let rclone_path1 = temp_dir.path().join("rclone1"); + let rclone_path2 = temp_dir.path().join("rclone2"); + + let mut app = RcloneApp::new_with_path(rclone_path1, false); + + assert!(!app.is_using_system_rclone()); + + app.set_using_system_rclone(true); + assert!(app.is_using_system_rclone()); + + app.set_rclone_path(rclone_path2.clone()); + assert_eq!(app.get_rclone_path(), &rclone_path2); + } + + #[test] + fn test_version_method_with_nonexistent_rclone() { + let temp_dir = setup_test_dir(); + let rclone_path = if cfg!(windows) { + temp_dir.path().join("rclone.exe") + } else { + temp_dir.path().join("rclone") + }; + + let app = RcloneApp::new_with_path(rclone_path, false); + + let result = app.version(); + assert!(result.is_err()); + } + + #[test] + fn test_version_method_with_mock_rclone() { + let temp_dir = setup_test_dir(); + let rclone_path = if cfg!(windows) { + temp_dir.path().join("rclone.exe") + } else { + temp_dir.path().join("rclone") + }; + + #[cfg(not(windows))] + { + use std::os::unix::fs::PermissionsExt; + fs::write(&rclone_path, "#!/bin/sh\necho 'rclone v1.60.0'").unwrap(); + let mut perms = fs::metadata(&rclone_path).unwrap().permissions(); + perms.set_mode(0o755); + fs::set_permissions(&rclone_path, perms).unwrap(); + } + + #[cfg(windows)] + { + fs::write(&rclone_path, "").unwrap(); + } + + let app = RcloneApp::new_with_path(rclone_path, false); + + if cfg!(not(windows)) { + let result = app.version(); + println!("Version result: {:?}", result); + } + } + + #[test] + fn test_using_system_rclone_flag() { + let temp_dir = setup_test_dir(); + let rclone_path = temp_dir.path().join("rclone"); + + let app = RcloneApp::new_with_path(rclone_path.clone(), true); + assert!(app.is_using_system_rclone()); + + let app2 = RcloneApp::new_with_path(rclone_path, false); + assert!(!app2.is_using_system_rclone()); + } + + #[test] + fn test_multiple_instances() { + let temp_dir = setup_test_dir(); + + let app1 = RcloneApp::new_with_path(temp_dir.path().join("rclone1"), true); + let app2 = RcloneApp::new_with_path(temp_dir.path().join("rclone2"), false); + let app3 = RcloneApp::new_with_path(temp_dir.path().join("rclone3"), true); + + assert!(app1.is_using_system_rclone()); + assert!(!app2.is_using_system_rclone()); + assert!(app3.is_using_system_rclone()); + + assert_ne!(app1.get_rclone_path(), app2.get_rclone_path()); + } + + #[tokio::test] + #[serial] + async fn test_check_system_rclone() { + let result = RcloneApp::check_system_rclone(); + println!("System rclone found: {:?}", result); + } + + #[test] + fn test_path_manipulation() { + let temp_dir = setup_test_dir(); + let original_path = temp_dir.path().join("original_rclone"); + let new_path = temp_dir.path().join("new_rclone"); + + let mut app = RcloneApp::new_with_path(original_path.clone(), false); + assert_eq!(app.get_rclone_path(), &original_path); + + app.set_rclone_path(new_path.clone()); + assert_eq!(app.get_rclone_path(), &new_path); + } + + #[test] + fn test_os_arch_detection() { + let os = if cfg!(target_os = "linux") { + "linux" + } else if cfg!(target_os = "macos") { + "osx" + } else if cfg!(target_os = "windows") { + "windows" + } else { + "unknown" + }; + + let arch = if cfg!(target_arch = "x86_64") { + "amd64" + } else if cfg!(target_arch = "aarch64") { + "arm64" + } else if cfg!(target_arch = "arm") { + "arm" + } else { + "unknown" + }; + + assert_ne!(os, "unknown", "ОС должна быть определена"); + assert_ne!(arch, "unknown", "Архитектура должна быть определена"); + + println!("OS: {}, ARCH: {}", os, arch); + } + + #[tokio::test] + #[ignore] + async fn test_actual_rclone_installation() { + match RcloneApp::new().await { + Ok(app) => { + assert!(app.get_rclone_path().exists()); + let version = app.version(); + assert!(version.is_ok()); + println!("Установлен rclone по пути: {:?}", app.get_rclone_path()); + println!("Версия: {:?}", version); + println!("Используется системный rclone: {}", app.is_using_system_rclone()); + } + Err(e) => { + panic!("Не удалось установить rclone: {}", e); + } + } + } +} From 1abb0f10f8bd927100ff2dce54324c8b06141d30 Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 2 Mar 2026 13:49:45 +0300 Subject: [PATCH 15/15] feat(rclone.exe): Added tests to main --- src/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index bbf2a21..6bf192b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +#[cfg(test)] +mod tests; + mod rcloneInstall; use tokio::runtime::Runtime; @@ -11,7 +14,7 @@ fn main() -> Result<(), Box> { Ok::<_, Box>(rclone) })?; - let v = rclone.version(); - println!("Rclone: {:?}", v); + let v = rclone.version().unwrap().to_string(); + println!("Rclone: {}", v); Ok::<_, Box>(()) }