mirror of
https://github.com/alterware/alterware-launcher.git
synced 2025-12-04 07:17:50 +00:00
backport extend
This commit is contained in:
54
src/extend.rs
Normal file
54
src/extend.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io::{self, Read},
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn file_blake3(file: &Path) -> std::io::Result<String> {
|
||||||
|
let mut blake3 = blake3::Hasher::new();
|
||||||
|
let mut file = File::open(file)?;
|
||||||
|
let mut buffer = [0; 1024];
|
||||||
|
loop {
|
||||||
|
let n = file.read(&mut buffer)?;
|
||||||
|
if n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blake3.update(&buffer[..n]);
|
||||||
|
}
|
||||||
|
Ok(blake3.finalize().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Blake3Path {
|
||||||
|
fn get_blake3(&self) -> io::Result<String>;
|
||||||
|
}
|
||||||
|
impl Blake3Path for Path {
|
||||||
|
fn get_blake3(&self) -> io::Result<String> {
|
||||||
|
if self.is_dir() {
|
||||||
|
// The default Error (PermissionDenied) is not very helpful when troubleshooting
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
format!("Path is a directory ({})", self.cute_path()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
file_blake3(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Blake3Path for PathBuf {
|
||||||
|
fn get_blake3(&self) -> io::Result<String> {
|
||||||
|
self.as_path().get_blake3()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CutePath {
|
||||||
|
fn cute_path(&self) -> String;
|
||||||
|
}
|
||||||
|
impl CutePath for Path {
|
||||||
|
fn cute_path(&self) -> String {
|
||||||
|
self.to_str().unwrap().replace('\\', "/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CutePath for PathBuf {
|
||||||
|
fn cute_path(&self) -> String {
|
||||||
|
self.as_path().cute_path()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ use futures_util::StreamExt;
|
|||||||
use indicatif::ProgressBar;
|
use indicatif::ProgressBar;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
|
||||||
|
use crate::extend::*;
|
||||||
use crate::misc;
|
use crate::misc;
|
||||||
|
|
||||||
pub async fn download_file_progress(
|
pub async fn download_file_progress(
|
||||||
@@ -36,7 +37,7 @@ pub async fn download_file_progress(
|
|||||||
let msg = format!(
|
let msg = format!(
|
||||||
"{}{} ({})",
|
"{}{} ({})",
|
||||||
misc::prefix("downloading"),
|
misc::prefix("downloading"),
|
||||||
misc::cute_path(path),
|
path.cute_path(),
|
||||||
misc::human_readable_bytes(total_size)
|
misc::human_readable_bytes(total_size)
|
||||||
);
|
);
|
||||||
pb.println(&msg);
|
pb.println(&msg);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::extend::*;
|
||||||
use crate::github;
|
use crate::github;
|
||||||
use crate::global::*;
|
use crate::global::*;
|
||||||
use crate::http_async;
|
use crate::http_async;
|
||||||
@@ -24,7 +25,7 @@ pub async fn update(dir: &Path, cache: &mut structs::Cache) {
|
|||||||
println!(
|
println!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
misc::prefix("downloading"),
|
misc::prefix("downloading"),
|
||||||
misc::cute_path(&dir.join("iw4x.dll"))
|
dir.join("iw4x.dll").cute_path()
|
||||||
);
|
);
|
||||||
http_async::download_file(
|
http_async::download_file(
|
||||||
&format!(
|
&format!(
|
||||||
|
|||||||
20
src/main.rs
20
src/main.rs
@@ -1,4 +1,5 @@
|
|||||||
mod config;
|
mod config;
|
||||||
|
mod extend;
|
||||||
mod github;
|
mod github;
|
||||||
mod global;
|
mod global;
|
||||||
mod http_async;
|
mod http_async;
|
||||||
@@ -10,6 +11,7 @@ mod structs;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
use extend::*;
|
||||||
use global::*;
|
use global::*;
|
||||||
use structs::*;
|
use structs::*;
|
||||||
|
|
||||||
@@ -219,13 +221,13 @@ async fn update_dir(
|
|||||||
let hash_local = hashes
|
let hash_local = hashes
|
||||||
.get(file_name)
|
.get(file_name)
|
||||||
.map(Cow::Borrowed)
|
.map(Cow::Borrowed)
|
||||||
.unwrap_or_else(|| Cow::Owned(misc::file_blake3(&file_path).unwrap()))
|
.unwrap_or_else(|| Cow::Owned(file_path.get_blake3().unwrap()))
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
if hash_local != hash_remote {
|
if hash_local != hash_remote {
|
||||||
files_to_download.push(file.clone());
|
files_to_download.push(file.clone());
|
||||||
} else {
|
} else {
|
||||||
let msg = format!("{}{}", misc::prefix("checked"), misc::cute_path(&file_path));
|
let msg = format!("{}{}", misc::prefix("checked"), file_path.cute_path());
|
||||||
pb.println(&msg);
|
pb.println(&msg);
|
||||||
info!("{msg}");
|
info!("{msg}");
|
||||||
hashes.insert(file_name.to_owned(), file.blake3.to_lowercase());
|
hashes.insert(file_name.to_owned(), file.blake3.to_lowercase());
|
||||||
@@ -288,7 +290,7 @@ async fn update_dir(
|
|||||||
download_complete = true;
|
download_complete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let hash = misc::file_blake3(&file_path).unwrap();
|
let hash = file_path.get_blake3().unwrap();
|
||||||
hashes.insert(file_name.to_owned(), hash.to_lowercase());
|
hashes.insert(file_name.to_owned(), hash.to_lowercase());
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if file_name.ends_with(".exe") {
|
if file_name.ends_with(".exe") {
|
||||||
@@ -388,14 +390,14 @@ async fn update(
|
|||||||
crate::println_info!(
|
crate::println_info!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
misc::prefix("removed"),
|
misc::prefix("removed"),
|
||||||
misc::cute_path(&file_path)
|
file_path.cute_path()
|
||||||
);
|
);
|
||||||
|
|
||||||
if fs::remove_file(&file_path).is_err() {
|
if fs::remove_file(&file_path).is_err() {
|
||||||
crate::println_error!(
|
crate::println_error!(
|
||||||
"{}Couldn't delete {}",
|
"{}Couldn't delete {}",
|
||||||
misc::prefix("error"),
|
misc::prefix("error"),
|
||||||
misc::cute_path(&file_path)
|
file_path.cute_path()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,20 +432,20 @@ async fn update(
|
|||||||
println!(
|
println!(
|
||||||
"{}Couldn't delete {}",
|
"{}Couldn't delete {}",
|
||||||
misc::prefix("error"),
|
misc::prefix("error"),
|
||||||
misc::cute_path(&file_path)
|
file_path.cute_path()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("{}{}", misc::prefix("removed"), misc::cute_path(&file_path));
|
println!("{}{}", misc::prefix("removed"), file_path.cute_path());
|
||||||
}
|
}
|
||||||
} else if file_path.is_dir() {
|
} else if file_path.is_dir() {
|
||||||
if fs::remove_dir_all(&file_path).is_err() {
|
if fs::remove_dir_all(&file_path).is_err() {
|
||||||
println!(
|
println!(
|
||||||
"{}Couldn't delete {}",
|
"{}Couldn't delete {}",
|
||||||
misc::prefix("error"),
|
misc::prefix("error"),
|
||||||
misc::cute_path(&file_path)
|
file_path.cute_path()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("{}{}", misc::prefix("removed"), misc::cute_path(&file_path));
|
println!("{}{}", misc::prefix("removed"), file_path.cute_path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/misc.rs
31
src/misc.rs
@@ -1,26 +1,9 @@
|
|||||||
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use std::{
|
|
||||||
fs::{self, File},
|
|
||||||
io::Read,
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{global, structs};
|
use crate::{global, structs};
|
||||||
|
|
||||||
pub fn file_blake3(file: &Path) -> std::io::Result<String> {
|
|
||||||
let mut blake3 = blake3::Hasher::new();
|
|
||||||
let mut file = File::open(file)?;
|
|
||||||
let mut buffer = [0; 1024];
|
|
||||||
loop {
|
|
||||||
let n = file.read(&mut buffer)?;
|
|
||||||
if n == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
blake3.update(&buffer[..n]);
|
|
||||||
}
|
|
||||||
Ok(blake3.finalize().to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stdin() -> String {
|
pub fn stdin() -> String {
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
std::io::stdin().read_line(&mut input).unwrap();
|
std::io::stdin().read_line(&mut input).unwrap();
|
||||||
@@ -34,12 +17,6 @@ pub fn rev_to_int(rev: &str) -> u16 {
|
|||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fatal_error(error: &str) {
|
|
||||||
crate::println_error!("{}: {error}", prefix("error"));
|
|
||||||
stdin();
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn human_readable_bytes(bytes: u64) -> String {
|
pub fn human_readable_bytes(bytes: u64) -> String {
|
||||||
let mut bytes = bytes as f64;
|
let mut bytes = bytes as f64;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
@@ -62,10 +39,6 @@ pub fn pb_style_download(pb: &ProgressBar, state: bool) {
|
|||||||
pb.set_style(style.unwrap());
|
pb.set_style(style.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cute_path(path: &Path) -> String {
|
|
||||||
path.to_str().unwrap().replace('\\', "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn is_program_in_path(program: &str) -> bool {
|
pub fn is_program_in_path(program: &str) -> bool {
|
||||||
std::env::var_os("PATH")
|
std::env::var_os("PATH")
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ mod config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod misc {
|
mod misc {
|
||||||
use crate::{fs, misc, structs};
|
use crate::{fs, misc, structs, Blake3Path};
|
||||||
use std::{fs::File, io::Write, path::Path};
|
use std::{fs::File, io::Write, path::Path};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -64,7 +64,7 @@ mod misc {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.write_all(b"alterware")
|
.write_all(b"alterware")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let blake3 = misc::file_blake3(&path).unwrap();
|
let blake3 = path.get_blake3().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
blake3,
|
blake3,
|
||||||
"f18a70588a620f3a874120dbc2a41f49a0f44349c8a9c10c51f2f1c7bb678daa"
|
"f18a70588a620f3a874120dbc2a41f49a0f44349c8a9c10c51f2f1c7bb678daa"
|
||||||
|
|||||||
Reference in New Issue
Block a user