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 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<ObjProps> = vec![ObjProps::new()];
let mut files: Vec<ObjProps> = 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<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) {
let mut username = None;
let mut domain = "";

View File

@ -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 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(r#"</d:prop></d:propfind>"#);

View File

@ -3,3 +3,4 @@ pub mod read;
pub mod nextsyncignore;
pub mod api;
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)
}