feat(service): started service

This commit is contained in:
grimhilt 2024-09-14 21:33:11 +02:00
parent cd7b225145
commit e780279acd
15 changed files with 202 additions and 45 deletions

View File

@ -3,3 +3,4 @@ pub mod init;
pub mod status;
pub mod reset;
pub mod push;
pub mod test;

View File

@ -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());

View File

@ -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();

View File

@ -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 {

12
src/commands/test.rs Normal file
View File

@ -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());
}

View File

@ -3,3 +3,4 @@ pub mod config;
pub mod store;
pub mod subcommands;
pub mod utils;
pub mod services;

View File

@ -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 => {}
};

2
src/services.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod service;
pub mod req_props;

81
src/services/req_props.rs Normal file
View File

@ -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 => "<d:creationdate />",
Props::GetLastModified => "<d:getlastmodified />",
_ => todo!("Props conversion not implemented"),
}
}
}
pub struct ReqProps {
service: Service,
properties: Vec<Props>,
}
impl ReqProps {
pub fn new(path: &str) -> Self {
ReqProps {
service: Service::new(),
properties: Vec::new(),
}
}
pub fn get_properties(mut self, properties: Vec<Props>) -> 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#"<?xml version="1.0" encoding="UTF-8"?><d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns"><d:prop>"#,
);
for property in &self.properties {
xml.push_str(property.into());
}
xml.push_str(r#"</d:prop></d:propfind>"#);
xml
}
pub fn send(&mut self) {
self.service
.propfind(String::from(
"http://localhost:8080/remote.php/dav/files/admin/Documents",
))
.send();
}
}
impl From<Obj> for ReqProps {
fn from(obj: Obj) -> Self {
ReqProps::new("")
}
}

63
src/services/service.rs Normal file
View File

@ -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<ClientBuilder>,
}
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<Method>,
url: Option<String>,
headers: HeaderMap,
body: Option<String>,
}
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());
}
}

View File

@ -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<Mutex<Vec<PathBuf>>> =
LazyLock::new(|| Mutex::new(vec![PathBuf::new()]));
use std::path::{Path, PathBuf};
use std::sync::{Mutex, OnceLock};
static REPO_ROOT: OnceLock<PathBuf> = OnceLock::new();
pub fn init(repo_root: &Option<PathBuf>) {
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<Path> 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<ObjPath> 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();

View File

@ -3,3 +3,4 @@ pub mod init;
pub mod reset;
pub mod status;
pub mod push;
pub mod test;

13
src/subcommands/test.rs Normal file
View File

@ -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());
}

View File

@ -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()
}

View File

@ -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<PathBuf> = LazyLock::new(|| {
let mut exe_path = env::current_dir().unwrap();
exe_path = exe_path.join("target/debug/nextsync");
exe_path
});
static EXE_PATH: OnceLock<PathBuf> = 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()