From c5d7135d99071815d22d8f09d7687fd58989dc6b Mon Sep 17 00:00:00 2001 From: grimhilt Date: Tue, 3 Sep 2024 23:04:51 +0200 Subject: [PATCH] feat(add): start to add file and improve nsobject --- src/commands/add.rs | 64 ++++++++++++++++++++++++++------- src/commands/status.rs | 2 +- src/store/ignorer.rs | 10 ++++-- src/store/nsobject.rs | 80 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 129 insertions(+), 27 deletions(-) diff --git a/src/commands/add.rs b/src/commands/add.rs index 859cd98..f8e5080 100644 --- a/src/commands/add.rs +++ b/src/commands/add.rs @@ -1,10 +1,6 @@ use crate::config::config::Config; -use crate::store::ignorer::Ignorer; -// use crate::store::object::object::{Obj, ObjMethods}; -// use crate::store::{self, object::Object}; -// use crate::utils::nextsyncignore::{self, ignore_file}; -// use crate::utils::path::{normalize_relative, path_buf_to_string, repo_root}; -// use crate::utils::{self, path}; +use crate::store::{ignorer::Ignorer, nsobject::NsObject}; +use std::fs; // use glob::glob; use std::path::{Path, PathBuf}; @@ -26,6 +22,25 @@ pub fn exec(args: AddArgs, config: Config) { return add_dir(config.get_root_unsafe(), &mut ignorer); } + for obj_to_add in args.files.iter() { + let mut path_to_add = config.execution_path.clone(); + path_to_add.push(PathBuf::from(obj_to_add)); + + if path_to_add.exists() { + if path_to_add.is_dir() { + add_dir(&path_to_add, &mut ignorer); + } else { + add_to_index(&path_to_add); + } + } else if NsObject::from_local_path(&path_to_add).exists() { + add_to_index(&path_to_add); + } else { + // try globbing + // todo!() + // else panic + panic!("fatal: pathspec '{}' did not match any files", obj_to_add); + } + } /* for all files if globbing @@ -45,15 +60,38 @@ pub fn exec(args: AddArgs, config: Config) { /// * `dir`: the directory to add from /// * `force`: true if we should apply the nextsyncignore's rules fn add_dir(dir: &PathBuf, ignorer: &mut Ignorer) { - /* - for elements present in dir { - if !force && should_ignore() { + let entries = match fs::read_dir(dir) { + Ok(entries) => entries, + Err(err) => { + eprintln!("Failed to read {} ({err})", dir.display()); + return; + } + }; + + // Read locals files and folders + for entry in entries { + let entry = match entry { + Ok(entry) => entry, + Err(err) => { + eprintln!("Failed to read entry {err}"); + continue; + } + }; + + // ignore object if it is ns config file or nsignored + if ignorer.should_ignore(&entry.path()) { continue; } - if is dir - add_dir(new_dir, force) - else + if entry.path().is_dir() { + add_dir(&entry.path(), ignorer); + add_to_index(&entry.path()); + } else { + add_to_index(&entry.path()); + } } - */ +} + +fn add_to_index(path: &PathBuf) { + println!("{}", path.display()); } diff --git a/src/commands/status.rs b/src/commands/status.rs index 9016af2..1b01297 100644 --- a/src/commands/status.rs +++ b/src/commands/status.rs @@ -105,7 +105,7 @@ fn compare_dir(pool: ThreadPool, root_path: &PathBuf, path: &PathBuf, res: Arc bool { + path.ends_with(".nextsync") + } + /// Returns whether a file/dir is ignored or not /// /// * `path`: - fn is_ignored(&mut self, path: PathBuf) -> bool { + fn is_ignored(&mut self, path: &PathBuf) -> bool { is_file_ignored(path.to_str().unwrap(), self.get_rules()) } @@ -47,7 +51,7 @@ impl Ignorer { /// `active_nsignore`. /// /// * `path`: - pub fn should_ignore(&mut self, path: PathBuf) -> bool { - self.use_nsignore && self.is_ignored(path) + pub fn should_ignore(&mut self, path: &PathBuf) -> bool { + self.is_config_file(path) || (self.use_nsignore && self.is_ignored(path)) } } diff --git a/src/store/nsobject.rs b/src/store/nsobject.rs index b1a9df0..3d69bde 100644 --- a/src/store/nsobject.rs +++ b/src/store/nsobject.rs @@ -1,12 +1,43 @@ -use crate::store::object::{ObjType, Obj, ObjMetadata}; +use crate::store::object::{Obj, ObjMetadata, ObjType}; +use crypto::digest::Digest; +use crypto::sha1::Sha1; use std::path::PathBuf; use std::sync::OnceLock; type NsObjectChilds = Vec>; +struct NsObjectPath { + path: PathBuf, +} + +impl From<&str> for NsObjectPath { + fn from(hash: &str) -> Self { + let (dir, res) = hash.split_at(2); + + let mut ns_obj_path = PathBuf::new(); + ns_obj_path.push(dir); + ns_obj_path.push(res); + + NsObjectPath { path: ns_obj_path } + } +} + +impl From<&PathBuf> for NsObjectPath { + fn from(obj_path: &PathBuf) -> Self { + let mut hasher = Sha1::new(); + hasher.input_str( + obj_path + .to_str() + .expect("Cannot contains non UTF-8 char in path"), + ); + NsObjectPath::from(hasher.result_str().as_str()) + } +} + pub struct NsObject { pub obj_type: ObjType, obj_path: OnceLock, + nsobj_path: OnceLock, childs: OnceLock, index: usize, } @@ -16,6 +47,7 @@ impl NsObject { NsObject { obj_type: ObjType::Obj, obj_path: OnceLock::from(path.to_path_buf()), + nsobj_path: OnceLock::new(), childs: OnceLock::new(), index: 0, } @@ -25,11 +57,27 @@ impl NsObject { NsObject { obj_type: ObjType::Obj, obj_path: OnceLock::new(), + nsobj_path: OnceLock::from(NsObjectPath::from(hash).path), childs: OnceLock::new(), index: 0, } } + pub fn get_obj_path(&self) -> &PathBuf { + self.obj_path.get_or_init(|| todo!()) + } + + fn get_nsobj_path(&self) -> &PathBuf { + self.nsobj_path + .get_or_init(|| NsObjectPath::from(self.get_obj_path()).path) + } + + /// Return the existence of the nsobj in the store + pub fn exists(&self) -> bool { + println!("{}", self.get_nsobj_path().display()); + self.get_nsobj_path().exists() + } + pub fn get_childs(&self) -> &NsObjectChilds { self.childs.get_or_init(|| { if self.obj_type != ObjType::Tree { @@ -40,14 +88,8 @@ impl NsObject { }) } - pub fn get_obj_path(&self) -> &PathBuf { - self.obj_path.get_or_init(|| { - todo!() - }) - } - pub fn is_file(&self) -> bool { - self.obj_type == ObjType::Blob + self.obj_type == ObjType::Blob } pub fn is_dir(&self) -> bool { @@ -60,6 +102,24 @@ impl NsObject { obj } + /// Saving the nsobj in the store + /// + /// first line consists of all size fixed datas (obj_type, size, modified) + /// next lines are the size variable datas + /// + /// * if it is a Tree obj after an empty line there will be the definition + /// of its subobjs (one line by subobj) * + /// obj_type + hash + pub fn save(&self) -> Result<(), ()> { + if !self.get_obj_path().exists { + // delete current obj + // delete reference on parent + } else { + + } + Ok(()) + } + pub fn get_metadata(&self) -> Option { todo!() } @@ -67,7 +127,7 @@ impl NsObject { pub fn iter(&self) -> NsObjectIter<'_> { NsObjectIter { nsobject: self, - index: 0 + index: 0, } } } @@ -84,7 +144,7 @@ impl<'a> Iterator for NsObjectIter<'a> { self.index += 1; match self.nsobject.get_childs().get(self.index - 1) { None => None, - Some(obj) => Some(&**obj) + Some(obj) => Some(&**obj), } } }