enumerate_remote function & applied to clone

This commit is contained in:
grimhilt 2023-07-21 14:45:45 +02:00
parent 30004ebd8b
commit 0832100d83
4 changed files with 97 additions and 73 deletions

View File

@ -6,6 +6,7 @@ use clap::Values;
use regex::Regex; use regex::Regex;
use crate::services::downloader::Downloader; use crate::services::downloader::Downloader;
use crate::utils::api::ApiProps; use crate::utils::api::ApiProps;
use crate::utils::remote::enumerate_remote;
use crate::global::global::{DIR_PATH, set_dir_path}; use crate::global::global::{DIR_PATH, set_dir_path};
use crate::services::api::ApiError; use crate::services::api::ApiError;
use crate::services::req_props::{ReqProps, ObjProps}; use crate::services::req_props::{ReqProps, ObjProps};
@ -43,45 +44,7 @@ pub fn clone(remote: Values<'_>) {
}, },
}; };
let mut folders: Vec<ObjProps> = vec![ObjProps::new()]; // try to create root folder
let mut files: Vec<ObjProps> = vec![];
let mut first_iter = true;
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 = 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() { if DirBuilder::new().recursive(true).create(ref_path.clone()).is_err() {
eprintln!("fatal: unable to create the destination directory"); eprintln!("fatal: unable to create the destination directory");
std::process::exit(1); std::process::exit(1);
@ -95,9 +58,12 @@ pub fn clone(remote: Values<'_>) {
eprintln!("err: not able to save remote"); eprintln!("err: not able to save remote");
} }
} }
} else {
let (folders, files) = enumerate_remote(|a| req(&api_props, a));
for folder in folders {
// create folder // create folder
let p = ref_path.clone().join(Path::new(&relative_s)); let p = ref_path.clone().join(Path::new(&folder.relative_s.unwrap()));
if let Err(err) = DirBuilder::new().recursive(true).create(p.clone()) { if let Err(err) = DirBuilder::new().recursive(true).create(p.clone()) {
eprintln!("err: cannot create directory {} ({})", p.display(), err); eprintln!("err: cannot create directory {} ({})", p.display(), err);
} }
@ -110,19 +76,6 @@ pub fn clone(remote: Values<'_>) {
} }
} }
// 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());
}
}
first_iter = false;
}
let downloader = Downloader::new() let downloader = Downloader::new()
.set_api_props(api_props.clone()) .set_api_props(api_props.clone())
.set_files(files) .set_files(files)
@ -139,6 +92,15 @@ fn save_blob(obj: ObjProps) {
} }
} }
fn req(api_props: &ApiProps, relative_s: &str) -> Result<Vec<ObjProps>, 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) { pub fn get_url_props(url: &str) -> (String, Option<&str>, &str) {
let mut username = None; let mut username = None;
let mut domain = ""; let mut domain = "";

View File

@ -37,6 +37,15 @@ impl ObjProps {
contentlength: None, 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 { pub struct ReqProps {
@ -81,6 +90,7 @@ impl ReqProps {
} }
pub fn gethref(&mut self) -> &mut 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.xml_balises.push(String::from("href"));
self self
} }
@ -127,6 +137,7 @@ impl ReqProps {
} }
fn validate_xml(&mut self) -> &mut ReqProps { fn validate_xml(&mut self) -> &mut ReqProps {
self.gethref();
let mut xml = String::from(r#"<?xml version="1.0" encoding="UTF-8"?><d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns"><d:prop>"#); let mut xml = String::from(r#"<?xml version="1.0" encoding="UTF-8"?><d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns"><d:prop>"#);
xml.push_str(&self.xml_payload.clone()); xml.push_str(&self.xml_payload.clone());
xml.push_str(r#"</d:prop></d:propfind>"#); xml.push_str(r#"</d:prop></d:propfind>"#);

View File

@ -3,3 +3,4 @@ pub mod read;
pub mod nextsyncignore; pub mod nextsyncignore;
pub mod api; pub mod api;
pub mod time; pub mod time;
pub mod remote;

50
src/utils/remote.rs Normal file
View File

@ -0,0 +1,50 @@
use crate::services::{req_props::ObjProps, api::ApiError};
pub fn enumerate_remote(req: impl Fn(&str) -> Result<Vec<ObjProps>, ApiError>) -> (Vec<ObjProps>, Vec<ObjProps>) {
let mut folders: Vec<ObjProps> = vec![ObjProps::new()];
let mut all_folders: Vec<ObjProps> = vec![];
let mut files: Vec<ObjProps> = 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)
}