Move to eyre errors

This commit is contained in:
IQuant 2024-08-23 00:08:51 +03:00
parent b45d4985cf
commit 2cddde4de7
5 changed files with 109 additions and 74 deletions

17
noita-proxy/Cargo.lock generated
View file

@ -1056,6 +1056,16 @@ version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "fastrand"
version = "1.9.0"
@ -1651,6 +1661,12 @@ version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "indexmap"
version = "2.4.0"
@ -1991,6 +2007,7 @@ dependencies = [
"egui-file-dialog",
"egui_extras",
"egui_plot",
"eyre",
"fluent-bundle",
"fluent-templates",
"image",

View file

@ -46,6 +46,7 @@ argh = "0.1.12"
shlex = "1.3.0"
quick-xml = { version = "0.36.0", features = ["serialize"] }
dashmap = "6.0.1"
eyre = "0.6.12"
[build-dependencies]
winresource = "0.1.17"

View file

@ -3,6 +3,7 @@ use std::{
error::Error,
fs::{self, File},
io::{self, BufReader},
mem,
path::{Path, PathBuf},
};
@ -248,41 +249,57 @@ impl Modmanager {
match promise.ready() {
Some(Ok(downloader)) => {
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 => {
ui.label(tr("modman_receiving_rel_info"));
ui.spinner();
}
}
}
State::UnpackMod(promise) => match promise.ready() {
Some(Ok(_)) => {
ui.label(tr("modman_installed"));
if ui.button(tr("button_continue")).clicked() {
self.state = State::Done;
if promise.ready().is_some() {
let State::DownloadMod(promise) = mem::take(&mut self.state) else {
unreachable!();
};
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 => {
ui.label(tr("modman_unpacking"));
if promise.ready().is_some() {
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) => {
ui.label(format!("Encountered an error: {}", err));
if ui.button(tr("button_retry")).clicked() {
@ -290,7 +307,7 @@ impl Modmanager {
}
}
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() {
self.state = State::JustStarted;
}

View file

@ -1,48 +1,19 @@
use std::{
fmt::Display,
fs::File,
io::{self, Read, Write},
io::{Read, Write},
path::{Path, PathBuf},
sync::{atomic::AtomicU64, Arc},
time::Duration,
};
use eframe::egui::{self, Ui};
use eyre::{eyre, Context};
use poll_promise::Promise;
use reqwest::blocking::Client;
use serde::Deserialize;
use thiserror::Error;
use zip::result::ZipError;
#[derive(Debug, Error, Clone)]
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())
}
}
pub type ReleasesError = eyre::Report;
#[derive(Debug, Deserialize)]
pub struct Release {
@ -92,18 +63,25 @@ fn download_thread(
.header("Accept", "application/octet-stream")
.header("X-GitHub-Api-Version", "2022-11-28")
.header("User-agent", "noita proxy")
.send()?;
.send()
.wrap_err_with(|| format!("Failed to download from {}", url))?;
let mut buf = [0; 4096];
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
.progress
.fetch_add(len as u64, std::sync::atomic::Ordering::Relaxed);
if len == 0 {
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(())
@ -153,7 +131,7 @@ impl AssetList {
self.0
.iter()
.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("X-GitHub-Api-Version", "2022-11-28")
.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("X-GitHub-Api-Version", "2022-11-28")
.header("User-agent", "noita proxy")
.send()?;
.send()
.wrap_err("Failed to request latest release")?;
Ok(response.json()?)
}
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
.get(format!(
"https://api.github.com/repos/IntQuant/noita_entangled_worlds/releases/tags/{}",
tag.0
))
.get(&url)
.header("Accept", "application/vnd.github+json")
.header("X-GitHub-Api-Version", "2022-11-28")
.header("User-agent", "noita proxy")
.send()?;
.send()
.wrap_err_with(|| format!("Failed to get release by tag from {}", url))?;
Ok(response.json()?)
}

View file

@ -1,11 +1,12 @@
use std::{
cmp::Ordering,
fs::{self, File},
io,
io, mem,
path::{Path, PathBuf},
};
use eframe::egui::{Align, Layout, Ui};
use eyre::Context;
use poll_promise::Promise;
use reqwest::blocking::Client;
use tracing::info;
@ -20,10 +21,13 @@ struct VersionCheckResult {
ord: Ordering,
}
#[derive(Default)]
enum State {
#[default]
Initial,
Download(Promise<Result<Downloader, ReleasesError>>),
ReleasesError(ReleasesError),
ReleasesError2(String),
Unpack(Promise<Result<(), ReleasesError>>),
}
@ -113,11 +117,17 @@ impl SelfUpdateManager {
});
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 => {}
}
}
Some(Err(err)) => self.state = State::ReleasesError(err.clone()),
Some(Err(err)) => self.state = State::ReleasesError2(format!("{:?}", err)),
None => {
ui.label(tr("selfupdate_receiving_rel_info"));
ui.spinner();
@ -137,7 +147,10 @@ impl SelfUpdateManager {
}
},
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));
}
}
}