From 0832100d8309f247274afd0bd772bc9a0edceb26 Mon Sep 17 00:00:00 2001 From: grimhilt Date: Fri, 21 Jul 2023 14:45:45 +0200 Subject: [PATCH] enumerate_remote function & applied to clone --- src/commands/clone.rs | 108 ++++++++++++-------------------------- src/services/req_props.rs | 11 ++++ src/utils.rs | 1 + src/utils/remote.rs | 50 ++++++++++++++++++ 4 files changed, 97 insertions(+), 73 deletions(-) create mode 100644 src/utils/remote.rs diff --git a/src/commands/clone.rs b/src/commands/clone.rs index 6afbeb3..7e1fdde 100644 --- a/src/commands/clone.rs +++ b/src/commands/clone.rs @@ -6,6 +6,7 @@ use clap::Values; use regex::Regex; use crate::services::downloader::Downloader; use crate::utils::api::ApiProps; +use crate::utils::remote::enumerate_remote; use crate::global::global::{DIR_PATH, set_dir_path}; use crate::services::api::ApiError; use crate::services::req_props::{ReqProps, ObjProps}; @@ -43,84 +44,36 @@ pub fn clone(remote: Values<'_>) { }, }; - let mut folders: Vec = vec![ObjProps::new()]; - let mut files: Vec = vec![]; - let mut first_iter = true; - while folders.len() > 0 { - let folder = folders.pop().unwrap(); + // try to create root folder + if DirBuilder::new().recursive(true).create(ref_path.clone()).is_err() { + eprintln!("fatal: unable to create the destination directory"); + std::process::exit(1); + } else { + init::init(); + let mut remote_config = api_props.username.clone(); + remote_config.push_str("@"); + remote_config.push_str(api_props.host.strip_prefix("https://").unwrap()); + remote_config.push_str(&api_props.root); + if config::set("remote", &remote_config).is_err() { + eprintln!("err: not able to save remote"); + } + } - let relative_s = match folder.relative_s { - Some(relative_s) => relative_s, - None => String::from(""), - }; + let (folders, files) = enumerate_remote(|a| req(&api_props, a)); - // request folder content - let res = ReqProps::new() - .set_request(relative_s.as_str(), &api_props) - .gethref() - .getcontentlength() - .getlastmodified() - .send_req_multiple(); - - let objs = match res { - Ok(o) => o, - Err(ApiError::IncorrectRequest(err)) => { - eprintln!("fatal: {}", err.status()); - std::process::exit(1); - }, - Err(ApiError::EmptyError(_)) => { - eprintln!("Failed to get body"); - vec![] - } - Err(ApiError::RequestError(err)) => { - eprintln!("fatal: {}", err); - std::process::exit(1); - }, - Err(ApiError::Unexpected(_)) => todo!() - }; - - // create object - if first_iter { - // root folder, init and config - if DirBuilder::new().recursive(true).create(ref_path.clone()).is_err() { - eprintln!("fatal: unable to create the destination directory"); - std::process::exit(1); - } else { - init::init(); - let mut remote_config = api_props.username.clone(); - remote_config.push_str("@"); - remote_config.push_str(api_props.host.strip_prefix("https://").unwrap()); - remote_config.push_str(&api_props.root); - if config::set("remote", &remote_config).is_err() { - eprintln!("err: not able to save remote"); - } - } - } else { - // create folder - let p = ref_path.clone().join(Path::new(&relative_s)); - if let Err(err) = DirBuilder::new().recursive(true).create(p.clone()) { - eprintln!("err: cannot create directory {} ({})", p.display(), err); - } - - // add tree - let path_folder = p.strip_prefix(ref_path.clone()).unwrap(); - let lastmodified = folder.lastmodified.unwrap().timestamp_millis(); - if let Err(err) = tree::add(path_folder.to_path_buf(), &lastmodified.to_string(), false) { - eprintln!("err: saving ref of {} ({})", path_folder.display(), err); - } + for folder in folders { + // create folder + let p = ref_path.clone().join(Path::new(&folder.relative_s.unwrap())); + if let Err(err) = DirBuilder::new().recursive(true).create(p.clone()) { + eprintln!("err: cannot create directory {} ({})", p.display(), err); } - // find folders and files in response - let mut iter = objs.iter(); - iter.next(); // jump first element which is the folder cloned - for object in iter { - if object.href.clone().unwrap().chars().last().unwrap() == '/' { - folders.push(object.clone()); - } else { - files.push(object.clone()); - } + // add tree + let path_folder = p.strip_prefix(ref_path.clone()).unwrap(); + let lastmodified = folder.lastmodified.unwrap().timestamp_millis(); + if let Err(err) = tree::add(path_folder.to_path_buf(), &lastmodified.to_string(), false) { + eprintln!("err: saving ref of {} ({})", path_folder.display(), err); } - first_iter = false; } let downloader = Downloader::new() @@ -139,6 +92,15 @@ fn save_blob(obj: ObjProps) { } } +fn req(api_props: &ApiProps, relative_s: &str) -> Result, ApiError> { + ReqProps::new() + .set_request(relative_s, &api_props) + .gethref() + .getcontentlength() + .getlastmodified() + .send_req_multiple() +} + pub fn get_url_props(url: &str) -> (String, Option<&str>, &str) { let mut username = None; let mut domain = ""; diff --git a/src/services/req_props.rs b/src/services/req_props.rs index 02135cc..4087ee0 100644 --- a/src/services/req_props.rs +++ b/src/services/req_props.rs @@ -37,6 +37,15 @@ impl ObjProps { contentlength: None, } } + + pub fn is_dir(&self) -> bool { + if let Some(href) = &self.href { + href.chars().last().unwrap() == '/' + } else { + eprintln!("err: cannot determine object type wihout href"); + false + } + } } pub struct ReqProps { @@ -81,6 +90,7 @@ impl ReqProps { } pub fn gethref(&mut self) -> &mut ReqProps { + // not an actual property but used to prevent getting anything else self.xml_balises.push(String::from("href")); self } @@ -127,6 +137,7 @@ impl ReqProps { } fn validate_xml(&mut self) -> &mut ReqProps { + self.gethref(); let mut xml = String::from(r#""#); xml.push_str(&self.xml_payload.clone()); xml.push_str(r#""#); diff --git a/src/utils.rs b/src/utils.rs index f530c31..1d32f8e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -3,3 +3,4 @@ pub mod read; pub mod nextsyncignore; pub mod api; pub mod time; +pub mod remote; diff --git a/src/utils/remote.rs b/src/utils/remote.rs new file mode 100644 index 0000000..8e4666f --- /dev/null +++ b/src/utils/remote.rs @@ -0,0 +1,50 @@ +use crate::services::{req_props::ObjProps, api::ApiError}; + +pub fn enumerate_remote(req: impl Fn(&str) -> Result, ApiError>) -> (Vec, Vec) { + let mut folders: Vec = vec![ObjProps::new()]; + let mut all_folders: Vec = vec![]; + let mut files: Vec = vec![]; + + while folders.len() > 0 { + let folder = folders.pop().unwrap(); + + let relative_s = match folder.relative_s { + Some(relative_s) => relative_s, + None => String::from(""), + }; + + // request folder content + let res = req(relative_s.as_str()); + + let objs = match res { + Ok(o) => o, + Err(ApiError::IncorrectRequest(err)) => { + eprintln!("fatal: {}", err.status()); + std::process::exit(1); + }, + Err(ApiError::EmptyError(_)) => { + eprintln!("Failed to get body"); + vec![] + } + Err(ApiError::RequestError(err)) => { + eprintln!("fatal: {}", err); + std::process::exit(1); + }, + Err(ApiError::Unexpected(_)) => todo!() + }; + + // find folders and files in response + let mut iter = objs.iter(); + iter.next(); // jump first element which is the folder cloned + for object in iter { + if object.is_dir() { + folders.push(object.clone()); + all_folders.push(object.clone()); + } else { + files.push(object.clone()); + } + } + } + + (all_folders, files) +}