From 1042a7ea2233d42303f7665cec7c884fe37589e6 Mon Sep 17 00:00:00 2001 From: grimhilt Date: Mon, 5 Jun 2023 15:54:40 +0200 Subject: [PATCH] clone all files and their content --- src/commands/clone.rs | 89 ++++++++++++++++++++++++++++++---- src/services.rs | 1 + src/services/auth.rs | 2 + src/services/download_files.rs | 19 ++++++++ 4 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 src/services/auth.rs create mode 100644 src/services/download_files.rs diff --git a/src/commands/clone.rs b/src/commands/clone.rs index 1255d5b..d119b6c 100644 --- a/src/commands/clone.rs +++ b/src/commands/clone.rs @@ -1,9 +1,14 @@ use clap::Values; +use std::io::Bytes; +use std::fs::OpenOptions; +use std::env; +use std::io::prelude::*; use std::io::Cursor; use xml::reader::{EventReader, XmlEvent}; -use std::fs::{self, DirBuilder}; +use std::fs::{File, DirBuilder}; use std::path::Path; use crate::services::list_folders::ListFolders; +use crate::services::download_files::DownloadFiles; use regex::Regex; 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 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 url_request; + let mut files: Vec = vec![]; + let mut first_iter = true; while folders.len() > 0 { + let folder = folders.pop().unwrap(); 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(); tokio::runtime::Runtime::new().unwrap().block_on(async { match call(url_request.as_str()).await { @@ -41,30 +56,84 @@ pub fn clone(remote: Values<'_>) { } } }); - folders.pop(); - if (folders.len() == 0) { - if DirBuilder::new().create(path.parent()).is_err() { + if first_iter { + first_iter = false; + dbg!(path.file_name()); + if DirBuilder::new().create(path.file_name().unwrap()).is_err() { // todo add second parameter to save in a folder eprintln!("fatal: directory already exist"); // 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 mut iter = objects.iter(); iter.next(); // jump first element which the folder fetched for object in iter { - dbg!(object); if object.chars().last().unwrap() == '/' { 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) -> std::io::Result<()> { + dbg!("in"); + let mut body: Vec = 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, 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 { diff --git a/src/services.rs b/src/services.rs index 73824d5..4c4d98a 100644 --- a/src/services.rs +++ b/src/services.rs @@ -1,2 +1,3 @@ pub mod api; pub mod list_folders; +pub mod download_files; diff --git a/src/services/auth.rs b/src/services/auth.rs new file mode 100644 index 0000000..139597f --- /dev/null +++ b/src/services/auth.rs @@ -0,0 +1,2 @@ + + diff --git a/src/services/download_files.rs b/src/services/download_files.rs new file mode 100644 index 0000000..3c92ef8 --- /dev/null +++ b/src/services/download_files.rs @@ -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(url: U) -> Self { + DownloadFiles { + api_builder: ApiBuilder::new() + .set_request(Method::GET, url), + } + } + + pub async fn send(&mut self) -> Result { + self.api_builder.send().await + } +}