diff --git a/src/commands/clone.rs b/src/commands/clone.rs index 1620534..0625044 100644 --- a/src/commands/clone.rs +++ b/src/commands/clone.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use clap::Values; use regex::Regex; use crate::services::api::ApiError; -use crate::services::list_folders::ListFolders; +use crate::services::req_props::ReqProps; use crate::services::download_files::DownloadFiles; use crate::store::object; use crate::commands; @@ -48,10 +48,10 @@ pub fn clone(remote: Values<'_>) { // request folder content let mut objs = vec![]; tokio::runtime::Runtime::new().unwrap().block_on(async { - let res = ListFolders::new() + let res = ReqProps::new() .set_request(folder.as_str(), &api_props) .gethref() - .send_with_res() + .send_req_multiple() .await; objs = match res { Ok(o) => o, diff --git a/src/commands/push.rs b/src/commands/push.rs index 7ec2215..060be40 100644 --- a/src/commands/push.rs +++ b/src/commands/push.rs @@ -1,5 +1,5 @@ use crate::commands::{status, config}; -use crate::services::req_props::ReqProps; +use crate::services::req_props::{ReqProps, ObjProps}; use crate::services::api::ApiError; use crate::services::upload_file::UploadFile; use crate::services::delete_path::DeletePath; @@ -61,14 +61,14 @@ impl PushChange for New { let res = ReqProps::new() .set_url(&self.obj.path.to_str().unwrap()) .getlastmodified() - .send_with_err() + .send_req_single() .await; match res { - Ok(data) => Ok(data), + Ok(obj) => Ok(Some(obj)), Err(ApiError::IncorrectRequest(err)) => { if err.status() == 404 { - Ok(vec![]) + Ok(None) } else { Err(()) } @@ -78,7 +78,7 @@ impl PushChange for New { }); if let Ok(infos) = file_infos { - if infos.len() == 0 { + if let Some(info) = infos { // file doesn't exist on remote PushState::Valid } else { @@ -114,6 +114,7 @@ impl PushChange for New { // update tree add_blob(&obj.path.clone(), "todo_date"); + // remove index index::rm_line(obj.path.to_str().unwrap()); } @@ -135,10 +136,10 @@ impl PushChange for Deleted { .await; match res { - Ok(data) => Ok(data), + Ok(obj) => Ok(Some(obj)), Err(ApiError::IncorrectRequest(err)) => { if err.status() == 404 { - Ok(vec![]) + Ok(None) } else { Err(()) } @@ -148,7 +149,7 @@ impl PushChange for Deleted { }); if let Ok(infos) = file_infos { - if infos.len() == 0 { + if let Some(inf) = infos { // file doesn't exist on remote PushState::Done } else { @@ -202,3 +203,5 @@ impl PushFactory { } } } + + diff --git a/src/services.rs b/src/services.rs index 316c9fc..7db338b 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1,5 +1,4 @@ pub mod api; -pub mod list_folders; pub mod download_files; pub mod req_props; pub mod upload_file; diff --git a/src/services/list_folders.rs b/src/services/list_folders.rs deleted file mode 100644 index c7dd0af..0000000 --- a/src/services/list_folders.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::services::api::{ApiBuilder, ApiError}; -use crate::utils::api::{ApiProps, get_relative_s}; -use xml::reader::{EventReader, XmlEvent}; -use std::io::Cursor; -use reqwest::{Method, Response, Error}; - -#[derive(Debug)] -pub struct FolderContent { - pub href: Option, - pub relative_s: Option, -} - -impl Clone for FolderContent { - fn clone(&self) -> Self { - FolderContent { - href: self.href.clone(), - relative_s: self.relative_s.clone(), - } - } -} - -impl FolderContent { - fn new() -> Self { - FolderContent { - href: None, - relative_s: None, - } - } -} - -pub struct ListFolders { - api_builder: ApiBuilder, - xml_balises: Vec, - api_props: Option -} - -impl ListFolders { - pub fn new() -> Self { - ListFolders { - api_builder: ApiBuilder::new(), - xml_balises: vec![], - api_props: None, - } - } - - pub fn set_url(&mut self, url: &str) -> &mut ListFolders { - self.api_builder.build_request(Method::from_bytes(b"PROPFIND").unwrap(), url); - self - } - - pub fn set_request(&mut self, p: &str, api_props: &ApiProps) -> &mut ListFolders { - self.api_props = Some(api_props.clone()); - self.api_builder.set_req(Method::from_bytes(b"PROPFIND").unwrap(), p, api_props); - self - } - - pub fn gethref(&mut self) -> &mut ListFolders { - self.xml_balises.push(String::from("href")); - self - } - - pub async fn send(&mut self) -> Result { - self.api_builder.send().await - } - - pub async fn send_with_err(&mut self) -> Result { - let res = self.send().await.map_err(ApiError::RequestError)?; - if res.status().is_success() { - let body = res.text().await.map_err(ApiError::EmptyError)?; - Ok(body) - } else { - Err(ApiError::IncorrectRequest(res)) - } - } - - pub async fn send_with_res(&mut self) -> Result, ApiError> { - match self.send_with_err().await { - Ok(body) => Ok(self.parse(body)), - Err(err) => Err(err), - } - } - - pub fn parse(&self, xml: String) -> Vec { - let cursor = Cursor::new(xml); - let parser = EventReader::new(cursor); - - let mut should_get = false; - let mut values: Vec = vec![]; - - let mut iter = self.xml_balises.iter(); - let mut val = iter.next(); - let mut content = FolderContent::new(); - - for event in parser { - match event { - Ok(XmlEvent::StartElement { name, .. }) => { - if let Some(v) = val.clone() { - should_get = &name.local_name == v; - } else { - // end of balises to get then start over for next object - values.push(content.clone()); - iter = self.xml_balises.iter(); - val = iter.next(); - content = FolderContent::new(); - if let Some(v) = val.clone() { - should_get = &name.local_name == v; - } - } - } - Ok(XmlEvent::Characters(text)) => { - if !text.trim().is_empty() && should_get { - match val.unwrap().as_str() { - "href" => { - content.href = Some(text.clone()); - content.relative_s = Some(get_relative_s(text, &(self.api_props.clone().unwrap()))); - dbg!(content.relative_s.clone()); - }, - _ => (), - } - val = iter.next() - } - } - Ok(XmlEvent::EndElement { .. }) => { - should_get = false; - } - Err(e) => { - eprintln!("Error: {}", e); - break; - } - _ => {} - } - } - values - } -} diff --git a/src/services/req_props.rs b/src/services/req_props.rs index d921134..eed9ac8 100644 --- a/src/services/req_props.rs +++ b/src/services/req_props.rs @@ -1,20 +1,47 @@ use crate::services::api::{ApiBuilder, ApiError}; +use crate::utils::api::get_relative_s; use xml::reader::{EventReader, XmlEvent}; use std::io::Cursor; use reqwest::{Method, Response, Error}; +use crate::utils::api::ApiProps; + +pub struct ObjProps { + pub href: Option, + pub relative_s: Option, +} + +impl Clone for ObjProps { + fn clone(&self) -> Self { + ObjProps { + href: self.href.clone(), + relative_s: self.relative_s.clone(), + } + } +} + +impl ObjProps { + fn new() -> Self { + ObjProps { + href: None, + relative_s: None, + } + } +} pub struct ReqProps { api_builder: ApiBuilder, - xml_list: Vec, + xml_balises: Vec, xml_payload: String, + api_props: Option } impl ReqProps { pub fn new() -> Self { ReqProps { api_builder: ApiBuilder::new(), - xml_list: vec![], + xml_balises: vec![], xml_payload: String::new(), + api_props: None, } } @@ -23,38 +50,49 @@ impl ReqProps { self } + pub fn set_request(&mut self, p: &str, api_props: &ApiProps) -> &mut ReqProps { + self.api_props = Some(api_props.clone()); + self.api_builder.set_req(Method::from_bytes(b"PROPFIND").unwrap(), p, api_props); + self + } + + pub fn gethref(&mut self) -> &mut ReqProps { + self.xml_balises.push(String::from("href")); + self + } + pub fn getlastmodified(&mut self) -> &mut ReqProps { - self.xml_list.push(String::from("getlastmodified")); + self.xml_balises.push(String::from("getlastmodified")); self.xml_payload.push_str(r#""#); self } pub fn getcontentlenght(&mut self) -> &mut ReqProps { - self.xml_list.push(String::from("getcontentlength")); + self.xml_balises.push(String::from("getcontentlength")); self.xml_payload.push_str(r#""#); self } pub fn _getcontenttype(&mut self) -> &mut ReqProps { - self.xml_list.push(String::from("getcontenttype")); + self.xml_balises.push(String::from("getcontenttype")); self.xml_payload.push_str(r#""#); self } pub fn _getpermissions(&mut self) -> &mut ReqProps { - self.xml_list.push(String::from("permissions")); + self.xml_balises.push(String::from("permissions")); self.xml_payload.push_str(r#""#); self } pub fn _getressourcetype(&mut self) -> &mut ReqProps { - self.xml_list.push(String::from("resourcetype")); + self.xml_balises.push(String::from("resourcetype")); self.xml_payload.push_str(r#""#); self } pub fn _getetag(&mut self) -> &mut ReqProps { - self.xml_list.push(String::from("getetag")); + self.xml_balises.push(String::from("getetag")); self.xml_payload.push_str(r#""#); self } @@ -72,24 +110,44 @@ impl ReqProps { self.api_builder.send().await } - pub async fn send_with_err(&mut self) -> Result, ApiError> { + pub async fn send_with_err(&mut self) -> Result { let res = self.send().await.map_err(ApiError::RequestError)?; if res.status().is_success() { let body = res.text().await.map_err(ApiError::EmptyError)?; - Ok(self.parse(body)) + Ok(body) } else { Err(ApiError::IncorrectRequest(res)) } } - pub fn parse(&self, xml: String) -> Vec { + pub async fn send_req_multiple(&mut self) -> Result, ApiError> { + match self.send_with_err().await { + Ok(body) => Ok(self.parse(body, true)), + Err(err) => Err(err), + } + } + + pub async fn send_req_single(&mut self) -> Result { + match self.send_with_err().await { + Ok(body) => { + let objs = self.parse(body, false); + let obj = objs[0].clone(); + Ok(obj) + }, + Err(err) => Err(err), + } + } + + fn parse(&self, xml: String, multiple: bool) -> Vec { let cursor = Cursor::new(xml); let parser = EventReader::new(cursor); let mut should_get = false; - let mut values: Vec = vec![]; - let mut iter = self.xml_list.iter(); + let mut values: Vec = vec![]; + + let mut iter = self.xml_balises.iter(); let mut val = iter.next(); + let mut content = ObjProps::new(); for event in parser { match event { @@ -97,12 +155,30 @@ impl ReqProps { if let Some(v) = val.clone() { should_get = &name.local_name == v; } else { - break; + // end of balises to get then start over for + // next object if want multiple + if multiple { + values.push(content.clone()); + iter = self.xml_balises.iter(); + val = iter.next(); + content = ObjProps::new(); + if let Some(v) = val.clone() { + should_get = &name.local_name == v; + } + } else { + break; + } } } Ok(XmlEvent::Characters(text)) => { if !text.trim().is_empty() && should_get { - values.push(text); + match val.unwrap().as_str() { + "href" => { + content.href = Some(text.clone()); + content.relative_s = Some(get_relative_s(text, &(self.api_props.clone().unwrap()))); + }, + _ => (), + } val = iter.next() } }