From 09f1b26a50977bf2ebce9d4435776874c8384572 Mon Sep 17 00:00:00 2001 From: grimhilt Date: Sun, 13 Oct 2024 22:07:42 +0200 Subject: [PATCH] feat(download): simple downloader working without streaming --- src/commands/clone.rs | 17 +++++++++++------ src/commands/test.rs | 6 +++--- src/services/download.rs | 25 ++++++++++++++++++++----- src/services/downloader.rs | 4 ++-- src/services/req_props.rs | 5 +---- src/services/service.rs | 3 ++- src/store/nsobject.rs | 2 +- src/store/object.rs | 34 ++++++++++++++++++++++++---------- src/store/structs.rs | 9 +++++++++ 9 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/commands/clone.rs b/src/commands/clone.rs index f30f5bd..9a29941 100644 --- a/src/commands/clone.rs +++ b/src/commands/clone.rs @@ -1,14 +1,13 @@ -use super::init::{self, InitArgs}; +use super::init; use crate::config::config::Config; use crate::services::{downloader::Downloader, enumerator::Enumerator, service::Service}; use crate::store::{ nsobject::NsObject, - structs::{self, to_obj_path}, + structs, }; use regex::Regex; use std::fs; use std::io::{self, BufRead}; -use std::path::PathBuf; pub struct CloneArgs { pub remote: String, @@ -35,7 +34,7 @@ pub async fn exec(args: CloneArgs, config: Config) { let service = Service::from(&url_props); let Ok((files, folders)) = Enumerator::new(&service) - .set_path(url_props.path.to_string()) + .set_path(String::new()) // use base_path of the service // .set_depth(args.depth) .get_properties(vec![]) .enumerate() @@ -57,8 +56,14 @@ pub async fn exec(args: CloneArgs, config: Config) { } let downloader = Downloader::new(&service) - .set_files(files.into_iter().map(|file| file.href).collect()) - .download(); + .set_files( + files + .into_iter() + .map(|file| file.abs_path().to_string()) + .collect(), + ) + .download() + .await; } pub struct UrlProps<'a> { diff --git a/src/commands/test.rs b/src/commands/test.rs index 33fb4a7..4279a0b 100644 --- a/src/commands/test.rs +++ b/src/commands/test.rs @@ -1,7 +1,7 @@ use crate::config::config::Config; -use crate::services::req_props::{Props, ReqProps}; -use crate::store::object::Obj; -use crate::store::{indexer::Indexer, structs}; +// use crate::services::req_props::{Props, ReqProps}; +// use crate::store::object::Obj; +// use crate::store::{indexer::Indexer, structs}; pub struct TestArgs {} diff --git a/src/services/download.rs b/src/services/download.rs index 0710f6b..b7ab181 100644 --- a/src/services/download.rs +++ b/src/services/download.rs @@ -1,27 +1,42 @@ use crate::services::service::{Request, Service}; -use reqwest::Error; -use reqwest::{header::HeaderMap, Method, Url}; -use reqwest::{Client, ClientBuilder, RequestBuilder}; +use crate::store::nsobject::NsObject; +use std::{fs::OpenOptions, io::Write}; pub struct Download<'a> { request: Request<'a>, + obj_path: String, } impl<'a> Download<'a> { pub fn new(service: &'a Service) -> Self { Download { request: Request::new(service), + obj_path: String::new(), } } pub fn set_obj_path(mut self, obj_path: String) -> Self { - self.request.get(obj_path); + self.request.get(obj_path.clone()); + self.obj_path = obj_path + .strip_prefix("/") + .unwrap_or(&self.obj_path.clone()) + .to_string(); self } pub async fn send(&mut self) -> Result<(), reqwest::Error> { let res = self.request.send().await; - let body = res.unwrap().text().await?; + let body = res.unwrap().bytes().await?; + let mut file = OpenOptions::new() + .write(true) + .create(true) + .open(self.obj_path.clone()) + .unwrap(); + + file.write_all(&body.to_vec()).unwrap(); + NsObject::from_local_path(&self.obj_path.clone().into()) + .save() + .unwrap(); Ok(()) } } diff --git a/src/services/downloader.rs b/src/services/downloader.rs index 586e40a..7010cd8 100644 --- a/src/services/downloader.rs +++ b/src/services/downloader.rs @@ -18,9 +18,9 @@ impl<'a> Downloader<'a> { self } - pub fn download(&self) { + pub async fn download(&self) { for file in self.files.clone() { - Download::new(self.service).set_obj_path(file).send(); + Download::new(self.service).set_obj_path(file).send().await; } } } diff --git a/src/services/req_props.rs b/src/services/req_props.rs index 3d2f554..1373d13 100644 --- a/src/services/req_props.rs +++ b/src/services/req_props.rs @@ -1,8 +1,5 @@ use crate::services::service::{Request, Service}; -use crate::store::{ - object::Obj, - structs::{to_obj_path, ObjPath}, -}; +use crate::store::structs::{to_obj_path, ObjPath}; use crate::utils::path; use serde::Deserialize; use serde_xml_rs::from_str; diff --git a/src/services/service.rs b/src/services/service.rs index 2f1d787..9070dd7 100644 --- a/src/services/service.rs +++ b/src/services/service.rs @@ -1,5 +1,5 @@ use crate::commands::clone::UrlProps; -use reqwest::{header::HeaderMap, Method, Url}; +use reqwest::{header::HeaderMap, Method}; use reqwest::{Client, ClientBuilder, RequestBuilder}; const USER_AGENT: &str = "Nextsync"; @@ -70,6 +70,7 @@ impl Service { let mut final_url = self.url_base.clone(); final_url.push_str("/"); final_url.push_str(&self.user); + final_url.push_str(&self.base_path); final_url.push_str(url); final_url } diff --git a/src/store/nsobject.rs b/src/store/nsobject.rs index 7203259..a6059d6 100644 --- a/src/store/nsobject.rs +++ b/src/store/nsobject.rs @@ -5,7 +5,7 @@ use crate::store::{ use std::fs::{self, File, OpenOptions}; use std::io::{self, Write}; use std::sync::OnceLock; -use std::time::{SystemTime, UNIX_EPOCH}; +use std::time::UNIX_EPOCH; type NsObjectChilds = Vec>; diff --git a/src/store/object.rs b/src/store/object.rs index 8172d5f..1ad4854 100644 --- a/src/store/object.rs +++ b/src/store/object.rs @@ -3,12 +3,12 @@ use crate::store::{ structs::{NsObjPath, ObjPath}, }; use crate::utils::path; -use std::env; -use std::fs::{self, File, OpenOptions}; -use std::io::{self, Write}; -use std::path::PathBuf; -use std::sync::OnceLock; -use std::time::{SystemTime, UNIX_EPOCH}; +use std::{ + env, fmt, fs, io, + path::PathBuf, + sync::OnceLock, + time::SystemTime, +}; const MAX_SIZE_TO_USE_HASH: u64 = 12 * 1024 * 1024; @@ -25,6 +25,12 @@ pub enum ObjType { Tree, } +impl fmt::Display for ObjType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + impl From for u8 { fn from(variant: ObjType) -> Self { variant as u8 @@ -92,10 +98,12 @@ impl Obj { if !self.obj_path.exists() { return ObjStatus::Deleted; } - if *self != nsobj { - return ObjStatus::Modified; + if self.obj_type != ObjType::Tree && nsobj.obj_type != ObjType::Tree { + if *self != nsobj { + return ObjStatus::Modified; + } } - todo!("Read status"); + ObjStatus::Unchanged }) } @@ -191,7 +199,13 @@ impl Obj { impl PartialEq for Obj { fn eq(&self, other: &NsObject) -> bool { if self.obj_type != other.obj_type { - eprintln!("Trying to compare different obj type"); + eprintln!( + "{}", + format!( + "Trying to compare different obj type ({} != {})", + self.obj_type, other.obj_type + ) + ); return false; } diff --git a/src/store/structs.rs b/src/store/structs.rs index aaa910e..017fad2 100644 --- a/src/store/structs.rs +++ b/src/store/structs.rs @@ -102,6 +102,15 @@ impl Into for PathBuf { } } +impl Into for String { + fn into(self) -> ObjPath { + ObjPath { + path: self.into(), + abs: OnceLock::new(), + } + } +} + #[derive(Debug, PartialEq, Clone)] pub struct NsObjPath { path: PathBuf,