From 3b46d228f4eee71cbd31784dcc0b689bd6c7cdd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= <40151420+ldericher@users.noreply.github.com> Date: Wed, 18 Jun 2025 19:40:34 +0000 Subject: [PATCH] impl `AppState::requeue_file` --- notes.md | 5 ----- src/appstate.rs | 20 +++++++++++++++++--- src/cachefile.rs | 4 ++++ src/file/checked.rs | 4 ++-- src/file/uploading.rs | 9 ++++++++- src/main.rs | 40 ++++++++++++++++++++++++++++++---------- 6 files changed, 61 insertions(+), 21 deletions(-) diff --git a/notes.md b/notes.md index 05f53b6..e908092 100644 --- a/notes.md +++ b/notes.md @@ -50,11 +50,6 @@ - "quiet" flag to disable output entirely - some switch to change log to "pretty-print" -- client error rework - - current variants are too "low level" - - use variants like `InvalidEndpoint`, `InvalidAlias` etc. - - `Uploading::abort() -> Checked` - - hashing - store file hashes with all `file::*` variants - check hashes on "continue" diff --git a/src/appstate.rs b/src/appstate.rs index 11016ff..8fb5252 100644 --- a/src/appstate.rs +++ b/src/appstate.rs @@ -89,10 +89,10 @@ impl AppState { }) } - fn finish_progressbar(&self) { + fn end_progressbar(&self, f: impl FnOnce(&ProgressBar)) { let mut slot = self.progress.borrow_mut(); if let Some(bar) = slot.as_ref() { - bar.finish(); + f(bar); *slot = None; } } @@ -136,7 +136,7 @@ impl AppState { } Err(path) => { debug!("Finished {:?}!", path.display()); - self.finish_progressbar(); + self.end_progressbar(|pb| pb.finish()); } } @@ -165,6 +165,20 @@ impl AppState { Some(self) } + pub fn requeue_file(mut self) -> Option { + let Some(uploading) = self.inner.pop_file(&self.http) else { + warn!("requeue_file called on empty queue"); + return None; + }; + + let checked = uploading.abort(); + self.inner.requeue_file(checked); + + self.end_progressbar(|pb| pb.abandon()); + + Some(self) + } + pub fn file_names(&self) -> Vec<&str> { self.inner.file_names() } diff --git a/src/cachefile.rs b/src/cachefile.rs index 7640800..44d07a0 100644 --- a/src/cachefile.rs +++ b/src/cachefile.rs @@ -118,6 +118,10 @@ impl CacheFile { self.files.push_front(FileState::U(file)); } + pub fn requeue_file(&mut self, file: file::Checked) { + self.files.push_back(FileState::C(file)); + } + pub fn share_notify(&self, client: &impl Client) -> sharry::Result<()> { client.share_notify(&self.uri, &self.alias_id, &self.share_id) } diff --git a/src/file/checked.rs b/src/file/checked.rs index 69e4ba2..58bdf79 100644 --- a/src/file/checked.rs +++ b/src/file/checked.rs @@ -17,9 +17,9 @@ use super::{FileTrait, Uploading}; #[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct Checked { /// canonical path to a regular file - path: PathBuf, + pub(super) path: PathBuf, /// size of that file - size: u64, + pub(super) size: u64, } impl Checked { diff --git a/src/file/uploading.rs b/src/file/uploading.rs index 587ded7..6c924c2 100644 --- a/src/file/uploading.rs +++ b/src/file/uploading.rs @@ -7,7 +7,7 @@ use std::{ use log::warn; use serde::{Deserialize, Serialize}; -use super::{Chunk, FileTrait}; +use super::{Checked, Chunk, FileTrait}; #[derive(Serialize, Deserialize, Debug)] pub struct Uploading { @@ -74,6 +74,13 @@ impl Uploading { Err(self.path) } } + + pub fn abort(self) -> Checked { + Checked { + path: self.path, + size: self.size, + } + } } impl<'t> FileTrait<'t> for Uploading { diff --git a/src/main.rs b/src/main.rs index 7332baf..de85892 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,8 @@ use log::{info, trace}; use appstate::AppState; use cli::Cli; -use output::{Log, SHRUPL, prompt_continue}; +use output::{Log, SHRUPL}; +use sharry::{ClientError, Parameter}; fn main() { let check_ctrlc = { @@ -52,7 +53,7 @@ fn main() { println!("{} to {}!", style("Welcome").magenta().bold(), *SHRUPL); let mut state = AppState::try_resume(&args) - .and_then(|state| prompt_continue().then_some(state)) + .and_then(|state| output::prompt_continue().then_some(state)) .unwrap_or_else(|| { check_ctrlc(); @@ -86,17 +87,36 @@ fn main() { match state.upload_chunk(&mut buffer) { Err(e) => { - // TODO better error handling (this will just retry endlessly) - // Error 404: Share might have been deleted Log::handle(&e); + tries += 1; - if let Some(s) = state.rewind() { - tries += 1; - trace!("State rewound, retrying last chunk (tried: {tries})"); + match e { + ClientError::InvalidParameter(p) => match p { + // TODO Error 404: File not found + Parameter::FileID(fid) => { + // requeue file + let Some(s) = state.requeue_file() else { + Log::error("Failed to requeue file!"); + }; - state = s; - } else { - Log::error("Failed to retry chunk!"); + trace!("File {fid:?} requeued (tried: {tries})"); + state = s; + } + // TODO Error 404: Share might have been deleted + Parameter::ShareID(sid) => { + Log::error(format_args!("404 sid: {sid}")); + } + p => Log::error(format_args!("Unexpected {p}!")), + }, + _ => { + // retry chunk + let Some(s) = state.rewind() else { + Log::error("Failed to retry chunk!"); + }; + + trace!("State rewound, retrying last chunk (tried: {tries})"); + state = s; + } } } Ok(false) => {