clone all files and their content

This commit is contained in:
grimhilt 2023-06-05 15:54:40 +02:00
parent a45c953397
commit 1042a7ea22
4 changed files with 101 additions and 10 deletions

View File

@ -1,9 +1,14 @@
use clap::Values; use clap::Values;
use std::io::Bytes;
use std::fs::OpenOptions;
use std::env;
use std::io::prelude::*;
use std::io::Cursor; use std::io::Cursor;
use xml::reader::{EventReader, XmlEvent}; use xml::reader::{EventReader, XmlEvent};
use std::fs::{self, DirBuilder}; use std::fs::{File, DirBuilder};
use std::path::Path; use std::path::Path;
use crate::services::list_folders::ListFolders; use crate::services::list_folders::ListFolders;
use crate::services::download_files::DownloadFiles;
use regex::Regex; use regex::Regex;
pub fn clone(remote: Values<'_>) { pub fn clone(remote: Values<'_>) {
@ -19,13 +24,23 @@ pub fn clone(remote: Values<'_>) {
}, },
}; };
let url_without_domain = domain_regex.replace(url, "/").to_string(); let url_without_domain = domain_regex.replace(url, "/").to_string();
let mut it = path.iter();
it.next();
it.next();
it.next();
it.next();
it.next();
let username = it.next().unwrap();
let mut folders = vec![url_without_domain]; let mut folders = vec![url_without_domain];
let mut url_request; let mut url_request;
let mut files: Vec<String> = vec![];
let mut first_iter = true;
while folders.len() > 0 { while folders.len() > 0 {
let folder = folders.pop().unwrap();
url_request = String::from(domain.clone()); url_request = String::from(domain.clone());
url_request.push_str(folders.last().unwrap().as_str()); url_request.push_str(folder.as_str());
let mut body = Default::default(); let mut body = Default::default();
tokio::runtime::Runtime::new().unwrap().block_on(async { tokio::runtime::Runtime::new().unwrap().block_on(async {
match call(url_request.as_str()).await { match call(url_request.as_str()).await {
@ -41,30 +56,84 @@ pub fn clone(remote: Values<'_>) {
} }
} }
}); });
folders.pop(); if first_iter {
if (folders.len() == 0) { first_iter = false;
if DirBuilder::new().create(path.parent()).is_err() { dbg!(path.file_name());
if DirBuilder::new().create(path.file_name().unwrap()).is_err() {
// todo add second parameter to save in a folder // todo add second parameter to save in a folder
eprintln!("fatal: directory already exist"); eprintln!("fatal: directory already exist");
// destination path 'path' already exists and is not an empty directory. // destination path 'path' already exists and is not an empty directory.
std::process::exit(1); //std::process::exit(1);
} }
} else {
let mut path = Path::new(&folder).strip_prefix("/remote.php/dav/files/");
path = path.unwrap().strip_prefix(username);
DirBuilder::new().recursive(true).create(path.unwrap());
} }
let objects = get_objects_xml(body); let objects = get_objects_xml(body);
let mut iter = objects.iter(); let mut iter = objects.iter();
iter.next(); // jump first element which the folder fetched iter.next(); // jump first element which the folder fetched
for object in iter { for object in iter {
dbg!(object);
if object.chars().last().unwrap() == '/' { if object.chars().last().unwrap() == '/' {
folders.push(object.to_string()); folders.push(object.to_string());
dbg!("folder"); } else {
files.push(object.to_string());
} }
} }
} }
// tokio::runtime::Runtime::new().unwrap().block_on(async {
download_files(domain, username.to_str().unwrap(), files);
// });
}
fn download_files(domain: &str, username: &str, files: Vec<String>) -> std::io::Result<()> {
dbg!("in");
let mut body: Vec<u8> = vec![];
for file in files {
let mut url_request = String::from(domain.clone());
url_request.push_str(file.as_str());
tokio::runtime::Runtime::new().unwrap().block_on(async {
match callDownload(url_request.as_str()).await {
Ok(b) => {
let mut path = Path::new(&file).strip_prefix("/remote.php/dav/files/");
path = path.unwrap().strip_prefix(username);
let pathCur = env::current_dir().unwrap();
let mut f = OpenOptions::new()
.write(true)
.create(true)
.open(pathCur.join(path.unwrap())).unwrap();
f.write_all(&b);
},
Err(MyError::IncorrectRequest(err)) => {
eprintln!("fatal: {}", err.status());
std::process::exit(1);
},
Err(MyError::EmptyError(_)) => eprintln!("Failed to get body"),
Err(MyError::RequestError(err)) => {
eprintln!("fatal: {}", err);
std::process::exit(1);
}
}
});
//f.write_all(body.clone())?;
dbg!(file);
}
Ok(())
}
async fn callDownload(url: &str) -> Result<Vec<u8>, MyError> {
let res = DownloadFiles::new(url).send().await.map_err(MyError::RequestError)?;
if res.status().is_success() {
let body = res.bytes().await.map_err(MyError::EmptyError)?;
Ok(body.to_vec())
} else {
Err(MyError::IncorrectRequest(res))
}
} }
fn get_objects_xml(xml: String) -> Vec<String> { fn get_objects_xml(xml: String) -> Vec<String> {

View File

@ -1,2 +1,3 @@
pub mod api; pub mod api;
pub mod list_folders; pub mod list_folders;
pub mod download_files;

2
src/services/auth.rs Normal file
View File

@ -0,0 +1,2 @@

View File

@ -0,0 +1,19 @@
use crate::services::api::ApiBuilder;
use reqwest::{Method, IntoUrl, Response, Error};
pub struct DownloadFiles {
api_builder: ApiBuilder,
}
impl DownloadFiles {
pub fn new<U: IntoUrl>(url: U) -> Self {
DownloadFiles {
api_builder: ApiBuilder::new()
.set_request(Method::GET, url),
}
}
pub async fn send(&mut self) -> Result<Response, Error> {
self.api_builder.send().await
}
}