cleaning clone
This commit is contained in:
parent
b16058b4d3
commit
7cfd572ad0
21
docs/conventions/variables.md
Normal file
21
docs/conventions/variables.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Conventions
|
||||||
|
|
||||||
|
## Path Variables
|
||||||
|
|
||||||
|
Considering cloning:
|
||||||
|
* ``https://nextcloud.example.com/remote.php/dav/files/grimhilt/dir/dir_to_clone``
|
||||||
|
|
||||||
|
We have (in ``ApiProps`` for example):
|
||||||
|
* ``host``: ``https://nextcloud.example.com``
|
||||||
|
* ``username``: ``grimhilt``
|
||||||
|
* ``root``: ``/dir/dir_to_clone``
|
||||||
|
|
||||||
|
Concerning paths we have:
|
||||||
|
* ``remote_p``: ``/remote.php/dav/files/grimhilt/dir/dir_to_clone/D1/D1_F1.md``
|
||||||
|
* ``ref_p``: ``/home/grimhilt/dir_cloned``
|
||||||
|
* ``relative_p``: ``D1/D1_F1.md``
|
||||||
|
* ``abs_p``: ``/home/grimhilt/dir_cloned/D1_D1_F1.md``
|
||||||
|
|
||||||
|
Use prefix:
|
||||||
|
* ``p`` for Path or PathBuffer
|
||||||
|
* ``ps`` for String
|
@ -7,14 +7,14 @@ use crate::services::list_folders::ListFolders;
|
|||||||
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;
|
||||||
use crate::utils::api::{get_local_path, get_local_path_t};
|
use crate::utils::api::{get_local_path_t, ApiProps};
|
||||||
use crate::global::global::{DIR_PATH, set_dir_path};
|
use crate::global::global::{DIR_PATH, set_dir_path};
|
||||||
|
|
||||||
pub fn clone(remote: Values<'_>) {
|
pub fn clone(remote: Values<'_>) {
|
||||||
let d = DIR_PATH.lock().unwrap().clone();
|
let d = DIR_PATH.lock().unwrap().clone();
|
||||||
|
|
||||||
let url = remote.clone().next().unwrap();
|
let url = remote.clone().next().unwrap();
|
||||||
let (domain, tmp_user, dist_path_str) = get_url_props(url);
|
let (host, tmp_user, dist_path_str) = get_url_props(url);
|
||||||
let username = match tmp_user {
|
let username = match tmp_user {
|
||||||
Some(u) => u,
|
Some(u) => u,
|
||||||
None => {
|
None => {
|
||||||
@ -22,6 +22,12 @@ pub fn clone(remote: Values<'_>) {
|
|||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let api_props = ApiProps {
|
||||||
|
host: host.clone(),
|
||||||
|
username: username.to_string(),
|
||||||
|
root: dist_path_str.to_string(),
|
||||||
|
};
|
||||||
|
dbg!(dist_path_str.clone());
|
||||||
|
|
||||||
let ref_path = match d.clone() {
|
let ref_path = match d.clone() {
|
||||||
Some(dir) => Path::new(&dir).to_owned(),
|
Some(dir) => Path::new(&dir).to_owned(),
|
||||||
@ -34,23 +40,18 @@ pub fn clone(remote: Values<'_>) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut folders = vec![String::from(dist_path_str)];
|
let mut folders = vec![String::from("")];
|
||||||
let mut url_request;
|
|
||||||
let mut files: Vec<String> = vec![];
|
let mut files: Vec<String> = vec![];
|
||||||
let mut first_iter = true;
|
let mut first_iter = true;
|
||||||
while folders.len() > 0 {
|
while folders.len() > 0 {
|
||||||
let folder = folders.pop().unwrap();
|
let folder = folders.pop().unwrap();
|
||||||
url_request = String::from(domain.clone());
|
|
||||||
if first_iter {
|
|
||||||
url_request.push_str("/remote.php/dav/files/");
|
|
||||||
url_request.push_str(username);
|
|
||||||
}
|
|
||||||
url_request.push_str(folder.as_str());
|
|
||||||
|
|
||||||
// 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(url_request.as_str())
|
dbg!(folder.clone());
|
||||||
|
let res = ListFolders::new()
|
||||||
|
.set_request(folder.as_str(), &api_props)
|
||||||
.gethref()
|
.gethref()
|
||||||
.send_with_res()
|
.send_with_res()
|
||||||
.await;
|
.await;
|
||||||
@ -83,13 +84,13 @@ pub fn clone(remote: Values<'_>) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// create folder
|
// create folder
|
||||||
let local_folder = get_local_path(folder, ref_path.clone(), username, dist_path_str);
|
let p = ref_path.clone().join(Path::new(&folder.clone()));
|
||||||
if let Err(err) = DirBuilder::new().recursive(true).create(local_folder.clone()) {
|
if let Err(err) = DirBuilder::new().recursive(true).create(p.clone()) {
|
||||||
eprintln!("error: cannot create directory {}: {}", local_folder.display(), err);
|
eprintln!("error: cannot create directory {}: {}", p.display(), err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add tree
|
// add tree
|
||||||
let path_folder = local_folder.strip_prefix(ref_path.clone()).unwrap();
|
let path_folder = p.strip_prefix(ref_path.clone()).unwrap();
|
||||||
if object::add_tree(&path_folder).is_err() {
|
if object::add_tree(&path_folder).is_err() {
|
||||||
eprintln!("error: cannot store object {}", path_folder.display());
|
eprintln!("error: cannot store object {}", path_folder.display());
|
||||||
}
|
}
|
||||||
@ -99,37 +100,35 @@ pub fn clone(remote: Values<'_>) {
|
|||||||
let mut iter = objs.iter();
|
let mut iter = objs.iter();
|
||||||
iter.next(); // jump first element which is the folder cloned
|
iter.next(); // jump first element which is the folder cloned
|
||||||
for object in iter {
|
for object in iter {
|
||||||
|
dbg!(object.clone());
|
||||||
if object.href.clone().unwrap().chars().last().unwrap() == '/' {
|
if object.href.clone().unwrap().chars().last().unwrap() == '/' {
|
||||||
folders.push(object.href.clone().unwrap().to_string());
|
folders.push(object.relative_s.clone().unwrap().to_string());
|
||||||
} else {
|
} else {
|
||||||
files.push(object.href.clone().unwrap().to_string());
|
files.push(object.relative_s.clone().unwrap().to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
first_iter = false;
|
first_iter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
download_files(ref_path.clone(), files);
|
download_files(ref_path.clone(), files, &api_props);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn download_files(local_p: PathBuf, files: Vec<String>) {
|
fn download_files(ref_p: PathBuf, files: Vec<String>, api_props: &ApiProps) {
|
||||||
for remote_file in files {
|
for relative_file in files {
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
let res = DownloadFiles::new()
|
let res = DownloadFiles::new()
|
||||||
.set_url_with_remote(remote_file.as_str())
|
.set_url(relative_file.as_str(), api_props)
|
||||||
.save(local_p.clone()).await;
|
.save(ref_p.clone()).await;
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
let relative_p = Path::new(&relative_file);
|
||||||
let s = &get_local_path_t(&remote_file.clone());
|
|
||||||
let ss = s.strip_prefix("/").unwrap();
|
|
||||||
let relative_p = Path::new(ss);
|
|
||||||
if let Err(_) = object::add_blob(relative_p, "tmpdate") {
|
if let Err(_) = object::add_blob(relative_p, "tmpdate") {
|
||||||
eprintln!("error saving reference of {}", remote_file.clone());
|
eprintln!("error saving reference of {}", relative_file.clone());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(ApiError::Unexpected(_)) => {
|
Err(ApiError::Unexpected(_)) => {
|
||||||
eprintln!("error writing {}", remote_file);
|
eprintln!("error writing {}", relative_file);
|
||||||
},
|
},
|
||||||
Err(ApiError::IncorrectRequest(err)) => {
|
Err(ApiError::IncorrectRequest(err)) => {
|
||||||
eprintln!("fatal: {}", err.status());
|
eprintln!("fatal: {}", err.status());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use reqwest::RequestBuilder;
|
use reqwest::RequestBuilder;
|
||||||
use reqwest::{Response, Error, IntoUrl, Method};
|
use reqwest::{Response, Error, IntoUrl, Method};
|
||||||
|
use crate::utils::api::ApiProps;
|
||||||
use std::env;
|
use std::env;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ impl ApiBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_request<U: IntoUrl>(mut self, method: Method, url: U) -> ApiBuilder {
|
pub fn set_request<U: IntoUrl>(&mut self, method: Method, url: U) -> &mut ApiBuilder {
|
||||||
self.request = Some(self.client.request(method, url));
|
self.request = Some(self.client.request(method, url));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -48,13 +49,14 @@ impl ApiBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_request_remote(&mut self, meth: Method, path: &str) -> &mut ApiBuilder {
|
pub fn set_req(&mut self, meth: Method, p: &str, api_props: &ApiProps) -> &mut ApiBuilder {
|
||||||
dotenv().ok();
|
let mut url = String::from(&api_props.host);
|
||||||
let host = env::var("HOST").unwrap();
|
url.push_str("/remote.php/dav/files/");
|
||||||
let mut url = String::from(host);
|
|
||||||
url.push_str("/");
|
url.push_str("/");
|
||||||
url.push_str(path);
|
url.push_str(&api_props.username);
|
||||||
dbg!(url.clone());
|
url.push_str(&api_props.root);
|
||||||
|
url.push_str("/");
|
||||||
|
url.push_str(p);
|
||||||
self.request = Some(self.client.request(meth, url));
|
self.request = Some(self.client.request(meth, url));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use reqwest::{Method, Response, Error};
|
use reqwest::{Method, Response, Error};
|
||||||
use crate::utils::api::get_local_path_t;
|
use crate::utils::api::{get_local_path_t, ApiProps};
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
pub struct DownloadFiles {
|
pub struct DownloadFiles {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
path: String,
|
relative_ps: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DownloadFiles {
|
impl DownloadFiles {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
DownloadFiles {
|
DownloadFiles {
|
||||||
api_builder: ApiBuilder::new(),
|
api_builder: ApiBuilder::new(),
|
||||||
path: String::from(""),
|
relative_ps: String::from(""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_url_with_remote(&mut self, url: &str) -> &mut DownloadFiles {
|
pub fn set_url(&mut self, relative_ps: &str, api_props: &ApiProps) -> &mut DownloadFiles {
|
||||||
self.path = get_local_path_t(url.clone()).strip_prefix("/").unwrap().to_string();
|
self.relative_ps = relative_ps.to_string();
|
||||||
self.api_builder.build_request_remote(Method::GET, url);
|
self.api_builder.set_req(Method::from_bytes(b"PROPFIND").unwrap(), relative_ps, api_props);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ impl DownloadFiles {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save(&mut self, local_path: PathBuf) -> Result<(), ApiError> {
|
pub async fn save(&mut self, ref_p: PathBuf) -> Result<(), ApiError> {
|
||||||
let p = local_path.join(PathBuf::from(self.path.clone()));
|
let p = ref_p.join(PathBuf::from(self.relative_ps.clone()));
|
||||||
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.bytes().await.map_err(ApiError::EmptyError)?;
|
let body = res.bytes().await.map_err(ApiError::EmptyError)?;
|
||||||
@ -53,6 +53,7 @@ impl DownloadFiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_file(path: PathBuf, content: &Vec<u8>) -> io::Result<()> {
|
fn write_file(path: PathBuf, content: &Vec<u8>) -> io::Result<()> {
|
||||||
|
dbg!(path.clone());
|
||||||
let mut f = OpenOptions::new()
|
let mut f = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
use crate::services::api::{ApiBuilder, ApiError};
|
use crate::services::api::{ApiBuilder, ApiError};
|
||||||
|
use crate::utils::api::{ApiProps, get_relative_s};
|
||||||
use xml::reader::{EventReader, XmlEvent};
|
use xml::reader::{EventReader, XmlEvent};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use reqwest::{Method, IntoUrl, Response, Error};
|
use reqwest::{Method, Response, Error};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct FolderContent {
|
pub struct FolderContent {
|
||||||
pub href: Option<String>,
|
pub href: Option<String>,
|
||||||
|
pub relative_s: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for FolderContent {
|
impl Clone for FolderContent {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
FolderContent {
|
FolderContent {
|
||||||
href: self.href.clone(),
|
href: self.href.clone(),
|
||||||
|
relative_s: self.relative_s.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,6 +23,7 @@ impl FolderContent {
|
|||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
FolderContent {
|
FolderContent {
|
||||||
href: None,
|
href: None,
|
||||||
|
relative_s: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,17 +31,29 @@ impl FolderContent {
|
|||||||
pub struct ListFolders {
|
pub struct ListFolders {
|
||||||
api_builder: ApiBuilder,
|
api_builder: ApiBuilder,
|
||||||
xml_balises: Vec<String>,
|
xml_balises: Vec<String>,
|
||||||
|
api_props: Option<ApiProps>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListFolders {
|
impl ListFolders {
|
||||||
pub fn new<U: IntoUrl>(url: U) -> Self {
|
pub fn new() -> Self {
|
||||||
ListFolders {
|
ListFolders {
|
||||||
api_builder: ApiBuilder::new()
|
api_builder: ApiBuilder::new(),
|
||||||
.set_request(Method::from_bytes(b"PROPFIND").unwrap(), url),
|
|
||||||
xml_balises: vec![],
|
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 {
|
pub fn gethref(&mut self) -> &mut ListFolders {
|
||||||
self.xml_balises.push(String::from("href"));
|
self.xml_balises.push(String::from("href"));
|
||||||
self
|
self
|
||||||
@ -93,7 +110,11 @@ impl ListFolders {
|
|||||||
Ok(XmlEvent::Characters(text)) => {
|
Ok(XmlEvent::Characters(text)) => {
|
||||||
if !text.trim().is_empty() && should_get {
|
if !text.trim().is_empty() && should_get {
|
||||||
match val.unwrap().as_str() {
|
match val.unwrap().as_str() {
|
||||||
"href" => content.href = Some(text),
|
"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()
|
val = iter.next()
|
||||||
|
@ -1,6 +1,32 @@
|
|||||||
use std::path::{PathBuf, Path};
|
use std::path::{PathBuf, Path};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ApiProps {
|
||||||
|
pub host: String, // nextcloud.example.com
|
||||||
|
pub username: String,
|
||||||
|
pub root: String, // /dir/cloned
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for ApiProps {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
ApiProps {
|
||||||
|
host: self.host.to_string(),
|
||||||
|
username: self.username.to_string(),
|
||||||
|
root: self.root.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_relative_s(p: String, api_props: &ApiProps) -> String {
|
||||||
|
let mut final_p = p.clone();
|
||||||
|
final_p = final_p.strip_prefix("/remote.php/dav/files/").unwrap().to_string();
|
||||||
|
final_p = final_p.strip_prefix(&api_props.username).unwrap().to_string();
|
||||||
|
final_p = final_p.strip_prefix(&api_props.root).unwrap().to_string();
|
||||||
|
final_p = final_p.strip_prefix("/").unwrap().to_string();
|
||||||
|
final_p
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_local_path(p: String, local_p: PathBuf, username: &str, dist_p: &str) -> PathBuf {
|
pub fn get_local_path(p: String, local_p: PathBuf, username: &str, dist_p: &str) -> PathBuf {
|
||||||
let mut final_p = Path::new(p.as_str());
|
let mut final_p = Path::new(p.as_str());
|
||||||
final_p = final_p.strip_prefix("/remote.php/dav/files/").unwrap();
|
final_p = final_p.strip_prefix("/remote.php/dav/files/").unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user