Compare commits
6 Commits
9956727cc9
...
b16058b4d3
Author | SHA1 | Date | |
---|---|---|---|
|
b16058b4d3 | ||
|
ea2b0772af | ||
|
b911ad8606 | ||
|
0bf5fb76e0 | ||
|
7a34b3c79b | ||
|
cbbf185b1a |
@ -1,9 +1,9 @@
|
||||
use clap::Values;
|
||||
use crate::utils::{self, nextsyncignore};
|
||||
use crate::utils::{self};
|
||||
use crate::utils::nextsyncignore::{self, ignore_file};
|
||||
use crate::store;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::io::Write;
|
||||
use glob::glob;
|
||||
|
||||
pub struct AddArgs<'a> {
|
||||
pub files: Values<'a>,
|
||||
@ -13,13 +13,21 @@ pub struct AddArgs<'a> {
|
||||
pub fn add(args: AddArgs) {
|
||||
let mut index_file = store::index::open();
|
||||
let mut added_files: Vec<String> = vec![];
|
||||
|
||||
let rules = match nextsyncignore::read_lines() {
|
||||
Ok(r) => r,
|
||||
Err(_) => vec![],
|
||||
};
|
||||
let mut ignored_f = vec![];
|
||||
let file_vec: Vec<&str> = args.files.collect();
|
||||
for file in file_vec {
|
||||
if !args.force && ignore_file(&file.to_string(), rules.clone(), &mut ignored_f) {
|
||||
continue;
|
||||
}
|
||||
let path = Path::new(file);
|
||||
match path.exists() {
|
||||
true => {
|
||||
if path.is_dir() {
|
||||
|
||||
added_files.push(String::from(path.to_str().unwrap()));
|
||||
add_folder_content(path.to_path_buf(), &mut added_files);
|
||||
} else {
|
||||
@ -33,19 +41,16 @@ pub fn add(args: AddArgs) {
|
||||
}
|
||||
}
|
||||
|
||||
// check ignored file if not forced
|
||||
if !args.force {
|
||||
let (ignored, ignored_files) = nextsyncignore::ignore_files(&mut added_files);
|
||||
if ignored {
|
||||
if ignored_f.len() > 0 {
|
||||
// todo multiple nextsyncignore
|
||||
println!("The following paths are ignored by your .nextsyncignore file:");
|
||||
for file in ignored_files {
|
||||
for file in ignored_f {
|
||||
println!("{}", file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save all added_files in index
|
||||
// todo avoid duplication
|
||||
for file in added_files {
|
||||
match writeln!(index_file, "{}", file) {
|
||||
Ok(()) => (),
|
||||
|
@ -1,16 +1,13 @@
|
||||
use std::fs::OpenOptions;
|
||||
use std::fs::DirBuilder;
|
||||
use std::io::prelude::*;
|
||||
use std::io::{self, Cursor};
|
||||
use std::path::{Path, PathBuf};
|
||||
use clap::Values;
|
||||
use regex::Regex;
|
||||
use xml::reader::{EventReader, XmlEvent};
|
||||
use crate::services::api::ApiError;
|
||||
use crate::services::list_folders::ListFolders;
|
||||
use crate::services::download_files::DownloadFiles;
|
||||
use crate::store::object;
|
||||
use crate::commands;
|
||||
use crate::utils::api::{get_local_path, get_local_path_t};
|
||||
use crate::global::global::{DIR_PATH, set_dir_path};
|
||||
|
||||
pub fn clone(remote: Values<'_>) {
|
||||
@ -23,11 +20,10 @@ pub fn clone(remote: Values<'_>) {
|
||||
None => {
|
||||
eprintln!("No username found");
|
||||
todo!();
|
||||
""
|
||||
}
|
||||
};
|
||||
|
||||
let local_path = match d.clone() {
|
||||
let ref_path = match d.clone() {
|
||||
Some(dir) => Path::new(&dir).to_owned(),
|
||||
None => {
|
||||
let iter = Path::new(dist_path_str).iter();
|
||||
@ -52,16 +48,33 @@ pub fn clone(remote: Values<'_>) {
|
||||
url_request.push_str(folder.as_str());
|
||||
|
||||
// request folder content
|
||||
let mut body = Default::default();
|
||||
let mut objs = vec![];
|
||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||
body = ListFolders::new(url_request.as_str())
|
||||
let res = ListFolders::new(url_request.as_str())
|
||||
.gethref()
|
||||
.send_with_res()
|
||||
.await;
|
||||
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 folder
|
||||
if first_iter {
|
||||
if DirBuilder::new().create(local_path.clone()).is_err() {
|
||||
if DirBuilder::new().create(ref_path.clone()).is_err() {
|
||||
eprintln!("fatal: directory already exist");
|
||||
// destination path 'path' already exists and is not an empty directory.
|
||||
//std::process::exit(1);
|
||||
@ -70,70 +83,54 @@ pub fn clone(remote: Values<'_>) {
|
||||
}
|
||||
} else {
|
||||
// create folder
|
||||
let local_folder = get_local_path(folder, local_path.clone(), username, dist_path_str);
|
||||
let local_folder = get_local_path(folder, ref_path.clone(), username, dist_path_str);
|
||||
if let Err(err) = DirBuilder::new().recursive(true).create(local_folder.clone()) {
|
||||
eprintln!("error: cannot create directory {}: {}", local_folder.display(), err);
|
||||
}
|
||||
|
||||
// add tree
|
||||
let path_folder = local_folder.strip_prefix(local_path.clone()).unwrap();
|
||||
let path_folder = local_folder.strip_prefix(ref_path.clone()).unwrap();
|
||||
if object::add_tree(&path_folder).is_err() {
|
||||
eprintln!("error: cannot store object {}", path_folder.display());
|
||||
}
|
||||
}
|
||||
|
||||
// find folders and files in response
|
||||
let objects = get_objects_xml(body);
|
||||
let mut iter = objects.iter();
|
||||
iter.next(); // jump first element which the folder fetched
|
||||
let mut iter = objs.iter();
|
||||
iter.next(); // jump first element which is the folder cloned
|
||||
for object in iter {
|
||||
if object.chars().last().unwrap() == '/' {
|
||||
folders.push(object.to_string());
|
||||
if object.href.clone().unwrap().chars().last().unwrap() == '/' {
|
||||
folders.push(object.href.clone().unwrap().to_string());
|
||||
} else {
|
||||
files.push(object.to_string());
|
||||
files.push(object.href.clone().unwrap().to_string());
|
||||
}
|
||||
}
|
||||
first_iter = false;
|
||||
}
|
||||
|
||||
download_files(&domain, local_path.clone(), username, dist_path_str, files);
|
||||
download_files(ref_path.clone(), files);
|
||||
}
|
||||
|
||||
fn get_local_path(p: String, local_p: PathBuf, username: &str, dist_p: &str) -> PathBuf {
|
||||
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(username.clone()).unwrap();
|
||||
let dist_p = Path::new(dist_p).strip_prefix("/");
|
||||
final_p = final_p.strip_prefix(dist_p.unwrap()).unwrap();
|
||||
local_p.clone().join(final_p.clone())
|
||||
}
|
||||
|
||||
fn write_file(path: PathBuf, content: &Vec<u8>, local_p: PathBuf) -> io::Result<()> {
|
||||
let mut f = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path.clone())?;
|
||||
|
||||
f.write_all(&content)?;
|
||||
|
||||
let relative_p = Path::new(&path).strip_prefix(local_p).unwrap();
|
||||
object::add_blob(relative_p, "tmpdate")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn download_files(domain: &str, local_p: PathBuf, username: &str, dist_p: &str, files: Vec<String>) {
|
||||
for file in files {
|
||||
let mut url_request = String::from(domain.clone());
|
||||
url_request.push_str(file.as_str());
|
||||
fn download_files(local_p: PathBuf, files: Vec<String>) {
|
||||
for remote_file in files {
|
||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||
match DownloadFiles::new(url_request.as_str()).send_with_err().await {
|
||||
Ok(b) => {
|
||||
let p_to_save = get_local_path(file.clone(), local_p.clone(), username, dist_p);
|
||||
let res = DownloadFiles::new()
|
||||
.set_url_with_remote(remote_file.as_str())
|
||||
.save(local_p.clone()).await;
|
||||
|
||||
if let Err(_) = write_file(p_to_save, &b, local_p.clone()) {
|
||||
eprintln!("error writing {}", file);
|
||||
match res {
|
||||
Ok(()) => {
|
||||
|
||||
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") {
|
||||
eprintln!("error saving reference of {}", remote_file.clone());
|
||||
}
|
||||
},
|
||||
Err(ApiError::Unexpected(_)) => {
|
||||
eprintln!("error writing {}", remote_file);
|
||||
},
|
||||
Err(ApiError::IncorrectRequest(err)) => {
|
||||
eprintln!("fatal: {}", err.status());
|
||||
std::process::exit(1);
|
||||
@ -148,37 +145,6 @@ fn download_files(domain: &str, local_p: PathBuf, username: &str, dist_p: &str,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// todo allow http
|
||||
fn get_url_props(url: &str) -> (String, Option<&str>, &str) {
|
||||
let mut username = None;
|
||||
let mut domain = "";
|
||||
@ -193,7 +159,7 @@ fn get_url_props(url: &str) -> (String, Option<&str>, &str) {
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
} else if url.find("?").is_some() {
|
||||
} else if url.find("?").is_some() { // from browser url
|
||||
let re = Regex::new(r"((https?://)?.+?)/.+dir=(.+?)&").unwrap();
|
||||
match re.captures_iter(url).last() {
|
||||
Some(cap) => {
|
||||
@ -218,9 +184,13 @@ fn get_url_props(url: &str) -> (String, Option<&str>, &str) {
|
||||
|
||||
}
|
||||
|
||||
let re = Regex::new(r"^http://").unwrap();
|
||||
if !re.is_match(domain) {
|
||||
let re = Regex::new(r"(^https?://)?").unwrap();
|
||||
let secure_domain = re.replace(domain, "https://").to_string();
|
||||
(secure_domain, username, path)
|
||||
return (secure_domain, username, path);
|
||||
}
|
||||
(domain.to_string(), username, path)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -231,21 +201,22 @@ mod tests {
|
||||
fn test_get_url_props() {
|
||||
let p = "/foo/bar";
|
||||
let u = Some("user");
|
||||
let d = String::from("https://nextcloud.com");
|
||||
let ld = String::from("https://nextcloud.example.com");
|
||||
assert_eq!(get_url_props("user@nextcloud.com/remote.php/dav/files/user/foo/bar"), (d.clone(), u, p));
|
||||
assert_eq!(get_url_props("user@nextcloud.com/foo/bar"), (d.clone(), u, p));
|
||||
assert_eq!(get_url_props("user@nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (ld.clone(), u, p));
|
||||
assert_eq!(get_url_props("user@nextcloud.example.com/foo/bar"), (ld.clone(), u, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.example.com/apps/files/?dir=/foo/bar&fileid=166666"), (ld.clone(), None, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.com/apps/files/?dir=/foo/bar&fileid=166666"), (d.clone(), None, p));
|
||||
let d = String::from("http://nextcloud.com");
|
||||
let sd = String::from("https://nextcloud.com");
|
||||
let sld = String::from("https://nextcloud.example.com");
|
||||
let ld = String::from("http://nextcloud.example.com");
|
||||
assert_eq!(get_url_props("user@nextcloud.com/remote.php/dav/files/user/foo/bar"), (sd.clone(), u, p));
|
||||
assert_eq!(get_url_props("user@nextcloud.com/foo/bar"), (sd.clone(), u, p));
|
||||
assert_eq!(get_url_props("user@nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (sld.clone(), u, p));
|
||||
assert_eq!(get_url_props("user@nextcloud.example.com/foo/bar"), (sld.clone(), u, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.example.com/apps/files/?dir=/foo/bar&fileid=166666"), (sld.clone(), None, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.com/apps/files/?dir=/foo/bar&fileid=166666"), (sd.clone(), None, p));
|
||||
assert_eq!(get_url_props("http://nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (ld.clone(), u, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (ld.clone(), u, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (sld.clone(), u, p));
|
||||
assert_eq!(get_url_props("http://nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (ld.clone(), u, p));
|
||||
assert_eq!(get_url_props("nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (ld.clone(), u, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.example.com/foo/bar"), (ld.clone(), None, p));
|
||||
assert_eq!(get_url_props("nextcloud.example.com/remote.php/dav/files/user/foo/bar"), (sld.clone(), u, p));
|
||||
assert_eq!(get_url_props("https://nextcloud.example.com/foo/bar"), (sld.clone(), None, p));
|
||||
assert_eq!(get_url_props("http://nextcloud.example.com/foo/bar"), (ld.clone(), None, p));
|
||||
assert_eq!(get_url_props("nextcloud.example.com/foo/bar"), (ld.clone(), None, p));
|
||||
assert_eq!(get_url_props("nextcloud.example.com/foo/bar"), (sld.clone(), None, p));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,23 +76,14 @@ fn get_staged(objs: &mut Vec<Obj>) -> Vec<Obj> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut to_remove: Vec<usize> = vec![];
|
||||
let mut index = 0;
|
||||
for obj in &mut *objs {
|
||||
dbg!(obj.clone().path.to_str().unwrap());
|
||||
objs.retain(|obj| {
|
||||
if indexes.contains(obj.clone().path.to_str().unwrap()) {
|
||||
staged_objs.push(obj.clone());
|
||||
to_remove.push(index);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
||||
let mut offset = 0;
|
||||
for i in to_remove {
|
||||
objs.remove(i + offset.clone());
|
||||
offset += 1;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
staged_objs
|
||||
}
|
||||
@ -260,35 +251,29 @@ fn print_staged_object(obj: Obj) {
|
||||
|
||||
fn remove_duplicate(hashes: &mut HashMap<String, Obj>, objects: &mut Vec<String>, remove_option: RemoveSide) -> Vec<String> {
|
||||
let mut hasher = Sha1::new();
|
||||
let mut to_remove: Vec<usize> = vec![];
|
||||
let mut i = 0;
|
||||
let mut duplicate = vec![];
|
||||
|
||||
for object in &mut *objects {
|
||||
objects.retain(|obj| {
|
||||
// hash the object
|
||||
hasher.input_str(object);
|
||||
hasher.input_str(obj);
|
||||
let hash = hasher.result_str();
|
||||
hasher.reset();
|
||||
|
||||
// find it on the list of hashes
|
||||
if hashes.contains_key(&hash) {
|
||||
duplicate.push(object.clone());
|
||||
duplicate.push(obj.clone());
|
||||
|
||||
// remove from hashes
|
||||
if remove_option == RemoveSide::Left || remove_option == RemoveSide::Both {
|
||||
hashes.remove(&hash);
|
||||
}
|
||||
if remove_option == RemoveSide::Right || remove_option == RemoveSide::Both {
|
||||
to_remove.push(i);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// remove all objects existing in the list of hashes
|
||||
i = 0;
|
||||
for index in to_remove {
|
||||
objects.remove(index-i);
|
||||
i += 1;
|
||||
// remove from objects
|
||||
remove_option != RemoveSide::Right && remove_option != RemoveSide::Both
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
duplicate
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ fn main() {
|
||||
if let Some(remote) = matches.values_of("remote") {
|
||||
commands::clone::clone(remote);
|
||||
}
|
||||
} else if let Some(matches) = matches.subcommand_matches("push") {
|
||||
} else if let Some(_matches) = matches.subcommand_matches("push") {
|
||||
commands::push::push();
|
||||
} else if let Some(matches) = matches.subcommand_matches("config") {
|
||||
if let Some(mut var) = matches.values_of("variable") {
|
||||
|
@ -9,6 +9,7 @@ pub enum ApiError {
|
||||
IncorrectRequest(reqwest::Response),
|
||||
EmptyError(reqwest::Error),
|
||||
RequestError(reqwest::Error),
|
||||
Unexpected(String),
|
||||
}
|
||||
|
||||
pub struct ApiBuilder {
|
||||
@ -47,6 +48,17 @@ impl ApiBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build_request_remote(&mut self, meth: Method, path: &str) -> &mut ApiBuilder {
|
||||
dotenv().ok();
|
||||
let host = env::var("HOST").unwrap();
|
||||
let mut url = String::from(host);
|
||||
url.push_str("/");
|
||||
url.push_str(path);
|
||||
dbg!(url.clone());
|
||||
self.request = Some(self.client.request(meth, url));
|
||||
self
|
||||
}
|
||||
|
||||
fn set_auth(&mut self) -> &mut ApiBuilder {
|
||||
// todo if not exist
|
||||
dotenv().ok();
|
||||
|
@ -1,23 +1,34 @@
|
||||
use crate::services::api::{ApiBuilder, ApiError};
|
||||
use reqwest::{Method, IntoUrl, Response, Error};
|
||||
use std::path::PathBuf;
|
||||
use reqwest::{Method, Response, Error};
|
||||
use crate::utils::api::get_local_path_t;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{self, Write};
|
||||
|
||||
pub struct DownloadFiles {
|
||||
api_builder: ApiBuilder,
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl DownloadFiles {
|
||||
pub fn new<U: IntoUrl>(url: U) -> Self {
|
||||
pub fn new() -> Self {
|
||||
DownloadFiles {
|
||||
api_builder: ApiBuilder::new()
|
||||
.set_request(Method::GET, url),
|
||||
api_builder: ApiBuilder::new(),
|
||||
path: String::from(""),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_url_with_remote(&mut self, url: &str) -> &mut DownloadFiles {
|
||||
self.path = get_local_path_t(url.clone()).strip_prefix("/").unwrap().to_string();
|
||||
self.api_builder.build_request_remote(Method::GET, url);
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
||||
self.api_builder.send().await
|
||||
}
|
||||
|
||||
pub async fn send_with_err(mut self) -> Result<Vec<u8>, ApiError> {
|
||||
pub async fn _send_with_err(mut self) -> Result<Vec<u8>, ApiError> {
|
||||
let res = self.send().await.map_err(ApiError::RequestError)?;
|
||||
if res.status().is_success() {
|
||||
let body = res.bytes().await.map_err(ApiError::EmptyError)?;
|
||||
@ -26,4 +37,28 @@ impl DownloadFiles {
|
||||
Err(ApiError::IncorrectRequest(res))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn save(&mut self, local_path: PathBuf) -> Result<(), ApiError> {
|
||||
let p = local_path.join(PathBuf::from(self.path.clone()));
|
||||
let res = self.send().await.map_err(ApiError::RequestError)?;
|
||||
if res.status().is_success() {
|
||||
let body = res.bytes().await.map_err(ApiError::EmptyError)?;
|
||||
match DownloadFiles::write_file(p, &body.to_vec()) {
|
||||
Err(_) => Err(ApiError::Unexpected(String::from(""))),
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
} else {
|
||||
Err(ApiError::IncorrectRequest(res))
|
||||
}
|
||||
}
|
||||
|
||||
fn write_file(path: PathBuf, content: &Vec<u8>) -> io::Result<()> {
|
||||
let mut f = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path.clone())?;
|
||||
|
||||
f.write_all(&content)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,31 @@
|
||||
use crate::services::api::{ApiBuilder, ApiError};
|
||||
use xml::reader::{EventReader, XmlEvent};
|
||||
use std::io::Cursor;
|
||||
use reqwest::{Method, IntoUrl, Response, Error};
|
||||
|
||||
pub struct FolderContent {
|
||||
pub href: Option<String>,
|
||||
}
|
||||
|
||||
impl Clone for FolderContent {
|
||||
fn clone(&self) -> Self {
|
||||
FolderContent {
|
||||
href: self.href.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FolderContent {
|
||||
fn new() -> Self {
|
||||
FolderContent {
|
||||
href: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ListFolders {
|
||||
api_builder: ApiBuilder,
|
||||
xml_balises: Vec<String>,
|
||||
}
|
||||
|
||||
impl ListFolders {
|
||||
@ -10,14 +33,20 @@ impl ListFolders {
|
||||
ListFolders {
|
||||
api_builder: ApiBuilder::new()
|
||||
.set_request(Method::from_bytes(b"PROPFIND").unwrap(), url),
|
||||
xml_balises: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gethref(&mut self) -> &mut ListFolders {
|
||||
self.xml_balises.push(String::from("href"));
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn send(&mut self) -> Result<Response, Error> {
|
||||
self.api_builder.send().await
|
||||
}
|
||||
|
||||
pub async fn send_with_err(mut self) -> Result<String, ApiError> {
|
||||
pub async fn send_with_err(&mut self) -> Result<String, ApiError> {
|
||||
let res = self.send().await.map_err(ApiError::RequestError)?;
|
||||
if res.status().is_success() {
|
||||
let body = res.text().await.map_err(ApiError::EmptyError)?;
|
||||
@ -27,21 +56,59 @@ impl ListFolders {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_with_res(self) -> String {
|
||||
pub async fn send_with_res(&mut self) -> Result<Vec<FolderContent>, ApiError> {
|
||||
match self.send_with_err().await {
|
||||
Ok(body) => body,
|
||||
Err(ApiError::IncorrectRequest(err)) => {
|
||||
eprintln!("fatal: {}", err.status());
|
||||
std::process::exit(1);
|
||||
},
|
||||
Err(ApiError::EmptyError(_)) => {
|
||||
eprintln!("Failed to get body");
|
||||
String::from("")
|
||||
Ok(body) => Ok(self.parse(body)),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
Err(ApiError::RequestError(err)) => {
|
||||
eprintln!("fatal: {}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
pub fn parse(&self, xml: String) -> Vec<FolderContent> {
|
||||
let cursor = Cursor::new(xml);
|
||||
let parser = EventReader::new(cursor);
|
||||
|
||||
let mut should_get = false;
|
||||
let mut values: Vec<FolderContent> = vec![];
|
||||
|
||||
let mut iter = self.xml_balises.iter();
|
||||
let mut val = iter.next();
|
||||
let mut content = FolderContent::new();
|
||||
|
||||
for event in parser {
|
||||
match event {
|
||||
Ok(XmlEvent::StartElement { name, .. }) => {
|
||||
if let Some(v) = val.clone() {
|
||||
should_get = &name.local_name == v;
|
||||
} else {
|
||||
// end of balises to get then start over for next object
|
||||
values.push(content.clone());
|
||||
iter = self.xml_balises.iter();
|
||||
val = iter.next();
|
||||
content = FolderContent::new();
|
||||
if let Some(v) = val.clone() {
|
||||
should_get = &name.local_name == v;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(XmlEvent::Characters(text)) => {
|
||||
if !text.trim().is_empty() && should_get {
|
||||
match val.unwrap().as_str() {
|
||||
"href" => content.href = Some(text),
|
||||
_ => (),
|
||||
}
|
||||
val = iter.next()
|
||||
}
|
||||
}
|
||||
Ok(XmlEvent::EndElement { .. }) => {
|
||||
should_get = false;
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", e);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
values
|
||||
}
|
||||
}
|
||||
|
@ -35,25 +35,25 @@ impl ReqProps {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn getcontenttype(&mut self) -> &mut ReqProps {
|
||||
pub fn _getcontenttype(&mut self) -> &mut ReqProps {
|
||||
self.xml_list.push(String::from("getcontenttype"));
|
||||
self.xml_payload.push_str(r#"<d:getcontenttype/>"#);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn getpermissions(&mut self) -> &mut ReqProps {
|
||||
pub fn _getpermissions(&mut self) -> &mut ReqProps {
|
||||
self.xml_list.push(String::from("permissions"));
|
||||
self.xml_payload.push_str(r#"<oc:permissions/>"#);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn getressourcetype(&mut self) -> &mut ReqProps {
|
||||
pub fn _getressourcetype(&mut self) -> &mut ReqProps {
|
||||
self.xml_list.push(String::from("resourcetype"));
|
||||
self.xml_payload.push_str(r#"<d:resourcetype/>"#);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn getetag(&mut self) -> &mut ReqProps {
|
||||
pub fn _getetag(&mut self) -> &mut ReqProps {
|
||||
self.xml_list.push(String::from("getetag"));
|
||||
self.xml_payload.push_str(r#"<d:getetag/>"#);
|
||||
self
|
||||
|
@ -57,7 +57,7 @@ pub fn add_tree(path: &Path) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn rm_blob(path: &Path) -> io::Result<()> {
|
||||
let (line, hash, name) = parse_path(path.clone(), true);
|
||||
let (line, hash, _) = parse_path(path.clone(), true);
|
||||
|
||||
// remove blob reference to parent
|
||||
if path.iter().count() == 1 {
|
||||
@ -84,7 +84,6 @@ pub fn rm_blob(path: &Path) -> io::Result<()> {
|
||||
|
||||
pub fn add_blob(path: &Path, date: &str) -> io::Result<()> {
|
||||
let (line, hash, name) = parse_path(path.clone(), true);
|
||||
|
||||
// add blob reference to parent
|
||||
if path.iter().count() == 1 {
|
||||
head::add_line(line)?;
|
||||
@ -112,7 +111,7 @@ fn hash_obj(obj: &str) -> (String, String) {
|
||||
(String::from(dir), String::from(res))
|
||||
}
|
||||
|
||||
fn object_path(obj: &str) -> PathBuf {
|
||||
fn _object_path(obj: &str) -> PathBuf {
|
||||
let mut root = match path::objects() {
|
||||
Some(path) => path,
|
||||
None => todo!(),
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod path;
|
||||
pub mod read;
|
||||
pub mod nextsyncignore;
|
||||
pub mod api;
|
||||
|
23
src/utils/api.rs
Normal file
23
src/utils/api.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::env;
|
||||
|
||||
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());
|
||||
final_p = final_p.strip_prefix("/remote.php/dav/files/").unwrap();
|
||||
final_p = final_p.strip_prefix(username.clone()).unwrap();
|
||||
let dist_p = Path::new(dist_p).strip_prefix("/");
|
||||
final_p = final_p.strip_prefix(dist_p.unwrap()).unwrap();
|
||||
local_p.clone().join(final_p.clone())
|
||||
}
|
||||
|
||||
pub fn get_local_path_t(p: &str) -> String {
|
||||
dbg!(p.clone());
|
||||
let username = env::var("USERNAME").unwrap();
|
||||
let root = env::var("ROOT").unwrap();
|
||||
let mut final_p = p;
|
||||
final_p = final_p.strip_prefix("/remote.php/dav/files/").unwrap();
|
||||
final_p = final_p.strip_prefix(&username).unwrap();
|
||||
final_p = final_p.strip_prefix("/").unwrap();
|
||||
final_p = final_p.strip_prefix(&root).unwrap();
|
||||
final_p.to_string()
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
use crate::utils::{read, path};
|
||||
use crate::utils::path;
|
||||
use regex::Regex;
|
||||
use std::fs::File;
|
||||
use std::io::{Cursor, Lines, BufReader, empty, BufRead};
|
||||
use std::io::{BufReader, BufRead};
|
||||
|
||||
fn read_lines() -> Result<Vec<String>, ()> {
|
||||
pub fn read_lines() -> Result<Vec<String>, ()> {
|
||||
if let Some(path) = path::nextsyncignore() {
|
||||
let file = match File::open(path) {
|
||||
Ok(buffer) => buffer,
|
||||
@ -23,13 +23,11 @@ fn read_lines() -> Result<Vec<String>, ()> {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
pub fn ignore_files(files: &mut Vec<String>) -> (bool, Vec<String>) {
|
||||
pub fn _ignore_files(files: &mut Vec<String>) -> (bool, Vec<String>) {
|
||||
let mut ignored_f = vec![];
|
||||
if let Some(path) = path::nextsyncignore() {
|
||||
if let Ok(lines) = read_lines() {
|
||||
files.retain(|file| !ignore_file(file, lines.clone(), &mut ignored_f));
|
||||
}
|
||||
}
|
||||
(ignored_f.len() > 0, ignored_f)
|
||||
}
|
||||
|
||||
@ -56,7 +54,7 @@ fn normalize_rule(l: String) -> String {
|
||||
|
||||
pub fn ignore_file(path: &String, lines: Vec<String>, ignored_f: &mut Vec<String>) -> bool {
|
||||
let mut ignored = false;
|
||||
for mut line in lines {
|
||||
for line in lines {
|
||||
if line.starts_with("!") {
|
||||
if !ignored {
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user