diff --git a/Cargo.lock b/Cargo.lock index 5f2b45f..306f531 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,24 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bzip2" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" version = "1.0.4" @@ -98,6 +116,15 @@ dependencies = [ "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "flate2" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fnv" version = "1.0.6" @@ -204,16 +231,16 @@ dependencies = [ [[package]] name = "includedir" version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/j-selby/includedir.git?rev=4e25ad8#4e25ad85d43d6fd6a22194edc48190d6529fbfcf" dependencies = [ - "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "includedir_codegen" version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/j-selby/includedir.git?rev=e6db212#e6db21299b76a8e9539378eec36421cbc3af980b" dependencies = [ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -354,6 +381,26 @@ dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "miniz_oxide" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide_c_api" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.6.12" @@ -383,6 +430,16 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "msdos_time" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "native-tls" version = "0.1.5" @@ -506,6 +563,11 @@ name = "pkg-config" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "podio" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.3.15" @@ -954,8 +1016,8 @@ dependencies = [ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.15 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "includedir 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "includedir_codegen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "includedir 0.2.2 (git+https://github.com/j-selby/includedir.git?rev=4e25ad8)", + "includedir_codegen 0.2.2 (git+https://github.com/j-selby/includedir.git?rev=e6db212)", "mime_guess 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -970,6 +1032,19 @@ dependencies = [ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "web-view 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zip 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zip" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] @@ -981,6 +1056,8 @@ dependencies = [ "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9" "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" "checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" +"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24" +"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b" "checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" @@ -988,6 +1065,7 @@ dependencies = [ "checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" +"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -1000,8 +1078,8 @@ dependencies = [ "checksum hyper 0.11.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4d6105c5eeb03068b10ff34475a0d166964f98e7b9777cc34b342a225af9b87c" "checksum hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c81fa95203e2a6087242c38691a0210f23e9f3f8f944350bd676522132e2985" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum includedir 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed470a2a5c0afe4587796a886aa185fcef159feaefd8c4f40d85423aeeec4a3a" -"checksum includedir_codegen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4cb2bb86e79496ab481fc7865ce8c2960cf1eb40cc1411524ce67fce54f3c95e" +"checksum includedir 0.2.2 (git+https://github.com/j-selby/includedir.git?rev=4e25ad8)" = "" +"checksum includedir_codegen 0.2.2 (git+https://github.com/j-selby/includedir.git?rev=e6db212)" = "" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -1020,8 +1098,11 @@ dependencies = [ "checksum mime_guess 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7e82a15629bb4ecd9e72365bf33d1382be91e030f820edb8e2a21c02430da8" "checksum mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "013572795763289e14710c7b279461295f2673b2b338200c235082cd7ca9e495" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" +"checksum miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa2d3ad070f428fffbd7d3ca2ea20bb0d8cffe9024405c44e1840bc1418b398" +"checksum miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92d98fdbd6145645828069b37ea92ca3de225e000d80702da25c20d3584b38a5" "checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958" "checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98" @@ -1036,6 +1117,7 @@ dependencies = [ "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" @@ -1091,3 +1173,4 @@ dependencies = [ "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum zip 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e7341988e4535c60882d5e5f0b7ad0a9a56b080ade8bdb5527cb512f7b2180e0" diff --git a/Cargo.toml b/Cargo.toml index 9f2d94c..a1c96ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ url = "*" reqwest = "0.8.4" number_prefix = "0.2.7" -includedir = "0.2.2" +includedir = {git = "https://github.com/j-selby/includedir.git", rev="4e25ad8"} phf = "0.7.21" serde = "1.0.27" @@ -30,5 +30,7 @@ nfd = "0.0.4" semver = "0.9.0" regex = "0.2" +zip = "0.2.8" + [build-dependencies] -includedir_codegen = "0.2.0" +includedir_codegen = {git = "https://github.com/j-selby/includedir.git", rev="e6db212"} diff --git a/src/installer.rs b/src/installer.rs index 0ee153a..9234bbf 100644 --- a/src/installer.rs +++ b/src/installer.rs @@ -4,8 +4,13 @@ use regex::Regex; +use zip::ZipArchive; + +use number_prefix::{decimal_prefix, Prefixed, Standalone}; + use std::fs::create_dir_all; use std::fs::read_dir; +use std::fs::File; use std::env::home_dir; use std::env::var; @@ -13,6 +18,9 @@ use std::env::consts::OS; use std::path::PathBuf; +use std::io::Cursor; +use std::io::copy; + use std::sync::Arc; use std::sync::Mutex; use std::sync::mpsc::Sender; @@ -21,8 +29,6 @@ use config::Config; use http::stream_file; -use number_prefix::{decimal_prefix, Prefixed, Standalone}; - /// A message thrown during the installation of packages. #[derive(Serialize)] pub enum InstallMessage { @@ -85,7 +91,7 @@ impl InstallerFramework { } // Make sure it is empty - let paths = match read_dir(path) { + let paths = match read_dir(&path) { Ok(v) => v, Err(v) => return Err(format!("Failed to read install destination: {:?}", v)), }; @@ -115,22 +121,24 @@ impl InstallerFramework { println!("Installing {}", package.name); + // 10%: polling messages .send(InstallMessage::Status( format!( "Polling {} for latest version of {}", package.source.name, package.name ), - base_package_percentage + base_package_range * 0.25, + base_package_percentage + base_package_range * 0.10, )) .unwrap(); let results = package.source.get_current_releases()?; + // 20%: waiting for parse/HTTP messages .send(InstallMessage::Status( format!("Resolving dependency for {}", package.name), - base_package_percentage + base_package_range * 0.50, + base_package_percentage + base_package_range * 0.20, )) .unwrap(); @@ -144,7 +152,7 @@ impl InstallerFramework { let latest_result = results .into_iter() .filter(|f| f.files.iter().filter(|x| regex.is_match(&x.name)).count() > 0) - .max_by_key(|f| f.version.clone()); + .min_by_key(|f| f.version.clone()); let latest_result = match latest_result { Some(v) => v, @@ -163,13 +171,20 @@ impl InstallerFramework { // Download this file let lock = Arc::new(Mutex::new(DownloadProgress { downloaded: 0 })); + let data_storage : Arc>> = Arc::new(Mutex::new(Vec::new())); + // 33-66%: downloading file stream_file(latest_file.url, |data, size| { + { + let mut data_lock = data_storage.lock().unwrap(); + data_lock.extend_from_slice(&data); + } + let mut reference = lock.lock().unwrap(); reference.downloaded += data.len(); - let base_percentage = base_package_percentage + base_package_range * 0.50; - let range_percentage = base_package_range / 2.0; + let base_percentage = base_package_percentage + base_package_range * 0.33; + let range_percentage = base_package_range / 3.0; let global_percentage = if size == 0 { base_percentage @@ -203,6 +218,71 @@ impl InstallerFramework { println!("File downloaded successfully"); + // Extract this downloaded file + // TODO: Handle files other then zips + // TODO: Make database for uninstall + let data = data_storage.lock().unwrap(); + let data_cursor = Cursor::new(data.as_slice()); + let mut zip = match ZipArchive::new(data_cursor) { + Ok(v) => v, + Err(v) => return Err(format!("Unable to open .zip file: {:?}", v)), + }; + + let extract_base_percentage = base_package_percentage + base_package_range * 0.66; + let extract_range_percentage = base_package_range / 3.0; + + let zip_size = zip.len(); + + for i in 0..zip_size { + let mut file = zip.by_index(i).unwrap(); + + let percentage = extract_base_percentage + + extract_range_percentage / zip_size as f64 * i as f64; + + messages + .send(InstallMessage::Status( + format!( + "Extracting {} ({} of {})", + file.name(), i + 1, zip_size + ), + percentage, + )) + .unwrap(); + + // Create target file + let target_path = path.join(file.name()); + println!("target_path: {:?}", target_path); + + // Check to make sure this isn't a directory + if file.name().ends_with("/") || file.name().ends_with("\\") { + // Create this directory and move on + match create_dir_all(target_path) { + Ok(v) => v, + Err(v) => return Err(format!("Unable to open file: {:?}", v)), + } + continue; + } + + match target_path.parent() { + Some(v) => match create_dir_all(v) { + Ok(v) => v, + Err(v) => return Err(format!("Unable to open file: {:?}", v)), + }, + None => {}, + } + + let mut target_file = match File::create(target_path) { + Ok(v) => v, + Err(v) => return Err(format!("Unable to open file handle: {:?}", v)), + }; + + // Cross the streams + match copy(&mut file, &mut target_file) { + Ok(v) => v, + Err(v) => return Err(format!("Unable to open write file: {:?}", v)), + }; + } + count += 1.0; } diff --git a/src/main.rs b/src/main.rs index 1a02520..41607ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,8 @@ extern crate toml; extern crate regex; extern crate semver; +extern crate zip; + mod assets; mod rest; mod config;