diff --git a/src/appstate.rs b/src/appstate.rs index ed01d39..ded7a4b 100644 --- a/src/appstate.rs +++ b/src/appstate.rs @@ -4,7 +4,7 @@ use std::{ path::{Path, PathBuf}, }; -use log::{debug, trace}; +use log::{debug, error, trace}; use serde::{Deserialize, Serialize}; use super::{ @@ -14,46 +14,98 @@ use super::{ #[derive(Serialize, Deserialize, Debug)] pub struct AppState { + #[serde(skip)] + file_name: PathBuf, + alias: Alias, share: Share, - checked: Vec, - uploading: Vec, + files: Vec, } -fn get_cachefile(args: &Cli) -> Option { - let file_name: PathBuf = dirs_next::cache_dir()? - .join("shrupl") - .join(format!("{}.json", args.get_hash())); - - trace!("cachefile: {}", file_name.display()); - - Some(file_name) +#[derive(Serialize, Deserialize, Debug)] +enum FileState { + C(FileChecked), + U(FileUploading), } impl AppState { + fn cache_dir() -> Option { + let dir_name = dirs_next::cache_dir()?.join("shrupl"); + + trace!("cachedir: {}", dir_name.display()); + + Some(dir_name) + } + + fn cache_file(args: &Cli) -> Option { + let file_name = Self::cache_dir()?.join(format!("{}.json", args.get_hash())); + + trace!("cachefile: {}", file_name.display()); + + Some(file_name) + } + fn load(file_name: impl AsRef) -> io::Result { let content = fs::read_to_string(file_name)?; serde_json::from_str(&content).map_err(io::Error::other) } - fn save(&self, file_name: impl AsRef) -> io::Result<()> { + pub fn try_resume(args: &Cli) -> Option { + let file_name = Self::cache_file(args)?; + + Self::load(&file_name) + .inspect_err(|e| debug!("could not resume from {}: {e}", file_name.display())) + .map(|state| { + debug!("successfully loaded AppState"); + + Self { + file_name, + alias: state.alias, + share: state.share, + files: state.files, + } + }) + .ok() + } + + pub fn from_args(args: Cli, agent: &ureq::Agent) -> Option { + let file_name = Self::cache_file(&args)?; + + let alias = args.get_alias(); + + let share = Share::create(&agent, &alias, args.get_share_request()) + .inspect_err(|e| error!("could not create Share: {e}")) + .ok()?; + + let files: Vec<_> = args.files.into_iter().map(|f| FileState::C(f)).collect(); + + Some(Self { + file_name, + alias, + share, + files, + }) + } + + pub fn save(&self) -> io::Result<()> { + let cache_dir = Self::cache_dir() + .ok_or_else(|| io::Error::other("could not determine cache directory"))?; + fs::create_dir_all(cache_dir)?; + let json = serde_json::to_string_pretty(self).map_err(io::Error::other)?; - let mut file = fs::File::create(file_name)?; + let mut file = fs::File::create(&self.file_name)?; file.write_all(json.as_bytes())?; + trace!("successfully saved AppState"); + Ok(()) } - pub fn try_resume(args: &Cli) -> Option { - let file_name = get_cachefile(args)?; + pub fn delete(self) -> io::Result<()> { + fs::remove_file(self.file_name)?; - // let content = fs::read_to_string(&file_name).ok()?; - // serde_json::from_str(&content) - // .inspect_err(|e| debug!("could not resume from {}: {e}", &file_name.display())) - // .ok() + trace!("successfully cleared AppState"); - Self::load(&file_name) - .inspect_err(|e| debug!("could not resume from {}: {e}", file_name.display())) - .ok() + Ok(()) } } diff --git a/src/main.rs b/src/main.rs index a8fbdc2..d65d6c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,9 +22,22 @@ fn main() { .build() .into(); - if let Some(state) = AppState::try_resume(&args) { - info!("state: {state:?}"); - } + let state = AppState::try_resume(&args) + .and_then(|state| { + info!("loaded state: {state:?}"); + + Some(state) + }) + .or_else(|| AppState::from_args(args, &agent)) + .unwrap_or_else(|| { + std::process::exit(1); + }); + + info!("continuing with state: {state:?}"); + state.save().unwrap(); + // state.delete().unwrap(); + + return; let alias = args.get_alias(); let share = Share::create(&agent, &alias, args.get_share_request()).unwrap();