diff --git a/src/main.rs b/src/main.rs index 17d53c9..d06addd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod file; mod sharry; use std::{ - process::exit, + process::{self, exit}, sync::{ Arc, atomic::{AtomicBool, Ordering}, @@ -22,22 +22,30 @@ use cli::Cli; use sharry::ClientError; fn main() { + env_logger::init(); + println!( "{} to {}!", style("Welcome").magenta().bold(), style("ShrUpl").yellow().bold(), ); - let stop = Arc::new(AtomicBool::new(false)); + let check_ctrlc = { + let stop = Arc::new(AtomicBool::new(false)); - let stop_ctrlc = stop.clone(); - ctrlc::set_handler(move || { - stop_ctrlc.store(true, Ordering::SeqCst); - info!("stopping as soon as possible ..."); - }) - .expect("Error setting Ctrl-C handler"); + let stop_ctrlc = stop.clone(); + ctrlc::set_handler(move || { + stop_ctrlc.store(true, Ordering::SeqCst); + info!("stopping as soon as possible ..."); + }) + .expect("Error setting Ctrl-C handler"); - env_logger::init(); + move || { + if stop.load(Ordering::SeqCst) { + process::exit(1); + } + } + }; let args = Cli::parse(); info!("args: {args:?}"); @@ -57,7 +65,7 @@ fn main() { .map_or(None, |b| b.then_some(state)) }) .unwrap_or_else(|| { - stop.load(Ordering::SeqCst).then(|| exit(0)); + check_ctrlc(); match AppState::from_args(&args, &agent) { Ok(state) => { @@ -67,8 +75,8 @@ fn main() { Err(e) => { if let Some(cause) = match e { ClientError::ResponseStatus { - actual: _, - expected: 403, + actual: 403, + expected: _, } => Some("Alias ID"), // ClientError::FileIO(_) => Some("URL"), _ => None, @@ -77,8 +85,8 @@ fn main() { println!( "{} probably wrong: {} – {:?}", style("Error!").red().bold(), - style(cause).cyan().italic(), - style(e.to_string()).yellow() + style(cause).cyan(), + style(e.to_string()).yellow().italic() ); } else { error!("unknown error: {e} – {e:?}"); @@ -110,6 +118,6 @@ fn main() { } state.save().unwrap(); // HACK unwrap - stop.load(Ordering::SeqCst).then(|| exit(0)); + check_ctrlc(); } } diff --git a/src/sharry/client.rs b/src/sharry/client.rs index e857faa..7656770 100644 --- a/src/sharry/client.rs +++ b/src/sharry/client.rs @@ -32,8 +32,8 @@ pub enum ClientError { #[error("response parsing failed: {0}")] ResponseParsing(String), - #[error("unexpected response status: {actual} (expected {expected})")] - ResponseStatus { actual: u16, expected: u16 }, + #[error("unexpected response status: {actual} (expected {expected:?})")] + ResponseStatus { actual: u16, expected: Option }, #[error("unexpected response content: {0}")] ResponseContent(String), @@ -48,21 +48,33 @@ impl ClientError { Self::ResponseParsing(msg.to_string()) } - pub fn res_check_status(actual: T, expected: T) -> Result<()> + pub fn res_status_check(actual: T, expected: T) -> Result<()> where - T: Into + Eq, + T: PartialEq + Into + Copy, { if actual == expected { Ok(()) } else { Err(Self::ResponseStatus { actual: actual.into(), - expected: expected.into(), + expected: Some(expected.into()), }) } } } +impl From for ClientError { + fn from(value: ureq::Error) -> Self { + match value { + ureq::Error::StatusCode(status) => ClientError::ResponseStatus { + actual: status, + expected: None, + }, + error => Self::Request(error.to_string()), + } + } +} + impl Client for ureq::Agent { fn share_create( &self, @@ -76,10 +88,10 @@ impl Client for ureq::Agent { .post(endpoint) .header("Sharry-Alias", alias_id) .send_json(data) - .map_err(ClientError::req_err)?; + .map_err(ClientError::from)?; trace!("{endpoint:?} response: {res:?}"); - ClientError::res_check_status(res.status(), ureq::http::StatusCode::OK)?; + ClientError::res_status_check(res.status(), ureq::http::StatusCode::OK)?; let res = res .body_mut() @@ -102,10 +114,10 @@ impl Client for ureq::Agent { .post(endpoint) .header("Sharry-Alias", alias_id) .send_empty() - .map_err(ClientError::req_err)?; + .map_err(ClientError::from)?; trace!("{endpoint:?} response: {res:?}"); - ClientError::res_check_status(res.status(), ureq::http::StatusCode::OK)?; + ClientError::res_status_check(res.status(), ureq::http::StatusCode::OK)?; let res = res .body_mut() @@ -132,10 +144,10 @@ impl Client for ureq::Agent { .header("Sharry-File-Name", file_name) .header("Upload-Length", file_size) .send_empty() - .map_err(ClientError::req_err)?; + .map_err(ClientError::from)?; trace!("{endpoint:?} response: {res:?}"); - ClientError::res_check_status(res.status(), ureq::http::StatusCode::CREATED)?; + ClientError::res_status_check(res.status(), ureq::http::StatusCode::CREATED)?; let location = (res.headers().get("Location")) .ok_or_else(|| ClientError::res_parse_err("Location header not found"))? @@ -154,10 +166,10 @@ impl Client for ureq::Agent { .header("Sharry-Alias", alias_id) .header("Upload-Offset", offset) .send(chunk) - .map_err(ClientError::req_err)?; + .map_err(ClientError::from)?; trace!("{patch_uri:?} response: {res:?}"); - ClientError::res_check_status(res.status(), ureq::http::StatusCode::NO_CONTENT)?; + ClientError::res_status_check(res.status(), ureq::http::StatusCode::NO_CONTENT)?; let res_offset = (res.headers().get("Upload-Offset")) .ok_or_else(|| ClientError::res_parse_err("Upload-Offset header not found"))?