[wip] impl Client for ureq::Agent
- progress bar handling - share notify timing
This commit is contained in:
parent
2edc690331
commit
b9a0e1eeb0
2 changed files with 54 additions and 26 deletions
|
|
@ -1,4 +1,8 @@
|
|||
use std::{fmt, io, time::Duration};
|
||||
use std::{
|
||||
cell::{Ref, RefCell},
|
||||
fmt, io,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use console::style;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
|
|
@ -7,12 +11,12 @@ use log::debug;
|
|||
use super::{
|
||||
cachefile::CacheFile,
|
||||
cli::Cli,
|
||||
file::FileTrait,
|
||||
file::{self, FileTrait},
|
||||
sharry::{self, Client, ClientError},
|
||||
};
|
||||
|
||||
pub struct AppState {
|
||||
progress: Option<ProgressBar>,
|
||||
current_bar: RefCell<Option<ProgressBar>>,
|
||||
buffer: Vec<u8>,
|
||||
|
||||
inner: CacheFile,
|
||||
|
|
@ -29,7 +33,7 @@ impl fmt::Debug for AppState {
|
|||
impl AppState {
|
||||
fn new(chunk_size: usize, inner: CacheFile) -> Self {
|
||||
Self {
|
||||
progress: None,
|
||||
current_bar: None.into(),
|
||||
buffer: vec![0; chunk_size * 1024 * 1024],
|
||||
inner,
|
||||
}
|
||||
|
|
@ -56,16 +60,9 @@ impl AppState {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn upload_chunk(&mut self, http: &impl Client) -> sharry::Result<Option<()>> {
|
||||
let Some(mut uploading) = self.inner.pop_file(http) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
debug!("{uploading} chunk {}", self.buffer.len());
|
||||
|
||||
// Initialize or fetch the existing ProgressBar
|
||||
let bar = &*self.progress.get_or_insert_with(|| {
|
||||
// Create a new bar with style
|
||||
fn get_or_create_progressbar(&self, uploading: &file::Uploading) -> Ref<'_, ProgressBar> {
|
||||
let mut slot = self.current_bar.borrow_mut();
|
||||
if slot.is_none() {
|
||||
let bar = ProgressBar::new(uploading.get_size())
|
||||
.with_style(
|
||||
ProgressStyle::with_template(&format!(
|
||||
|
|
@ -76,21 +73,42 @@ impl AppState {
|
|||
),
|
||||
style("/").magenta(),
|
||||
))
|
||||
.unwrap(),
|
||||
.unwrap(), // safe as long as the style template is valid
|
||||
)
|
||||
.with_message(uploading.get_name().to_owned())
|
||||
.with_position(uploading.get_offset());
|
||||
.with_position(uploading.get_offset())
|
||||
.with_message(uploading.get_name().to_owned());
|
||||
|
||||
bar.enable_steady_tick(Duration::from_millis(100));
|
||||
bar
|
||||
});
|
||||
*slot = Some(bar);
|
||||
}
|
||||
drop(slot);
|
||||
|
||||
// unwrap is safe: We just made sure it's `Some`.
|
||||
Ref::map(self.current_bar.borrow(), |opt| opt.as_ref().unwrap())
|
||||
}
|
||||
|
||||
fn finish_bar(&self) {
|
||||
let mut slot = self.current_bar.borrow_mut();
|
||||
if let Some(bar) = &*slot {
|
||||
bar.finish();
|
||||
*slot = None;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_chunk(&mut self, http: &impl Client) -> sharry::Result<Option<()>> {
|
||||
let Some(mut uploading) = self.inner.pop_file(http) else {
|
||||
self.inner.share_notify(http).unwrap(); // HACK unwrap
|
||||
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
self.get_or_create_progressbar(&uploading);
|
||||
|
||||
debug!("{uploading} chunk {}", self.buffer.len());
|
||||
|
||||
let chunk = uploading
|
||||
.read(&mut self.buffer)
|
||||
.map_err(ClientError::from)?;
|
||||
if chunk.get_length() == 0 {
|
||||
return Err(ClientError::req_err("wtf"));
|
||||
}
|
||||
|
||||
http.file_patch(
|
||||
chunk.get_patch_uri(),
|
||||
|
|
@ -101,16 +119,19 @@ impl AppState {
|
|||
|
||||
match uploading.check_eof() {
|
||||
Ok(uploading) => {
|
||||
let bar = self.get_or_create_progressbar(&uploading);
|
||||
bar.set_position(uploading.get_offset());
|
||||
// BUG in `indicatif` crate?
|
||||
// `set_position` does not force immediate redraw, so we also call `inc_length` here
|
||||
bar.inc_length(0);
|
||||
drop(bar);
|
||||
|
||||
self.inner.push_file(uploading);
|
||||
Ok(Some(()))
|
||||
}
|
||||
Err(path) => {
|
||||
debug!("Finished {:?}!", path.display());
|
||||
bar.finish();
|
||||
self.progress = None;
|
||||
|
||||
self.inner.share_notify(http).unwrap(); // HACK unwrap
|
||||
self.finish_bar();
|
||||
|
||||
Ok(self.inner.has_file().then_some(()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,13 @@ impl Uploading {
|
|||
f.seek(SeekFrom::Start(self.offset))?;
|
||||
let read_len = f.read(buf)?;
|
||||
|
||||
if read_len == 0 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::UnexpectedEof,
|
||||
format!("could not read from file {:?}", self.path.display()),
|
||||
));
|
||||
}
|
||||
|
||||
let chunk = Chunk::new(&buf[..read_len], &self.patch_uri, self.offset);
|
||||
self.offset += chunk.get_length();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue