loading bar when downloading
This commit is contained in:
parent
80d497d47c
commit
dfd42389f3
@ -9,7 +9,6 @@ use crate::utils::api::ApiProps;
|
||||
use crate::global::global::{DIR_PATH, set_dir_path};
|
||||
use crate::services::api::ApiError;
|
||||
use crate::services::req_props::{ReqProps, ObjProps};
|
||||
use crate::services::download_files::DownloadFiles;
|
||||
use crate::store::object::{tree, blob};
|
||||
use crate::commands::config;
|
||||
use crate::commands::init;
|
||||
@ -127,6 +126,7 @@ pub fn clone(remote: Values<'_>) {
|
||||
let downloader = Downloader::new()
|
||||
.set_api_props(api_props.clone())
|
||||
.set_files(files)
|
||||
.should_log()
|
||||
.download(ref_path.clone(), Some(&save_blob));
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ impl DownloadFiles {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_stream(&mut self, ref_p: PathBuf) -> Result<(), ApiError> {
|
||||
pub fn save_stream(&mut self, ref_p: PathBuf, callback: Option<impl Fn(u64)>) -> Result<(), ApiError> {
|
||||
let abs_p = ref_p.join(PathBuf::from(self.relative_ps.clone()));
|
||||
let mut file = File::create(abs_p).unwrap();
|
||||
|
||||
@ -48,11 +48,18 @@ impl DownloadFiles {
|
||||
let res = self.send().await.map_err(ApiError::RequestError)?;
|
||||
if res.status().is_success() {
|
||||
let mut stream = res.bytes_stream();
|
||||
|
||||
while let Some(chunk) = stream.next().await {
|
||||
if let Err(err) = file.write_all(&chunk.unwrap()) {
|
||||
let unwrap_chunk = chunk.unwrap();
|
||||
// save chunk inside file
|
||||
if let Err(err) = file.write_all(&unwrap_chunk) {
|
||||
return Err(ApiError::Unexpected(err.to_string()));
|
||||
} else if let Some(fct) = &callback {
|
||||
// call callback with size of this chunk
|
||||
fct(unwrap_chunk.len().try_into().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ApiError::IncorrectRequest(res))
|
||||
|
@ -1,4 +1,6 @@
|
||||
use std::path::PathBuf;
|
||||
use indicatif::{ProgressBar, MultiProgress, ProgressStyle, HumanBytes};
|
||||
|
||||
use crate::utils::api::ApiProps;
|
||||
use crate::services::api::ApiError;
|
||||
use crate::services::download_files::DownloadFiles;
|
||||
@ -10,6 +12,8 @@ pub struct Downloader {
|
||||
files: Vec<ObjProps>,
|
||||
should_log: bool,
|
||||
api_props: Option<ApiProps>,
|
||||
progress_bars: Vec<ProgressBar>,
|
||||
multi_progress: Option<MultiProgress>,
|
||||
}
|
||||
|
||||
impl Downloader {
|
||||
@ -18,6 +22,8 @@ impl Downloader {
|
||||
files: vec![],
|
||||
should_log: false,
|
||||
api_props: None,
|
||||
progress_bars: vec![],
|
||||
multi_progress: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,35 +47,95 @@ impl Downloader {
|
||||
self
|
||||
}
|
||||
|
||||
fn init_log(&mut self, nb_objs: u64, total_size: u64) {
|
||||
self.multi_progress = Some(MultiProgress::new());
|
||||
|
||||
self.progress_bars.push(
|
||||
self.multi_progress
|
||||
.clone()
|
||||
.unwrap()
|
||||
.add(ProgressBar::new(nb_objs).with_message("Objects")));
|
||||
|
||||
let msg = format!("0B/{}", HumanBytes(total_size).to_string());
|
||||
self.progress_bars.push(
|
||||
self.multi_progress
|
||||
.clone()
|
||||
.unwrap()
|
||||
.add(ProgressBar::new(total_size).with_message(msg)));
|
||||
|
||||
self.progress_bars[0].set_style(
|
||||
ProgressStyle::with_template("{_:>10} [{bar:40}] {pos}/{len} {msg}")
|
||||
.unwrap()
|
||||
.progress_chars("=> "));
|
||||
|
||||
self.progress_bars[1].set_style(
|
||||
ProgressStyle::with_template("[{elapsed_precise}] [{bar:40}] {msg}")
|
||||
.unwrap()
|
||||
.progress_chars("=> "));
|
||||
|
||||
self.progress_bars[0].tick();
|
||||
self.progress_bars[1].tick();
|
||||
}
|
||||
|
||||
fn update_bytes_bar(&self, size: u64) {
|
||||
let bytes_bar = &self.progress_bars[1];
|
||||
bytes_bar.inc(size);
|
||||
let msg = format!(
|
||||
"{}/{}",
|
||||
HumanBytes(bytes_bar.position()).to_string(),
|
||||
HumanBytes(bytes_bar.length().unwrap()).to_string());
|
||||
bytes_bar.set_message(msg);
|
||||
}
|
||||
|
||||
pub fn download(&mut self, ref_p: PathBuf, callback: Option<&dyn Fn(ObjProps)>) {
|
||||
if self.should_log {
|
||||
let mut total_size = 0;
|
||||
let nb_objs = self.files.len();
|
||||
|
||||
self.files
|
||||
.iter()
|
||||
.for_each(|f|
|
||||
if let Some(size) = f.contentlength {
|
||||
total_size += size
|
||||
}
|
||||
);
|
||||
|
||||
self.init_log(nb_objs.try_into().unwrap(), total_size);
|
||||
}
|
||||
|
||||
for file in self.files.clone() {
|
||||
let relative_s = &file.clone().relative_s.unwrap();
|
||||
let mut download = DownloadFiles::new();
|
||||
download.set_url(&relative_s, &self.api_props.clone().unwrap());
|
||||
|
||||
let res = {
|
||||
let should_use_stream = {
|
||||
if let Some(size) = file.contentlength {
|
||||
if size > SIZE_TO_STREAM {
|
||||
download.save_stream(ref_p.clone())
|
||||
true
|
||||
} else {
|
||||
download.save(ref_p.clone())
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
// download
|
||||
let res = {
|
||||
if should_use_stream {
|
||||
// todo should increment here
|
||||
download.save_stream(ref_p.clone(), Some(|a| self.update_bytes_bar(a)))
|
||||
} else {
|
||||
download.save(ref_p.clone())
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// deal with error
|
||||
match res {
|
||||
Ok(()) => {
|
||||
if let Some(fct) = callback {
|
||||
fct(file);
|
||||
fct(file.clone());
|
||||
}
|
||||
//let relative_p = PathBuf::from(&relative_s);
|
||||
//let lastmodified = obj.clone().lastmodified.unwrap().timestamp_millis();
|
||||
//if let Err(err) = blob::add(relative_p, &lastmodified.to_string()) {
|
||||
// eprintln!("err: saving ref of {} ({})", relative_s.clone(), err);
|
||||
//}
|
||||
},
|
||||
Err(ApiError::Unexpected(_)) => {
|
||||
eprintln!("err: writing {}", relative_s);
|
||||
@ -84,6 +150,22 @@ impl Downloader {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// increment loading bars
|
||||
if self.should_log {
|
||||
self.progress_bars[0].inc(1); // increment object
|
||||
|
||||
// increment bytes only if
|
||||
// not incremented continuously by stream
|
||||
if !should_use_stream {
|
||||
self.update_bytes_bar(file.contentlength.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// finish all bars
|
||||
for bar in &self.progress_bars {
|
||||
bar.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user