mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
Move to eyre errors
This commit is contained in:
parent
b45d4985cf
commit
2cddde4de7
5 changed files with 109 additions and 74 deletions
17
noita-proxy/Cargo.lock
generated
17
noita-proxy/Cargo.lock
generated
|
@ -1056,6 +1056,16 @@ version = "3.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b"
|
checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "eyre"
|
||||||
|
version = "0.6.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
|
||||||
|
dependencies = [
|
||||||
|
"indenter",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
|
@ -1651,6 +1661,12 @@ version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indenter"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.4.0"
|
version = "2.4.0"
|
||||||
|
@ -1991,6 +2007,7 @@ dependencies = [
|
||||||
"egui-file-dialog",
|
"egui-file-dialog",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
"egui_plot",
|
"egui_plot",
|
||||||
|
"eyre",
|
||||||
"fluent-bundle",
|
"fluent-bundle",
|
||||||
"fluent-templates",
|
"fluent-templates",
|
||||||
"image",
|
"image",
|
||||||
|
|
|
@ -46,6 +46,7 @@ argh = "0.1.12"
|
||||||
shlex = "1.3.0"
|
shlex = "1.3.0"
|
||||||
quick-xml = { version = "0.36.0", features = ["serialize"] }
|
quick-xml = { version = "0.36.0", features = ["serialize"] }
|
||||||
dashmap = "6.0.1"
|
dashmap = "6.0.1"
|
||||||
|
eyre = "0.6.12"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
winresource = "0.1.17"
|
winresource = "0.1.17"
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{self, BufReader},
|
io::{self, BufReader},
|
||||||
|
mem,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -248,41 +249,57 @@ impl Modmanager {
|
||||||
match promise.ready() {
|
match promise.ready() {
|
||||||
Some(Ok(downloader)) => {
|
Some(Ok(downloader)) => {
|
||||||
downloader.show_progress(ui);
|
downloader.show_progress(ui);
|
||||||
match downloader.ready() {
|
|
||||||
Some(Ok(_)) => {
|
|
||||||
let path = downloader.path().to_path_buf();
|
|
||||||
let directory = settings.mod_path();
|
|
||||||
let promise: Promise<Result<(), ReleasesError>> =
|
|
||||||
Promise::spawn_thread("unpack", move || {
|
|
||||||
extract_and_remove_zip(path, directory)
|
|
||||||
});
|
|
||||||
self.state = State::UnpackMod(promise);
|
|
||||||
}
|
|
||||||
Some(Err(err)) => self.state = State::ReleasesError(err.clone()),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Some(Err(err)) => self.state = State::ReleasesError(err.clone()),
|
Some(Err(_)) => {}
|
||||||
None => {
|
None => {
|
||||||
ui.label(tr("modman_receiving_rel_info"));
|
ui.label(tr("modman_receiving_rel_info"));
|
||||||
ui.spinner();
|
ui.spinner();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if promise.ready().is_some() {
|
||||||
State::UnpackMod(promise) => match promise.ready() {
|
let State::DownloadMod(promise) = mem::take(&mut self.state) else {
|
||||||
Some(Ok(_)) => {
|
unreachable!();
|
||||||
ui.label(tr("modman_installed"));
|
|
||||||
if ui.button(tr("button_continue")).clicked() {
|
|
||||||
self.state = State::Done;
|
|
||||||
};
|
};
|
||||||
|
match promise.block_and_take() {
|
||||||
|
Ok(downloader) => {
|
||||||
|
let path = downloader.path().to_path_buf();
|
||||||
|
let directory = settings.mod_path();
|
||||||
|
let promise: Promise<Result<(), ReleasesError>> =
|
||||||
|
Promise::spawn_thread("unpack", move || {
|
||||||
|
extract_and_remove_zip(path, directory)
|
||||||
|
});
|
||||||
|
self.state = State::UnpackMod(promise);
|
||||||
|
}
|
||||||
|
Err(err) => self.state = State::ReleasesError(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(Err(err)) => {
|
}
|
||||||
self.state = State::ReleasesError(err.clone());
|
State::UnpackMod(promise) => {
|
||||||
|
match promise.ready() {
|
||||||
|
Some(Ok(_)) => {
|
||||||
|
ui.label(tr("modman_installed"));
|
||||||
|
if ui.button(tr("button_continue")).clicked() {
|
||||||
|
self.state = State::Done;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some(Err(_)) => {}
|
||||||
|
None => {
|
||||||
|
ui.label(tr("modman_unpacking"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
if promise.ready().is_some() {
|
||||||
ui.label(tr("modman_unpacking"));
|
let State::UnpackMod(promise) = mem::take(&mut self.state) else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
match promise.block_and_take() {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => {
|
||||||
|
self.state = State::ReleasesError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
State::Error(err) => {
|
State::Error(err) => {
|
||||||
ui.label(format!("Encountered an error: {}", err));
|
ui.label(format!("Encountered an error: {}", err));
|
||||||
if ui.button(tr("button_retry")).clicked() {
|
if ui.button(tr("button_retry")).clicked() {
|
||||||
|
@ -290,7 +307,7 @@ impl Modmanager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State::ReleasesError(err) => {
|
State::ReleasesError(err) => {
|
||||||
ui.label(format!("Encountered an error: {}", err));
|
ui.label(format!("Encountered an error: \n {:?}", err));
|
||||||
if ui.button(tr("button_retry")).clicked() {
|
if ui.button(tr("button_retry")).clicked() {
|
||||||
self.state = State::JustStarted;
|
self.state = State::JustStarted;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,19 @@
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, Read, Write},
|
io::{Read, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{atomic::AtomicU64, Arc},
|
sync::{atomic::AtomicU64, Arc},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use eframe::egui::{self, Ui};
|
use eframe::egui::{self, Ui};
|
||||||
|
use eyre::{eyre, Context};
|
||||||
use poll_promise::Promise;
|
use poll_promise::Promise;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use thiserror::Error;
|
|
||||||
use zip::result::ZipError;
|
|
||||||
|
|
||||||
#[derive(Debug, Error, Clone)]
|
pub type ReleasesError = eyre::Report;
|
||||||
pub enum ReleasesError {
|
|
||||||
#[error("Could not complete request: {0}")]
|
|
||||||
Request(Arc<reqwest::Error>),
|
|
||||||
#[error("Asset not found")]
|
|
||||||
AssetNotFound,
|
|
||||||
#[error("Io error: {0}")]
|
|
||||||
Io(Arc<io::Error>),
|
|
||||||
#[error("Zip error: {0}")]
|
|
||||||
Zip(Arc<ZipError>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<reqwest::Error> for ReleasesError {
|
|
||||||
fn from(value: reqwest::Error) -> Self {
|
|
||||||
Self::Request(value.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<io::Error> for ReleasesError {
|
|
||||||
fn from(value: io::Error) -> Self {
|
|
||||||
Self::Io(value.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ZipError> for ReleasesError {
|
|
||||||
fn from(value: ZipError) -> Self {
|
|
||||||
Self::Zip(value.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Release {
|
pub struct Release {
|
||||||
|
@ -92,18 +63,25 @@ fn download_thread(
|
||||||
.header("Accept", "application/octet-stream")
|
.header("Accept", "application/octet-stream")
|
||||||
.header("X-GitHub-Api-Version", "2022-11-28")
|
.header("X-GitHub-Api-Version", "2022-11-28")
|
||||||
.header("User-agent", "noita proxy")
|
.header("User-agent", "noita proxy")
|
||||||
.send()?;
|
.send()
|
||||||
|
.wrap_err_with(|| format!("Failed to download from {}", url))?;
|
||||||
let mut buf = [0; 4096];
|
let mut buf = [0; 4096];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let len = response.read(&mut buf)?;
|
let len = response.read(&mut buf).wrap_err_with(|| {
|
||||||
|
format!(
|
||||||
|
"Failed to download from {}: couldn't read from response",
|
||||||
|
url
|
||||||
|
)
|
||||||
|
})?;
|
||||||
shared
|
shared
|
||||||
.progress
|
.progress
|
||||||
.fetch_add(len as u64, std::sync::atomic::Ordering::Relaxed);
|
.fetch_add(len as u64, std::sync::atomic::Ordering::Relaxed);
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
file.write_all(&buf[..len])?;
|
file.write_all(&buf[..len])
|
||||||
|
.wrap_err_with(|| format!("Failed to download from {}: couldn't write to file", url))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -153,7 +131,7 @@ impl AssetList {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.find(|asset| asset.name == name)
|
.find(|asset| asset.name == name)
|
||||||
.ok_or(ReleasesError::AssetNotFound)
|
.ok_or_else(|| eyre!("Asset not found: {}", name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,9 +191,15 @@ impl Release {
|
||||||
.header("Accept", "application/vnd.github+json")
|
.header("Accept", "application/vnd.github+json")
|
||||||
.header("X-GitHub-Api-Version", "2022-11-28")
|
.header("X-GitHub-Api-Version", "2022-11-28")
|
||||||
.header("User-agent", "noita proxy")
|
.header("User-agent", "noita proxy")
|
||||||
.send()?;
|
.send()
|
||||||
|
.wrap_err_with(|| format!("Failed to request asset list from {}", self.assets_url))?;
|
||||||
|
|
||||||
Ok(response.json()?)
|
Ok(response.json().wrap_err_with(|| {
|
||||||
|
format!(
|
||||||
|
"Failed to request asset list from {}: couldn't parse json",
|
||||||
|
self.assets_url
|
||||||
|
)
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,21 +209,24 @@ pub fn get_latest_release(client: &Client) -> Result<Release, ReleasesError> {
|
||||||
.header("Accept", "application/vnd.github+json")
|
.header("Accept", "application/vnd.github+json")
|
||||||
.header("X-GitHub-Api-Version", "2022-11-28")
|
.header("X-GitHub-Api-Version", "2022-11-28")
|
||||||
.header("User-agent", "noita proxy")
|
.header("User-agent", "noita proxy")
|
||||||
.send()?;
|
.send()
|
||||||
|
.wrap_err("Failed to request latest release")?;
|
||||||
|
|
||||||
Ok(response.json()?)
|
Ok(response.json()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_release_by_tag(client: &Client, tag: Tag) -> Result<Release, ReleasesError> {
|
pub fn get_release_by_tag(client: &Client, tag: Tag) -> Result<Release, ReleasesError> {
|
||||||
|
let url = format!(
|
||||||
|
"https://api.github.com/repos/IntQuant/noita_entangled_worlds/releases/tags/{}",
|
||||||
|
tag.0
|
||||||
|
);
|
||||||
let response = client
|
let response = client
|
||||||
.get(format!(
|
.get(&url)
|
||||||
"https://api.github.com/repos/IntQuant/noita_entangled_worlds/releases/tags/{}",
|
|
||||||
tag.0
|
|
||||||
))
|
|
||||||
.header("Accept", "application/vnd.github+json")
|
.header("Accept", "application/vnd.github+json")
|
||||||
.header("X-GitHub-Api-Version", "2022-11-28")
|
.header("X-GitHub-Api-Version", "2022-11-28")
|
||||||
.header("User-agent", "noita proxy")
|
.header("User-agent", "noita proxy")
|
||||||
.send()?;
|
.send()
|
||||||
|
.wrap_err_with(|| format!("Failed to get release by tag from {}", url))?;
|
||||||
|
|
||||||
Ok(response.json()?)
|
Ok(response.json()?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io,
|
io, mem,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use eframe::egui::{Align, Layout, Ui};
|
use eframe::egui::{Align, Layout, Ui};
|
||||||
|
use eyre::Context;
|
||||||
use poll_promise::Promise;
|
use poll_promise::Promise;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
@ -20,10 +21,13 @@ struct VersionCheckResult {
|
||||||
ord: Ordering,
|
ord: Ordering,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
enum State {
|
enum State {
|
||||||
|
#[default]
|
||||||
Initial,
|
Initial,
|
||||||
Download(Promise<Result<Downloader, ReleasesError>>),
|
Download(Promise<Result<Downloader, ReleasesError>>),
|
||||||
ReleasesError(ReleasesError),
|
ReleasesError(ReleasesError),
|
||||||
|
ReleasesError2(String),
|
||||||
Unpack(Promise<Result<(), ReleasesError>>),
|
Unpack(Promise<Result<(), ReleasesError>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,11 +117,17 @@ impl SelfUpdateManager {
|
||||||
});
|
});
|
||||||
self.state = State::Unpack(promise);
|
self.state = State::Unpack(promise);
|
||||||
}
|
}
|
||||||
Some(Err(err)) => self.state = State::ReleasesError(err.clone()),
|
Some(Err(_)) => {
|
||||||
|
let State::Download(promise) = mem::take(&mut self.state) else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
self.state =
|
||||||
|
State::ReleasesError(promise.block_and_take().err().unwrap())
|
||||||
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(Err(err)) => self.state = State::ReleasesError(err.clone()),
|
Some(Err(err)) => self.state = State::ReleasesError2(format!("{:?}", err)),
|
||||||
None => {
|
None => {
|
||||||
ui.label(tr("selfupdate_receiving_rel_info"));
|
ui.label(tr("selfupdate_receiving_rel_info"));
|
||||||
ui.spinner();
|
ui.spinner();
|
||||||
|
@ -137,7 +147,10 @@ impl SelfUpdateManager {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
State::ReleasesError(err) => {
|
State::ReleasesError(err) => {
|
||||||
ui.label(format!("Encountered an error: {}", err));
|
ui.label(format!("Encountered an error: {:?}", err));
|
||||||
|
}
|
||||||
|
State::ReleasesError2(err) => {
|
||||||
|
ui.label(format!("Encountered an error:\n{}", err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue