diff --git a/src/commands.rs b/src/commands.rs index 576bbc0..90f61a8 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -3,3 +3,4 @@ pub mod init; pub mod status; pub mod reset; pub mod push; +pub mod test; diff --git a/src/commands/add.rs b/src/commands/add.rs index 2257a44..9fb1072 100644 --- a/src/commands/add.rs +++ b/src/commands/add.rs @@ -21,7 +21,7 @@ pub struct AddArgs { } pub fn exec(args: AddArgs, config: Config) { - structs::init(config.get_root()); + structs::init(config.get_root_unsafe()); // Init ignorer let mut ignorer = Ignorer::new(config.get_root_unsafe()); diff --git a/src/commands/push.rs b/src/commands/push.rs index d6e069d..3c98205 100644 --- a/src/commands/push.rs +++ b/src/commands/push.rs @@ -5,7 +5,7 @@ use crate::store::{indexer::Indexer, structs}; pub struct PushArgs {} pub fn exec(args: PushArgs, config: Config) { - structs::init(config.get_root()); + structs::init(config.get_root_unsafe()); let mut indexer = Indexer::new(config.get_root_unsafe()); let _ = indexer.load(); diff --git a/src/commands/status.rs b/src/commands/status.rs index 753a00d..f477ef3 100644 --- a/src/commands/status.rs +++ b/src/commands/status.rs @@ -110,7 +110,7 @@ pub fn exec(args: StatusArgs, config: Config) { } pub fn get_obj_changes(args: &StatusArgs, config: &Config) -> ObjStaged { - structs::init(config.get_root()); + structs::init(config.get_root_unsafe()); // use root of repo if no custom path has been set by the command let root = if config.is_custom_execution_path { diff --git a/src/commands/test.rs b/src/commands/test.rs new file mode 100644 index 0000000..f56964b --- /dev/null +++ b/src/commands/test.rs @@ -0,0 +1,12 @@ +use crate::config::config::Config; +use crate::services::req_props::{Props, ReqProps}; +use crate::store::object::Obj; +use crate::store::{indexer::Indexer, structs}; + +pub struct TestArgs {} + +pub fn exec(args: TestArgs, config: Config) { + dbg!(ReqProps::new("") + .get_properties(vec![Props::CreationDate, Props::GetLastModified]) + .send()); +} diff --git a/src/lib.rs b/src/lib.rs index 9c1dbc1..e497633 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,3 +3,4 @@ pub mod config; pub mod store; pub mod subcommands; pub mod utils; +pub mod services; diff --git a/src/main.rs b/src/main.rs index 7bb0a50..262fcc1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod config; mod store; mod subcommands; mod utils; +mod services; fn main() { let app = Command::new("Nextsync") @@ -17,6 +18,7 @@ fn main() { subcommands::status::create(), subcommands::reset::create(), subcommands::push::create(), + subcommands::test::create(), ]); // .setting(clap::AppSettings::SubcommandRequiredElseHelp); @@ -28,6 +30,7 @@ fn main() { Some(("status", args)) => subcommands::status::handler(args), Some(("reset", args)) => subcommands::reset::handler(args), Some(("push", args)) => subcommands::push::handler(args), + Some(("test", args)) => subcommands::test::handler(args), Some((_, _)) => {} None => {} }; diff --git a/src/services.rs b/src/services.rs new file mode 100644 index 0000000..8bfeec3 --- /dev/null +++ b/src/services.rs @@ -0,0 +1,2 @@ +pub mod service; +pub mod req_props; diff --git a/src/services/req_props.rs b/src/services/req_props.rs new file mode 100644 index 0000000..79a40b5 --- /dev/null +++ b/src/services/req_props.rs @@ -0,0 +1,81 @@ +use crate::services::service::Service; +use crate::store::object::Obj; + +pub enum Props { + CreationDate, + GetLastModified, + GetETag, + GetContentType, + RessourceType, + GetContentLength, + GetContentLanguage, + DisplayName, + FileId, + Permissions, + Size, + HasPreview, + Favorite, + CommentsUnread, + OwnerDisplayName, + ShareTypes, + ContainedFolderCount, + ContainedFileCountm, +} + +impl From<&Props> for &str { + fn from(variant: &Props) -> Self { + match variant { + Props::CreationDate => "", + Props::GetLastModified => "", + _ => todo!("Props conversion not implemented"), + } + } +} + +pub struct ReqProps { + service: Service, + properties: Vec, +} + +impl ReqProps { + pub fn new(path: &str) -> Self { + ReqProps { + service: Service::new(), + properties: Vec::new(), + } + } + + pub fn get_properties(mut self, properties: Vec) -> Self { + self.properties.extend(properties); + self + } + + pub fn get_property(&mut self, property: Props) { + self.properties.push(property); + } + + fn get_body(&self) -> String { + let mut xml = String::from( + r#""#, + ); + for property in &self.properties { + xml.push_str(property.into()); + } + xml.push_str(r#""#); + xml + } + + pub fn send(&mut self) { + self.service + .propfind(String::from( + "http://localhost:8080/remote.php/dav/files/admin/Documents", + )) + .send(); + } +} + +impl From for ReqProps { + fn from(obj: Obj) -> Self { + ReqProps::new("") + } +} diff --git a/src/services/service.rs b/src/services/service.rs new file mode 100644 index 0000000..2a309f3 --- /dev/null +++ b/src/services/service.rs @@ -0,0 +1,63 @@ +use core::ops::{Deref, DerefMut}; +use reqwest::blocking::{Client, ClientBuilder, RequestBuilder}; +use reqwest::{header::HeaderMap, Method, Url}; + +const USER_AGENT: &str = "Nextsync"; + +pub struct ClientConfig { + client: Option, +} + +impl ClientConfig { + pub fn new() -> Self { + ClientConfig { + client: Some(Client::builder().user_agent(USER_AGENT)), + } + } + + pub fn default_headers(mut self, headers: HeaderMap) -> Self { + self.client = Some(self.client.take().expect("Client was already built").default_headers(headers)); + self + } + + pub fn build(&mut self) -> Client { + self.client.take().expect("Cannot build the client twice").build().unwrap() + } +} + +pub struct Service { + client: ClientConfig, + method: Option, + url: Option, + headers: HeaderMap, + body: Option, +} + +impl Service { + pub fn new() -> Self { + Service { + client: ClientConfig::new(), + method: None, + url: None, + headers: HeaderMap::new(), + body: None, + } + } + + pub fn propfind(&mut self, url: String) -> &mut Self { + self.method = Some(Method::from_bytes(b"PROPFIND").expect("Cannot be invalid")); + self.url = Some(url); + self + } + + pub fn send(&mut self) { + dbg!(self.client + .build() + .request( + self.method.clone().expect("Method must be set"), + self.url.clone().expect("Url must be set"), + ) + .bearer_auth("rK5ud2NmrR8p586Th7v272HRgUcZcEKIEluOGjzQQRj7gWMMAISFTiJcFnnmnNiu2VVlENks") + .send()); + } +} diff --git a/src/store/structs.rs b/src/store/structs.rs index 2d2957a..88fbbe0 100644 --- a/src/store/structs.rs +++ b/src/store/structs.rs @@ -1,34 +1,25 @@ use crate::utils::{path, tests}; -use crypto::digest::Digest; -use crypto::sha1::Sha1; +use crypto::{digest::Digest, sha1::Sha1}; +use std::env; use std::ops::{Deref, DerefMut}; -use std::path::{PathBuf, Path}; -use std::sync::{LazyLock, Mutex, OnceLock}; - -// for tests only as it is mutable -static REPO_ROOT_DEV: LazyLock>> = - LazyLock::new(|| Mutex::new(vec![PathBuf::new()])); +use std::path::{Path, PathBuf}; +use std::sync::{Mutex, OnceLock}; static REPO_ROOT: OnceLock = OnceLock::new(); -pub fn init(repo_root: &Option) { +pub fn init(repo_root: &PathBuf) { if tests::is_var_setup() { - REPO_ROOT_DEV.lock().unwrap()[0] = repo_root.clone().expect("Tried to initialize REPO_ROOT_DEV without a proper `repo_root`"); - return; + env::set_var("REPO_ROOT_DEV", path::to_string(repo_root)); } - if let Some(repo_root) = repo_root { - if REPO_ROOT.get().is_none() { - let _ = REPO_ROOT.set(repo_root.clone()); - } - } else { - eprintln!("REPO_ROOT failed to initialize"); + if REPO_ROOT.get().is_none() { + let _ = REPO_ROOT.set(repo_root.clone()); } } pub fn get_repo_root() -> PathBuf { if tests::is_var_setup() { - return REPO_ROOT_DEV.lock().unwrap()[0].clone(); + return env::var("REPO_ROOT_DEV").expect("REPO_ROOT_DEV is not set").into(); } match REPO_ROOT.get() { @@ -85,7 +76,10 @@ impl AsRef for ObjPath { } pub fn to_obj_path(path: &PathBuf) -> ObjPath { - ObjPath { path: path.clone(), abs: OnceLock::new() } + ObjPath { + path: path.clone(), + abs: OnceLock::new(), + } } impl Into for &PathBuf { @@ -151,9 +145,7 @@ impl From<&ObjPath> for NsObjPath { let mut path = get_repo_root(); path.push(".nextsync"); path.push("HEAD"); - return NsObjPath { - path - }; + return NsObjPath { path }; } let mut hasher = Sha1::new(); diff --git a/src/subcommands.rs b/src/subcommands.rs index 7fb25cf..5db3430 100644 --- a/src/subcommands.rs +++ b/src/subcommands.rs @@ -3,3 +3,4 @@ pub mod init; pub mod reset; pub mod status; pub mod push; +pub mod test; diff --git a/src/subcommands/test.rs b/src/subcommands/test.rs new file mode 100644 index 0000000..20c87f0 --- /dev/null +++ b/src/subcommands/test.rs @@ -0,0 +1,13 @@ +use clap::{Arg, ArgAction, ArgMatches, Command}; + +use crate::commands; +use crate::commands::test::TestArgs; +use crate::config::config::Config; + +pub fn create() -> Command { + Command::new("test").about("Test command") +} + +pub fn handler(args: &ArgMatches) { + commands::test::exec(TestArgs {}, Config::new()); +} diff --git a/src/utils/tests.rs b/src/utils/tests.rs index 7edab7a..7f0b35b 100644 --- a/src/utils/tests.rs +++ b/src/utils/tests.rs @@ -1,15 +1,5 @@ use std::env; -#[cfg(test)] -pub fn is_running() -> bool { - true -} - -#[cfg(not(test))] -pub fn is_running() -> bool { - false -} - pub fn is_var_setup() -> bool { env::var("RUNNING_TESTS").is_ok() } diff --git a/tests/common/client.rs b/tests/common/client.rs index 4fafb1e..20c3634 100644 --- a/tests/common/client.rs +++ b/tests/common/client.rs @@ -6,14 +6,10 @@ use std::io::{self, Write}; use std::path::PathBuf; use std::process::{Command, Output}; use std::str; -use std::sync::LazyLock; +use std::sync::OnceLock; // Absolute path of the nextsync executable -static EXE_PATH: LazyLock = LazyLock::new(|| { - let mut exe_path = env::current_dir().unwrap(); - exe_path = exe_path.join("target/debug/nextsync"); - exe_path -}); +static EXE_PATH: OnceLock = OnceLock::new(); pub struct ClientTest { volume: String, // temp dir for the test @@ -30,9 +26,11 @@ pub fn get_random_test_id() -> String { impl ClientTest { pub fn new(id: &str) -> Self { - // init the EXE_PATH for the first time - let _ = &*EXE_PATH; - + let _ = EXE_PATH.get_or_init(|| { + let mut exe_path = env::current_dir().unwrap(); + exe_path = exe_path.join("target/debug/nextsync"); + exe_path + }); let mut test_id = id.to_string(); test_id.push_str("_"); test_id.push_str(&get_random_test_id()); @@ -106,7 +104,7 @@ impl ClientTest { } pub fn exec(&mut self, args: &str) -> Output { - let output = Command::new(&*EXE_PATH.to_str().unwrap()) + let output = Command::new(EXE_PATH.get().unwrap().to_str().unwrap()) .current_dir(self.volume.clone()) .args(args.split(" ")) .output()