shrupl/src/main.rs

141 lines
3.9 KiB
Rust
Raw Normal View History

2025-06-02 23:57:17 +00:00
mod appstate;
mod cachefile;
2025-05-28 00:07:59 +00:00
mod cli;
mod file;
mod impl_ureq;
mod output;
2025-05-22 17:34:44 +00:00
mod sharry;
2025-06-05 01:44:39 +00:00
use std::{
process,
2025-06-05 01:44:39 +00:00
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
2025-06-05 01:34:12 +00:00
};
2025-05-27 14:01:09 +00:00
use clap::Parser;
use console::style;
use log::{info, trace};
2025-05-22 17:34:44 +00:00
2025-06-02 23:57:17 +00:00
use appstate::AppState;
2025-05-28 00:07:59 +00:00
use cli::Cli;
2025-06-18 19:40:34 +00:00
use output::{Log, SHRUPL};
use sharry::{ClientError, Parameter};
2025-05-17 23:57:52 +00:00
fn main() {
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");
2025-06-05 01:34:12 +00:00
move || {
if stop.load(Ordering::SeqCst) {
process::exit(255);
}
}
};
2025-05-22 17:34:44 +00:00
2025-05-28 00:07:59 +00:00
let args = Cli::parse();
2025-06-18 18:58:49 +00:00
env_logger::Builder::new()
.filter_module("shrupl", args.get_level_filter())
.parse_default_env()
.init();
info!("args: {args:#?}");
2025-05-22 17:34:44 +00:00
println!("{} to {}!", style("Welcome").magenta().bold(), *SHRUPL);
2025-06-05 11:20:27 +00:00
let mut state = AppState::try_resume(&args)
2025-06-18 19:40:34 +00:00
.and_then(|state| output::prompt_continue().then_some(state))
2025-06-05 12:58:09 +00:00
.unwrap_or_else(|| {
check_ctrlc();
2025-06-05 12:58:09 +00:00
match AppState::from_args(&args) {
2025-06-05 12:58:09 +00:00
Ok(state) => {
2025-06-12 23:28:42 +00:00
state.save().unwrap_or_else(|e| {
Log::warning(format_args!("Failed to save state: {e}"));
2025-06-12 23:28:42 +00:00
});
2025-06-05 12:58:09 +00:00
state
}
2025-06-05 12:58:09 +00:00
Err(e) => {
Log::handle(&e);
Log::error(format_args!("Failed to create state: {e}"));
2025-06-05 12:58:09 +00:00
}
2025-06-05 11:20:27 +00:00
}
});
2025-06-04 21:02:35 +00:00
info!("continuing with state: {state:#?}");
let fns_magenta = output::style_all(&args.file_names(), |s| style(s).magenta()).join(", ");
2025-06-13 23:50:42 +00:00
println!("{} is uploading: {fns_magenta}", *SHRUPL);
2025-06-05 17:37:35 +00:00
let mut buffer = vec![0; args.chunk_size * 1024 * 1024];
2025-06-18 18:44:24 +00:00
let mut tries = 0;
2025-06-05 01:13:54 +00:00
loop {
2025-06-18 18:44:24 +00:00
if !args.may_retry(tries) {
Log::error("Retry limit reached!");
}
match state.upload_chunk(&mut buffer) {
Err(e) => {
Log::handle(&e);
2025-06-18 19:40:34 +00:00
tries += 1;
if let ClientError::InvalidParameter(p) = e { 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!");
2025-06-18 19:40:34 +00:00
};
trace!("File {fid:?} requeued (tried: {tries})");
2025-06-18 19:40:34 +00:00
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}!")),
} } else {
// retry chunk
let Some(s) = state.rewind() else {
Log::error("Failed to retry chunk!");
};
trace!("State rewound, retrying last chunk (tried: {tries})");
state = s;
2025-06-13 23:11:40 +00:00
}
}
Ok(false) => {
trace!("chunk uploaded");
2025-06-18 18:44:24 +00:00
tries = 0;
}
Ok(true) => {
2025-06-05 11:20:27 +00:00
info!("all uploads done");
break;
}
}
2025-06-05 01:13:54 +00:00
2025-06-12 23:28:42 +00:00
state.save().unwrap_or_else(|e| {
Log::warning(format_args!("Failed to save state: {e}"));
2025-06-12 23:28:42 +00:00
});
check_ctrlc();
2025-05-26 20:31:22 +00:00
}
2025-06-13 23:02:41 +00:00
state.clear().unwrap_or_else(|e| {
Log::warning(format_args!("Failed to remove state: {e}"));
2025-06-13 23:02:41 +00:00
});
println!("{} finished {}", *SHRUPL, style("successfully!").green());
2025-05-17 23:57:52 +00:00
}