enumerate all objects on server when cloning
This commit is contained in:
parent
f398347856
commit
a45c953397
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -2,6 +2,15 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -514,9 +523,11 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rust-crypto",
|
"rust-crypto",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"xml-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -709,6 +720,23 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.18"
|
version = "0.11.18"
|
||||||
@ -1378,3 +1406,9 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xml-rs"
|
||||||
|
version = "0.8.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c"
|
||||||
|
|||||||
@ -12,3 +12,5 @@ dotenv ="0.15.0"
|
|||||||
clap = "2.33"
|
clap = "2.33"
|
||||||
rust-crypto = "0.2.36"
|
rust-crypto = "0.2.36"
|
||||||
colored = "2.0.0"
|
colored = "2.0.0"
|
||||||
|
xml-rs = "0.8.0"
|
||||||
|
regex = "1.8.3"
|
||||||
|
|||||||
@ -1,28 +1,115 @@
|
|||||||
use clap::Values;
|
use clap::Values;
|
||||||
|
use std::io::Cursor;
|
||||||
|
use xml::reader::{EventReader, XmlEvent};
|
||||||
use std::fs::{self, DirBuilder};
|
use std::fs::{self, DirBuilder};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::services::list_folders::ListFolders;
|
use crate::services::list_folders::ListFolders;
|
||||||
use std::error::Error;
|
use regex::Regex;
|
||||||
|
|
||||||
pub fn clone(remote: Values<'_>) {
|
pub fn clone(remote: Values<'_>) {
|
||||||
let url = remote.clone().next().unwrap();
|
let url = remote.clone().next().unwrap();
|
||||||
let path = Path::new(url);
|
let mut path = Path::new(url);
|
||||||
|
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
|
||||||
call(url).await
|
|
||||||
});
|
|
||||||
//DirBuilder::new()
|
|
||||||
// .create(path.parent());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn call(url: &str) -> Result<String, Box<dyn Error>> {
|
let domain_regex = Regex::new(r"(https?:\/\/.+?)\/").unwrap();
|
||||||
let response = ListFolders::new(url).send().await?;
|
let domain = match domain_regex.captures_iter(url).last() {
|
||||||
if response.status().is_success() {
|
Some(capture) => capture.get(1).expect("Domain not found").as_str(),
|
||||||
let body = response.text().await?;
|
None => {
|
||||||
println!("Response body: {}", body);
|
eprintln!("fatal: no domain found");
|
||||||
} else {
|
std::process::exit(1);
|
||||||
println!("Request failed with status code: {}", response.status());
|
},
|
||||||
|
};
|
||||||
|
let url_without_domain = domain_regex.replace(url, "/").to_string();
|
||||||
|
|
||||||
|
let mut folders = vec![url_without_domain];
|
||||||
|
let mut url_request;
|
||||||
|
while folders.len() > 0 {
|
||||||
|
|
||||||
|
url_request = String::from(domain.clone());
|
||||||
|
url_request.push_str(folders.last().unwrap().as_str());
|
||||||
|
let mut body = Default::default();
|
||||||
|
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||||
|
match call(url_request.as_str()).await {
|
||||||
|
Ok(b) => body = b.clone(),
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
folders.pop();
|
||||||
|
if (folders.len() == 0) {
|
||||||
|
if DirBuilder::new().create(path.parent()).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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_objects_xml(xml: String) -> Vec<String> {
|
||||||
|
let cursor = Cursor::new(xml);
|
||||||
|
let parser = EventReader::new(cursor);
|
||||||
|
|
||||||
|
let mut should_get = false;
|
||||||
|
let mut objects: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for event in parser {
|
||||||
|
match event {
|
||||||
|
Ok(XmlEvent::StartElement { name, .. }) => {
|
||||||
|
should_get = name.local_name == "href";
|
||||||
|
}
|
||||||
|
Ok(XmlEvent::Characters(text)) => {
|
||||||
|
if !text.trim().is_empty() && should_get {
|
||||||
|
objects.push(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(XmlEvent::EndElement { .. }) => {
|
||||||
|
should_get = false;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
objects
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MyError {
|
||||||
|
IncorrectRequest(reqwest::Response),
|
||||||
|
EmptyError(reqwest::Error),
|
||||||
|
RequestError(reqwest::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn call(url: &str) -> Result<String, MyError> {
|
||||||
|
let res = ListFolders::new(url).send().await.map_err(MyError::RequestError)?;
|
||||||
|
if res.status().is_success() {
|
||||||
|
let body = res.text().await.map_err(MyError::EmptyError)?;
|
||||||
|
Ok(body)
|
||||||
|
} else {
|
||||||
|
Err(MyError::IncorrectRequest(res))
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,6 @@ impl ListFolders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
pub async fn send(&mut self) -> Result<Response, Error> {
|
||||||
Ok(self.api_builder.send().await?)
|
self.api_builder.send().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user