merge list folders and req props

This commit is contained in:
grimhilt 2023-06-17 16:26:31 +02:00
parent eabf707844
commit 1fd7948122
5 changed files with 105 additions and 162 deletions

View File

@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
use clap::Values; use clap::Values;
use regex::Regex; use regex::Regex;
use crate::services::api::ApiError; 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::services::download_files::DownloadFiles;
use crate::store::object; use crate::store::object;
use crate::commands; use crate::commands;
@ -48,10 +48,10 @@ pub fn clone(remote: Values<'_>) {
// request folder content // request folder content
let mut objs = vec![]; let mut objs = vec![];
tokio::runtime::Runtime::new().unwrap().block_on(async { tokio::runtime::Runtime::new().unwrap().block_on(async {
let res = ListFolders::new() let res = ReqProps::new()
.set_request(folder.as_str(), &api_props) .set_request(folder.as_str(), &api_props)
.gethref() .gethref()
.send_with_res() .send_req_multiple()
.await; .await;
objs = match res { objs = match res {
Ok(o) => o, Ok(o) => o,

View File

@ -1,5 +1,5 @@
use crate::commands::{status, config}; 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::api::ApiError;
use crate::services::upload_file::UploadFile; use crate::services::upload_file::UploadFile;
use crate::services::delete_path::DeletePath; use crate::services::delete_path::DeletePath;
@ -61,14 +61,14 @@ impl PushChange for New {
let res = ReqProps::new() let res = ReqProps::new()
.set_url(&self.obj.path.to_str().unwrap()) .set_url(&self.obj.path.to_str().unwrap())
.getlastmodified() .getlastmodified()
.send_with_err() .send_req_single()
.await; .await;
match res { match res {
Ok(data) => Ok(data), Ok(obj) => Ok(Some(obj)),
Err(ApiError::IncorrectRequest(err)) => { Err(ApiError::IncorrectRequest(err)) => {
if err.status() == 404 { if err.status() == 404 {
Ok(vec![]) Ok(None)
} else { } else {
Err(()) Err(())
} }
@ -78,7 +78,7 @@ impl PushChange for New {
}); });
if let Ok(infos) = file_infos { if let Ok(infos) = file_infos {
if infos.len() == 0 { if let Some(info) = infos {
// file doesn't exist on remote // file doesn't exist on remote
PushState::Valid PushState::Valid
} else { } else {
@ -114,6 +114,7 @@ impl PushChange for New {
// update tree // update tree
add_blob(&obj.path.clone(), "todo_date"); add_blob(&obj.path.clone(), "todo_date");
// remove index // remove index
index::rm_line(obj.path.to_str().unwrap()); index::rm_line(obj.path.to_str().unwrap());
} }
@ -135,10 +136,10 @@ impl PushChange for Deleted {
.await; .await;
match res { match res {
Ok(data) => Ok(data), Ok(obj) => Ok(Some(obj)),
Err(ApiError::IncorrectRequest(err)) => { Err(ApiError::IncorrectRequest(err)) => {
if err.status() == 404 { if err.status() == 404 {
Ok(vec![]) Ok(None)
} else { } else {
Err(()) Err(())
} }
@ -148,7 +149,7 @@ impl PushChange for Deleted {
}); });
if let Ok(infos) = file_infos { if let Ok(infos) = file_infos {
if infos.len() == 0 { if let Some(inf) = infos {
// file doesn't exist on remote // file doesn't exist on remote
PushState::Done PushState::Done
} else { } else {
@ -202,3 +203,5 @@ impl PushFactory {
} }
} }
} }

View File

@ -1,5 +1,4 @@
pub mod api; pub mod api;
pub mod list_folders;
pub mod download_files; pub mod download_files;
pub mod req_props; pub mod req_props;
pub mod upload_file; pub mod upload_file;

View File

@ -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<String>,
pub relative_s: Option<String>,
}
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<String>,
api_props: Option<ApiProps>
}
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<Response, Error> {
self.api_builder.send().await
}
pub async fn send_with_err(&mut self) -> Result<String, ApiError> {
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<Vec<FolderContent>, ApiError> {
match self.send_with_err().await {
Ok(body) => Ok(self.parse(body)),
Err(err) => Err(err),
}
}
pub fn parse(&self, xml: String) -> Vec<FolderContent> {
let cursor = Cursor::new(xml);
let parser = EventReader::new(cursor);
let mut should_get = false;
let mut values: Vec<FolderContent> = 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
}
}

View File

@ -1,20 +1,47 @@
use crate::services::api::{ApiBuilder, ApiError}; use crate::services::api::{ApiBuilder, ApiError};
use crate::utils::api::get_relative_s;
use xml::reader::{EventReader, XmlEvent}; use xml::reader::{EventReader, XmlEvent};
use std::io::Cursor; use std::io::Cursor;
use reqwest::{Method, Response, Error}; use reqwest::{Method, Response, Error};
use crate::utils::api::ApiProps;
pub struct ObjProps {
pub href: Option<String>,
pub relative_s: Option<String>,
}
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 { pub struct ReqProps {
api_builder: ApiBuilder, api_builder: ApiBuilder,
xml_list: Vec<String>, xml_balises: Vec<String>,
xml_payload: String, xml_payload: String,
api_props: Option<ApiProps>
} }
impl ReqProps { impl ReqProps {
pub fn new() -> Self { pub fn new() -> Self {
ReqProps { ReqProps {
api_builder: ApiBuilder::new(), api_builder: ApiBuilder::new(),
xml_list: vec![], xml_balises: vec![],
xml_payload: String::new(), xml_payload: String::new(),
api_props: None,
} }
} }
@ -23,38 +50,49 @@ impl ReqProps {
self 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 { 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#"<d:getlastmodified/>"#); self.xml_payload.push_str(r#"<d:getlastmodified/>"#);
self self
} }
pub fn getcontentlenght(&mut self) -> &mut ReqProps { 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#"<d:getcontentlength/>"#); self.xml_payload.push_str(r#"<d:getcontentlength/>"#);
self self
} }
pub fn _getcontenttype(&mut self) -> &mut ReqProps { 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#"<d:getcontenttype/>"#); self.xml_payload.push_str(r#"<d:getcontenttype/>"#);
self self
} }
pub fn _getpermissions(&mut self) -> &mut ReqProps { 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#"<oc:permissions/>"#); self.xml_payload.push_str(r#"<oc:permissions/>"#);
self self
} }
pub fn _getressourcetype(&mut self) -> &mut ReqProps { 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#"<d:resourcetype/>"#); self.xml_payload.push_str(r#"<d:resourcetype/>"#);
self self
} }
pub fn _getetag(&mut self) -> &mut ReqProps { 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#"<d:getetag/>"#); self.xml_payload.push_str(r#"<d:getetag/>"#);
self self
} }
@ -72,24 +110,44 @@ impl ReqProps {
self.api_builder.send().await self.api_builder.send().await
} }
pub async fn send_with_err(&mut self) -> Result<Vec<String>, ApiError> { pub async fn send_with_err(&mut self) -> Result<String, ApiError> {
let res = self.send().await.map_err(ApiError::RequestError)?; let res = self.send().await.map_err(ApiError::RequestError)?;
if res.status().is_success() { if res.status().is_success() {
let body = res.text().await.map_err(ApiError::EmptyError)?; let body = res.text().await.map_err(ApiError::EmptyError)?;
Ok(self.parse(body)) Ok(body)
} else { } else {
Err(ApiError::IncorrectRequest(res)) Err(ApiError::IncorrectRequest(res))
} }
} }
pub fn parse(&self, xml: String) -> Vec<String> { pub async fn send_req_multiple(&mut self) -> Result<Vec<ObjProps>, 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<ObjProps, ApiError> {
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<ObjProps> {
let cursor = Cursor::new(xml); let cursor = Cursor::new(xml);
let parser = EventReader::new(cursor); let parser = EventReader::new(cursor);
let mut should_get = false; let mut should_get = false;
let mut values: Vec<String> = vec![]; let mut values: Vec<ObjProps> = vec![];
let mut iter = self.xml_list.iter();
let mut iter = self.xml_balises.iter();
let mut val = iter.next(); let mut val = iter.next();
let mut content = ObjProps::new();
for event in parser { for event in parser {
match event { match event {
@ -97,12 +155,30 @@ impl ReqProps {
if let Some(v) = val.clone() { if let Some(v) = val.clone() {
should_get = &name.local_name == v; should_get = &name.local_name == v;
} else { } 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)) => { Ok(XmlEvent::Characters(text)) => {
if !text.trim().is_empty() && should_get { 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() val = iter.next()
} }
} }