Compare commits
No commits in common. "d442bf689cdbd4e5bedd59cd83ff97d67d9dab85" and "61531f664b3c5abfcb8578a1784c1614343f77eb" have entirely different histories.
d442bf689c
...
61531f664b
@ -4,4 +4,3 @@ pub mod status;
|
|||||||
pub mod reset;
|
pub mod reset;
|
||||||
pub mod push;
|
pub mod push;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
pub mod clone;
|
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
use crate::config::config::Config;
|
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
pub struct CloneArgs {
|
|
||||||
pub remote: String,
|
|
||||||
pub depth: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exec(args: CloneArgs, config: Config) {
|
|
||||||
get_url_props(&args.remote);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UrlProps<'a> {
|
|
||||||
is_secure: bool,
|
|
||||||
domain: &'a str,
|
|
||||||
path: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UrlProps<'_> {
|
|
||||||
fn new() -> Self {
|
|
||||||
UrlProps {
|
|
||||||
is_secure: true,
|
|
||||||
domain: "",
|
|
||||||
path: "",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_url_props(url: &str) -> UrlProps {
|
|
||||||
let mut url_props = UrlProps::new();
|
|
||||||
|
|
||||||
// Match protocol and domain
|
|
||||||
let re = Regex::new(r"((?<protocol>https?)://)?(?<domain>[^/]*)").unwrap();
|
|
||||||
let captures = re.captures(url).expect("fatal: invalid url");
|
|
||||||
|
|
||||||
// Assume is secure
|
|
||||||
let protocol = captures.name("protocol").map_or("https", |m| m.as_str());
|
|
||||||
|
|
||||||
url_props.is_secure = protocol == "https";
|
|
||||||
url_props.domain = captures
|
|
||||||
.name("domain")
|
|
||||||
.map(|m| m.as_str())
|
|
||||||
.expect("fatal: domain not found");
|
|
||||||
|
|
||||||
// Get rest of url
|
|
||||||
let end_of_domain_idx = captures
|
|
||||||
.name("domain")
|
|
||||||
.expect("Already unwraped before")
|
|
||||||
.end();
|
|
||||||
let rest_of_url = &url[end_of_domain_idx..];
|
|
||||||
|
|
||||||
// Try webdav url
|
|
||||||
if let Some(rest_of_url) = rest_of_url.strip_prefix("/remote.php/dav/files") {
|
|
||||||
let re = Regex::new(r"[^\/]*(?<path>.*)").unwrap();
|
|
||||||
url_props.path = re
|
|
||||||
.captures(rest_of_url)
|
|
||||||
.expect("fatal: invalid webdav url")
|
|
||||||
.name("path")
|
|
||||||
.map_or("/", |m| m.as_str());
|
|
||||||
return url_props;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try 'dir' argument
|
|
||||||
let re = Regex::new(r"\?dir=(?<path>[^&]*)").unwrap();
|
|
||||||
if let Some(captures) = re.captures(rest_of_url) {
|
|
||||||
url_props.path = captures.name("path").map_or("/", |m| m.as_str());
|
|
||||||
return url_props;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try path next to domain
|
|
||||||
if rest_of_url.chars().nth(0).expect("fatal: invalid url") == '/' {
|
|
||||||
url_props.path = rest_of_url;
|
|
||||||
return url_props;
|
|
||||||
}
|
|
||||||
|
|
||||||
panic!("fatal: invalid url (cannot found path)");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
const DOMAIN: &str = "nextcloud.com";
|
|
||||||
const SUBDOMAIN: &str = "nextcloud.example.com";
|
|
||||||
|
|
||||||
fn compare_url_props(url_to_test: &str, is_secure: bool, domain: &str) {
|
|
||||||
let path = "/foo/bar";
|
|
||||||
let url_props = get_url_props(url_to_test);
|
|
||||||
assert_eq!(url_props.is_secure, is_secure);
|
|
||||||
assert_eq!(url_props.domain, domain);
|
|
||||||
assert_eq!(url_props.path, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_url_props_from_browser_test() {
|
|
||||||
compare_url_props(
|
|
||||||
"https://nextcloud.com/apps/files/?dir=/foo/bar&fileid=166666",
|
|
||||||
true,
|
|
||||||
DOMAIN,
|
|
||||||
);
|
|
||||||
compare_url_props(
|
|
||||||
"https://nextcloud.com/apps/files/files/625?dir=/foo/bar",
|
|
||||||
true,
|
|
||||||
DOMAIN,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_url_props_direct_url_test() {
|
|
||||||
compare_url_props("https://nextcloud.example.com/foo/bar", true, SUBDOMAIN);
|
|
||||||
compare_url_props("http://nextcloud.example.com/foo/bar", false, SUBDOMAIN);
|
|
||||||
compare_url_props("nextcloud.example.com/foo/bar", true, SUBDOMAIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_url_props_with_port_test() {
|
|
||||||
compare_url_props("localhost:8080/foo/bar", true, "localhost:8080");
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,12 +18,9 @@ pub fn exec(args: TestArgs, config: Config) {
|
|||||||
// println!("{:?}", config);
|
// println!("{:?}", config);
|
||||||
|
|
||||||
// Ok(())
|
// Ok(())
|
||||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
let req = ReqProps::new("")
|
||||||
|
|
||||||
let mut req = ReqProps::new("")
|
|
||||||
.set_config(&config)
|
.set_config(&config)
|
||||||
.get_properties(vec![Props::CreationDate, Props::LastModified]);
|
.get_properties(vec![Props::CreationDate, Props::GetLastModified])
|
||||||
req.send().await;
|
.send();
|
||||||
});
|
dbg!(req);
|
||||||
// dbg!(req);
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ fn main() {
|
|||||||
subcommands::reset::create(),
|
subcommands::reset::create(),
|
||||||
subcommands::push::create(),
|
subcommands::push::create(),
|
||||||
subcommands::test::create(),
|
subcommands::test::create(),
|
||||||
subcommands::clone::create(),
|
|
||||||
]);
|
]);
|
||||||
// .setting(clap::AppSettings::SubcommandRequiredElseHelp);
|
// .setting(clap::AppSettings::SubcommandRequiredElseHelp);
|
||||||
|
|
||||||
@ -32,7 +31,6 @@ fn main() {
|
|||||||
Some(("reset", args)) => subcommands::reset::handler(args),
|
Some(("reset", args)) => subcommands::reset::handler(args),
|
||||||
Some(("push", args)) => subcommands::push::handler(args),
|
Some(("push", args)) => subcommands::push::handler(args),
|
||||||
Some(("test", args)) => subcommands::test::handler(args),
|
Some(("test", args)) => subcommands::test::handler(args),
|
||||||
Some(("clone", args)) => subcommands::clone::handler(args),
|
|
||||||
Some((_, _)) => {}
|
Some((_, _)) => {}
|
||||||
None => {}
|
None => {}
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
use crate::services::service::Service;
|
use crate::services::service::Service;
|
||||||
use crate::store::object::Obj;
|
use crate::store::object::Obj;
|
||||||
use crate::config::config::Config;
|
use crate::config::config::Config;
|
||||||
use serde::Deserialize;
|
|
||||||
use serde_xml_rs::from_str;
|
|
||||||
|
|
||||||
pub enum Props {
|
pub enum Props {
|
||||||
CreationDate,
|
CreationDate,
|
||||||
LastModified,
|
GetLastModified,
|
||||||
ETag,
|
GetETag,
|
||||||
ContentType,
|
GetContentType,
|
||||||
RessourceType,
|
RessourceType,
|
||||||
ContentLength,
|
GetContentLength,
|
||||||
ContentLanguage,
|
GetContentLanguage,
|
||||||
DisplayName,
|
DisplayName,
|
||||||
FileId,
|
FileId,
|
||||||
Permissions,
|
Permissions,
|
||||||
@ -25,41 +23,11 @@ pub enum Props {
|
|||||||
ContainedFileCountm,
|
ContainedFileCountm,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
struct Propstat {
|
|
||||||
#[serde(rename = "prop")]
|
|
||||||
prop: Prop,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
struct Prop {
|
|
||||||
#[serde(rename = "getlastmodified")]
|
|
||||||
last_modified: Option<String>,
|
|
||||||
#[serde(rename = "getcontentlength")]
|
|
||||||
content_length: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
struct Response {
|
|
||||||
#[serde(rename = "href")]
|
|
||||||
href: String,
|
|
||||||
#[serde(rename = "propstat")]
|
|
||||||
propstat: Propstat,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
struct Multistatus {
|
|
||||||
#[serde(rename = "response")]
|
|
||||||
responses: Vec<Response>,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl From<&Props> for &str {
|
impl From<&Props> for &str {
|
||||||
fn from(variant: &Props) -> Self {
|
fn from(variant: &Props) -> Self {
|
||||||
match variant {
|
match variant {
|
||||||
Props::CreationDate => "<d:creationdate />",
|
Props::CreationDate => "<d:creationdate />",
|
||||||
Props::LastModified => "<d:getlastmodified />",
|
Props::GetLastModified => "<d:getlastmodified />",
|
||||||
_ => todo!("Props conversion not implemented"),
|
_ => todo!("Props conversion not implemented"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,18 +73,8 @@ impl ReqProps {
|
|||||||
xml
|
xml
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) {
|
pub fn send(&mut self) {
|
||||||
dbg!("send");
|
self.service.send();
|
||||||
let res = self.service.send().await;
|
|
||||||
dbg!("Sent");
|
|
||||||
let text = res.unwrap().text().await.unwrap();
|
|
||||||
self.parse(&text);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse (&self, xml: &str) {
|
|
||||||
dbg!("Parsing");
|
|
||||||
let multistatus: Multistatus = from_str(&xml).unwrap();
|
|
||||||
dbg!(multistatus);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::config::config::Config;
|
use crate::config::config::Config;
|
||||||
use reqwest::{Client, ClientBuilder};
|
use reqwest::blocking::{Client, ClientBuilder};
|
||||||
use reqwest::{header::HeaderMap, Method, Url};
|
use reqwest::{header::HeaderMap, Method, Url};
|
||||||
|
|
||||||
const USER_AGENT: &str = "Nextsync";
|
const USER_AGENT: &str = "Nextsync";
|
||||||
@ -65,10 +65,9 @@ impl Service {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self) -> Result<reqwest::Response, reqwest::Error> {
|
pub fn send(&mut self) {
|
||||||
let mut url = self
|
let mut url = self
|
||||||
.config
|
.config.clone()
|
||||||
.clone()
|
|
||||||
.expect("A config must be provided to service")
|
.expect("A config must be provided to service")
|
||||||
.get_nsconfig()
|
.get_nsconfig()
|
||||||
.get_remote("origin")
|
.get_remote("origin")
|
||||||
@ -76,11 +75,11 @@ impl Service {
|
|||||||
.expect("An url must be set on the remote");
|
.expect("An url must be set on the remote");
|
||||||
url.push_str(&self.url.clone().unwrap());
|
url.push_str(&self.url.clone().unwrap());
|
||||||
|
|
||||||
self.client
|
dbg!(self
|
||||||
|
.client
|
||||||
.build()
|
.build()
|
||||||
.request(self.method.clone().expect("Method must be set"), url)
|
.request(self.method.clone().expect("Method must be set"), url,)
|
||||||
.bearer_auth("rK5ud2NmrR8p586Th7v272HRgUcZcEKIEluOGjzQQRj7gWMMAISFTiJcFnnmnNiu2VVlENks")
|
.bearer_auth("rK5ud2NmrR8p586Th7v272HRgUcZcEKIEluOGjzQQRj7gWMMAISFTiJcFnnmnNiu2VVlENks")
|
||||||
.send()
|
.send());
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,3 @@ pub mod reset;
|
|||||||
pub mod status;
|
pub mod status;
|
||||||
pub mod push;
|
pub mod push;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
pub mod clone;
|
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
use clap::{Arg, Command, ArgMatches};
|
|
||||||
|
|
||||||
use crate::commands;
|
|
||||||
use crate::config::config::Config;
|
|
||||||
|
|
||||||
pub fn create() -> Command {
|
|
||||||
// let remote_desc = sized_str(&format!("The repository to clone from. See the NEXTSYNC URLS section below for more information on specifying repositories."));
|
|
||||||
// let depth_desc = sized_str(&format!("Depth of the recursive fetch of object properties. This value should be lower when there are a lot of files per directory and higher when there are a lot of subdirectories with fewer files. (Default: {})", clone::DEPTH));
|
|
||||||
Command::new("clone")
|
|
||||||
.arg(
|
|
||||||
Arg::new("remote")
|
|
||||||
.required(true)
|
|
||||||
.num_args(1)
|
|
||||||
.value_name("REMOTE")
|
|
||||||
//.help(_desc)
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new("depth")
|
|
||||||
.short('d')
|
|
||||||
.long("depth")
|
|
||||||
.required(false)
|
|
||||||
.num_args(1)
|
|
||||||
//.help(&depth_desc)
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new("directory")
|
|
||||||
.required(false)
|
|
||||||
.num_args(1)
|
|
||||||
.value_name("DIRECTORY")
|
|
||||||
)
|
|
||||||
.about("Clone a repository into a new directory")
|
|
||||||
.after_help("NEXTSYNC URLS\nThe following syntaxes may be used:\n\t- user@host.xz/path/to/repo\n\t- http[s]://host.xz/apps/files/?dir=/path/to/repo&fileid=111111\n\t- [http[s]://]host.xz/remote.php/dav/files/user/path/to/repo\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handler(args: &ArgMatches) {
|
|
||||||
if let Some(val) = args.get_one::<String>("directory") {
|
|
||||||
// global::global::set_dir_path(String::from(val.to_string()));
|
|
||||||
}
|
|
||||||
if let Some(remote) = args.get_one::<String>("remote") {
|
|
||||||
commands::clone::exec(commands::clone::CloneArgs {
|
|
||||||
remote: remote.to_string(),
|
|
||||||
depth: args.get_one::<String>("depth").cloned(),
|
|
||||||
}, Config::new());
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,7 @@ fn compare_vect(vec1: Vec<Obj>, vec2: Vec<&str>, config: &Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn status_expected(config: &Config, staged: Vec<&str>, not_staged: Vec<&str>) {
|
fn status_expected(config: &Config, staged: Vec<&str>, not_staged: Vec<&str>) {
|
||||||
let res = get_obj_changes(config);
|
let res = get_obj_changes(&DEFAULT_STATUS_ARG, config);
|
||||||
|
|
||||||
assert_eq!(res.staged.len(), staged.len());
|
assert_eq!(res.staged.len(), staged.len());
|
||||||
assert_eq!(res.not_staged.len(), not_staged.len());
|
assert_eq!(res.not_staged.len(), not_staged.len());
|
||||||
|
Loading…
Reference in New Issue
Block a user