Move zip download and extracting to altarik/mod.rs and implemented zip version

This commit is contained in:
Quentin Legot 2023-10-04 23:57:34 +02:00
parent affa6d8535
commit 532257ffb0
5 changed files with 319 additions and 67 deletions

142
src-tauri/Cargo.lock generated
View File

@ -68,6 +68,23 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "async-compression"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
dependencies = [
"bzip2",
"flate2",
"futures-core",
"futures-io",
"memchr",
"pin-project-lite",
"xz2",
"zstd",
"zstd-safe",
]
[[package]]
name = "async-trait"
version = "0.1.73"
@ -79,6 +96,23 @@ dependencies = [
"syn 2.0.37",
]
[[package]]
name = "async_zip"
version = "0.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "795310de3218cde15219fc98c1cf7d8fe9db4865aab27fcf1d535d6cb61c6b54"
dependencies = [
"async-compression",
"chrono",
"crc32fast",
"futures-util",
"log",
"pin-project",
"thiserror",
"tokio",
"tokio-util",
]
[[package]]
name = "atk"
version = "0.15.1"
@ -218,6 +252,27 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[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.11+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "cairo-rs"
version = "0.15.12"
@ -258,6 +313,7 @@ version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
"libc",
]
@ -1547,6 +1603,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jobserver"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.64"
@ -1598,6 +1663,7 @@ name = "launcher-tauri"
version = "0.0.0"
dependencies = [
"anyhow",
"async_zip",
"directories",
"log4rs",
"rand 0.8.5",
@ -1608,6 +1674,8 @@ dependencies = [
"tauri",
"tauri-build",
"tokio",
"tokio-stream",
"tokio-tar",
"urlencoding",
"uuid",
"warp",
@ -1712,6 +1780,17 @@ dependencies = [
"tracing-subscriber",
]
[[package]]
name = "lzma-sys"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "mac"
version = "0.1.1"
@ -2614,9 +2693,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.15"
version = "0.38.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531"
checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7"
dependencies = [
"bitflags 2.4.0",
"errno",
@ -2917,9 +2996,9 @@ dependencies = [
[[package]]
name = "sharded-slab"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
@ -3557,6 +3636,21 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-tar"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75"
dependencies = [
"filetime",
"futures-core",
"libc",
"redox_syscall 0.3.5",
"tokio",
"tokio-stream",
"xattr",
]
[[package]]
name = "tokio-tungstenite"
version = "0.20.1"
@ -3577,6 +3671,7 @@ checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
dependencies = [
"bytes",
"futures-core",
"futures-io",
"futures-sink",
"pin-project-lite",
"tokio",
@ -4456,6 +4551,15 @@ dependencies = [
"libc",
]
[[package]]
name = "xz2"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
dependencies = [
"lzma-sys",
]
[[package]]
name = "yaml-rust"
version = "0.4.5"
@ -4464,3 +4568,33 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[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.8+zstd.1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c"
dependencies = [
"cc",
"libc",
"pkg-config",
]

View File

@ -27,6 +27,9 @@ anyhow = "1.0.66"
rand = "0.8.5"
directories = "5.0.0"
sha256 = "1.4.0"
tokio-tar = "0.3.1"
async_zip = { version = "0.0.15", features = ["full"] }
tokio-stream = "0.1.14"
[features]
# by default Tauri runs in production mode

View File

@ -1,6 +1,16 @@
use anyhow::Result;
use std::path::{PathBuf, Path};
use anyhow::{Result, bail};
use reqwest::Client;
use serde::{Serialize, Deserialize};
use async_zip::base::read::seek::ZipFileReader;
use tokio::{fs::{OpenOptions, File, self}, sync::mpsc, io::AsyncWriteExt};
use tokio_tar::Archive;
use tokio_stream::StreamExt;
use crate::launcher::ProgressMessage;
use super::{ACTUAL_OS, manifest::OSName};
#[derive(Serialize, Deserialize, Clone)]
@ -64,3 +74,161 @@ impl AltarikManifest {
}
}
impl Chapter {
}
impl JavaPlatform {
pub async fn download_java(&self, root_path: &Path, reqwest: &Client, log_channel: mpsc::Sender<ProgressMessage>) -> Result<()> {
let download_path = root_path.join("runtime").join("download");
let (url, extension) = match ACTUAL_OS {
OSName::Linux => {
(self.linux.clone(), "tar.gz")
},
OSName::Windows => {
(self.win32.clone(), "zip")
},
_ => {
bail!("Your current is not supported")
}
};
let url = match url {
Some(url) => url,
None => bail!("No available executable available for your platform")
};
let filepath = download_path.join(format!("{}.{}", url.x64.name.clone(), extension));
let mut should_download = false;
if !filepath.exists() {
should_download = true;
} else {
let hash = sha256::try_digest(filepath.clone());
match hash {
Ok(hash) => {
if hash != url.x64.sha256sum {
println!("Hash of java archive is not correct, redownloading");
should_download = true;
}
},
Err(_) => should_download = true
}
}
if should_download {
println!("Downloading java");
if filepath.exists() {
fs::remove_file(filepath.clone()).await?; // remove content before writing and appending to it
}
let mut file = OpenOptions::new()
.write(true)
.append(true)
.create(true)
.open(filepath)
.await?;
let mut res = reqwest.get(url.x64.link.clone()).send().await?;
log_channel.send(ProgressMessage { p_type: String::from("java"), current: 0, total: 100 }).await?;
let length = if let Some(length) = res.content_length() {
length as usize
} else {
0
};
let mut downloaded_size = 0;
while let Some(chunk) = res.chunk().await? {
downloaded_size += chunk.len();
file.write_all(&chunk).await?;
log_channel.send(ProgressMessage { p_type: String::from("java"), current: if length != 0 { downloaded_size / length } else { 0 }, total: 100 }).await?;
}
println!("{} downloaded", url.x64.name)
} else {
println!("{} already downloaded", url.x64.name)
}
Ok(())
}
pub async fn extract_java(&self, root_path: &Path) -> Result<()> {
let (url, extension) = match ACTUAL_OS {
OSName::Linux => {
(self.linux.clone(), "tar.gz")
},
OSName::Windows => {
(self.win32.clone(), "zip")
},
_ => {
bail!("Your current is not supported")
}
};
let url = match url {
Some(url) => url,
None => bail!("No available executable available for your platform")
};
let archive_path = root_path.join("runtime").join("download").join(format!("{}.{}", url.x64.name, extension));
let extract_path = root_path.join("runtime");
// if !extract_path.exists() {
// fs::create_dir(extract_path.clone()).await?;
// }
extract_zip(archive_path, extract_path).await?;
Ok(())
}
}
impl ModsPack {
pub async fn download_mods() {
// TODO
}
}
async fn extract_targz(archive_path: PathBuf, extract_path: PathBuf) -> Result<()> {
let file = File::open(archive_path.clone()).await?;
let mut archive = Archive::new(file);
let mut entries = archive.entries()?;
while let Some(entry) = entries.next().await {
let file = entry?;
println!("{:?}", archive_path);
println!("{}", file.path()?.to_string_lossy().to_string());
}
Ok(())
}
async fn extract_zip(archive_path: PathBuf, extract_path: PathBuf) -> Result<()> {
// TODO add log_channel to send progression to user
let file = File::open(archive_path.clone()).await?;
let mut reader = ZipFileReader::with_tokio(file).await?;
for index in 0..reader.file().entries().len() {
if let Some(entry) = reader.file().entries().get(index) {
let entry = entry.entry();
// println!("{}", entry.filename().as_str()?);
let filename = entry.filename().as_str()?;
let path = extract_path.join(filename);
if entry.dir()? {
if !path.exists() {
fs::create_dir_all(path).await?;
}
} else {
let mut entry_reader = reader.reader_with_entry(index).await?;
if path.exists() {
fs::remove_file(&path).await?;
}
let mut writer = OpenOptions::new()
.write(true)
.append(true)
.create_new(true)
.open(&path)
.await?;
let mut buf = Vec::with_capacity(1024 * 128);
entry_reader.read_to_end_checked(&mut buf).await?;
writer.write_all(&buf).await?;
}
}
}
Ok(())
}

View File

@ -6,7 +6,7 @@ use std::path::{Path, self, PathBuf};
use anyhow::{Result, bail};
use reqwest::{Client, StatusCode};
use serde::{Serialize, Deserialize};
use tokio::{fs::{self, File, OpenOptions}, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc};
use tokio::{fs::{self, File}, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc};
use crate::authentification::GameProfile;
@ -113,67 +113,14 @@ impl<'a> MinecraftClient<'_> {
let lib = &self.opts.root_path.join("libraries");
let asset = &self.opts.root_path.join("assets").join("objects");
self.save_version_index().await?;
self.download_java(chapter).await?;
chapter.java.platform.download_java(self.opts.root_path, &self.reqwest_client, self.opts.log_channel.clone()).await?;
chapter.java.platform.extract_java(self.opts.root_path).await?;
self.download_libraries(lib).await?;
self.download_assets(asset).await?;
self.opts.log_channel.send(ProgressMessage { p_type: "completed".to_string(), current: 0, total: 0 }).await?;
Ok(())
}
async fn download_java(&mut self, chapter: Chapter) -> Result<()> {
let download_path = self.opts.root_path.join("runtime").join("download");
// let extract_path = self.opts.root_path.join("runtime");
let (url, extension) = match ACTUAL_OS {
OSName::Linux => {
(chapter.java.platform.linux, "tar.gz")
},
OSName::Windows => {
(chapter.java.platform.win32, "zip")
},
_ => {
bail!("Your current is not supported")
}
};
let url = match url {
Some(url) => url,
None => bail!("No available executable available for your platform")
};
let filepath = download_path.join(format!("{}.{}", url.x64.name.clone(), extension));
let mut should_download = false;
if !filepath.exists() {
should_download = true;
} else {
let hash = sha256::try_digest(filepath.clone());
match hash {
Ok(hash) => {
if hash != url.x64.sha256sum {
println!("Hash of java archive is not correct, redownloading");
should_download = true;
}
},
Err(_) => should_download = true
}
}
if should_download {
println!("Downloading java");
if filepath.exists() {
fs::remove_file(filepath.clone()).await?; // remove content before writing and appending to it
}
let mut file = OpenOptions::new()
.write(true)
.create(true)
.open(filepath)
.await?;
let b = self.reqwest_client.get(url.x64.link.clone()).send().await?.bytes().await?;
file.write(&b).await?;
println!("{} downloaded", url.x64.name)
} else {
println!("{} already downloaded", url.x64.name)
}
Ok(())
}
async fn download_libraries(&mut self, lib: &PathBuf) -> Result<()> {
self.filter_non_necessary_librairies();
let total = self.details.libraries.len();

View File

@ -432,16 +432,16 @@
integrity sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==
"@types/react-dom@^18.0.6":
version "18.2.8"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.8.tgz#338f1b0a646c9f10e0a97208c1d26b9f473dffd6"
integrity sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==
version "18.2.10"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.10.tgz#06247cb600e39b63a0a385f6a5014c44bab296f2"
integrity sha512-5VEC5RgXIk1HHdyN1pHlg0cOqnxHzvPGpMMyGAP5qSaDRmyZNDaQ0kkVAkK6NYlDhP6YBID3llaXlmAS/mdgCA==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18.0.15":
version "18.2.24"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.24.tgz#3c7d68c02e0205a472f04abe4a0c1df35d995c05"
integrity sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw==
version "18.2.25"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.25.tgz#99fa44154132979e870ff409dc5b6e67f06f0199"
integrity sha512-24xqse6+VByVLIr+xWaQ9muX1B4bXJKXBbjszbld/UEDslGLY53+ZucF44HCmLbMPejTzGG9XgR+3m2/Wqu1kw==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"