From baeef1a33a90736770b8fed585c86981a26b41b5 Mon Sep 17 00:00:00 2001 From: grimhilt Date: Sun, 8 Sep 2024 17:59:22 +0200 Subject: [PATCH] feat(reset): introduce reset and fix ROOT_PATH --- src/commands.rs | 1 + src/commands/add.rs | 45 +++++++++++++++++++------- src/commands/reset.rs | 11 +++++++ src/commands/status.rs | 13 +++++--- src/config/config.rs | 1 + src/main.rs | 2 ++ src/store/ignorer.rs | 10 +++++- src/store/indexer.rs | 12 +++++-- src/store/nsobject.rs | 15 --------- src/store/structs.rs | 68 +++++++++++++++++++++++++++++++++------- src/subcommands.rs | 1 + src/subcommands/reset.rs | 17 ++++++++++ src/utils.rs | 1 + src/utils/path.rs | 18 +++++++---- src/utils/tests.rs | 15 +++++++++ 15 files changed, 178 insertions(+), 52 deletions(-) create mode 100644 src/commands/reset.rs create mode 100644 src/subcommands/reset.rs create mode 100644 src/utils/tests.rs diff --git a/src/commands.rs b/src/commands.rs index e2eb32e..75b5fee 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,3 +1,4 @@ pub mod add; pub mod init; pub mod status; +pub mod reset; diff --git a/src/commands/add.rs b/src/commands/add.rs index fae9d6f..9382e17 100644 --- a/src/commands/add.rs +++ b/src/commands/add.rs @@ -1,10 +1,12 @@ use crate::config::config::Config; use crate::store::{ - structs::to_obj_path, ignorer::Ignorer, indexer::Indexer, nsobject::{self, NsObject}, + structs::{self, to_obj_path}, }; +use crate::utils::path::to_repo_relative; +use colored::Colorize; use std::fs; // use glob::glob; use std::path::PathBuf; @@ -19,6 +21,8 @@ pub struct AddArgs { } pub fn exec(args: AddArgs, config: Config) { + structs::init(config.get_root()); + // Init ignorer let mut ignorer = Ignorer::new(config.get_root_unsafe()); ignorer.active_nsignore(!args.force); @@ -27,8 +31,6 @@ pub fn exec(args: AddArgs, config: Config) { let mut indexer = Indexer::new(config.get_root_unsafe()); let _ = indexer.load(); - nsobject::init(config.get_root_unsafe()); - if args.all { return add_dir(config.get_root_unsafe(), &mut ignorer, &mut indexer); } @@ -38,6 +40,11 @@ pub fn exec(args: AddArgs, config: Config) { path_to_add.push(PathBuf::from(obj_to_add)); if path_to_add.exists() { + // ignore object if it is ns config file or nsignored + if ignorer.should_ignore(&path_to_add) { + continue; + } + if path_to_add.is_dir() { indexer.index_dir(path_to_add.clone()); add_dir(&path_to_add, &mut ignorer, &mut indexer); @@ -54,17 +61,31 @@ pub fn exec(args: AddArgs, config: Config) { } } + // print all path ignored + if ignorer.ignored_paths.len() > 0 { + println!("The following paths are ignored by one of your .nsignore files:"); + for ignored_path in ignorer.ignored_paths { + println!("{}", to_repo_relative(&ignored_path).display()); + } + println!( + "{}", + "hint: Use -f if you really want to add them.".bright_red() + ); + // hint: Turn this message off by running + // hint: "git config advice.addIgnoredFile false" + } + dbg!(indexer.save()); /* - for all files - if globbing - take all match glob nextsyncignore - else - if dir - add dir - add all childs with nextsyncignore - else - add files + for all files + if globbing + take all match glob nextsyncignore + else + if dir + add dir + add all childs with nextsyncignore + else + add files */ } diff --git a/src/commands/reset.rs b/src/commands/reset.rs new file mode 100644 index 0000000..7e43c25 --- /dev/null +++ b/src/commands/reset.rs @@ -0,0 +1,11 @@ +use crate::config::config::Config; +use crate::store::indexer::Indexer; + +pub struct ResetArgs { +} + +pub fn exec(args: ResetArgs, config: Config) { + // Init ignorer + let indexer = Indexer::new(config.get_root_unsafe()); + let _ = indexer.save(); +} diff --git a/src/commands/status.rs b/src/commands/status.rs index 6706b38..f165042 100644 --- a/src/commands/status.rs +++ b/src/commands/status.rs @@ -1,9 +1,10 @@ use crate::config::config::Config; use crate::store::{ - structs::to_obj_path, indexer::Indexer, nsobject::NsObject, object::{Obj, ObjStatus, ObjType}, + structs, + structs::to_obj_path, }; use crate::utils::path; use colored::{ColoredString, Colorize}; @@ -109,6 +110,8 @@ pub fn exec(args: StatusArgs, config: Config) { } pub fn get_obj_changes(args: &StatusArgs, config: &Config) -> ObjStaged { + structs::init(config.get_root()); + // use root of repo if no custom path has been set by the command let root = if config.is_custom_execution_path { config.execution_path.clone() @@ -236,13 +239,13 @@ fn compare_dir( } }; + if entry.path().ends_with(".nextsync") { + continue; + } + let local_obj = Obj::from_local_path(&entry.path().into()); if entry.path().is_dir() { - if entry.path().ends_with(".nextsync") { - continue; - } - if local_obj.is_new() { // TODO: opti move files in new directory if indexer.is_staged_parent(&local_obj) { diff --git a/src/config/config.rs b/src/config/config.rs index 374fb78..4568070 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -1,6 +1,7 @@ use std::env; use std::path::{Path, PathBuf}; use std::sync::OnceLock; +use crate::store::structs; /// /// # Parameters diff --git a/src/main.rs b/src/main.rs index c82efe5..4073093 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ fn main() { subcommands::init::create(), subcommands::add::create(), subcommands::status::create(), + subcommands::reset::create(), ]); // .setting(clap::AppSettings::SubcommandRequiredElseHelp); @@ -24,6 +25,7 @@ fn main() { Some(("init", args)) => subcommands::init::handler(args), Some(("add", args)) => subcommands::add::handler(args), Some(("status", args)) => subcommands::status::handler(args), + Some(("reset", args)) => subcommands::reset::handler(args), Some((_, _)) => {} None => {} }; diff --git a/src/store/ignorer.rs b/src/store/ignorer.rs index 7037c94..42f8f43 100644 --- a/src/store/ignorer.rs +++ b/src/store/ignorer.rs @@ -9,6 +9,8 @@ pub struct Ignorer { use_nsignore: bool, /// Nsignore's rules rules: OnceLock>, + /// Path that have been ignored by should_ignore function + pub ignored_paths: Vec, childs: Option>>, } @@ -18,6 +20,7 @@ impl Ignorer { path: path.to_path_buf(), use_nsignore: true, rules: OnceLock::new(), + ignored_paths: Vec::new(), childs: None, } } @@ -52,6 +55,11 @@ impl Ignorer { /// /// * `path`: pub fn should_ignore(&mut self, path: &PathBuf) -> bool { - self.is_config_file(path) || (self.use_nsignore && self.is_ignored(path)) + let should = self.is_config_file(path) || (self.use_nsignore && self.is_ignored(path)); + + if should { + self.ignored_paths.push(path.clone()); + } + should } } diff --git a/src/store/indexer.rs b/src/store/indexer.rs index 2751ce5..c404c16 100644 --- a/src/store/indexer.rs +++ b/src/store/indexer.rs @@ -27,9 +27,9 @@ fn sort_paths_hierarchically(paths: &mut Vec) { } #[derive(Debug)] -struct IndexedObj { +pub struct IndexedObj { obj_type: ObjType, - path: PathBuf, + pub path: PathBuf, } pub struct Indexer { @@ -76,6 +76,14 @@ impl Indexer { dbg!(&self.indexed_objs); } + pub fn clear(&mut self) { + self.indexed_objs.clear(); + } + + pub fn get_indexed_objs(&self) -> &Vec { + &self.indexed_objs + } + fn is_indexed(&self, obj: &IndexedObj) -> bool { self.indexed_objs .iter() diff --git a/src/store/nsobject.rs b/src/store/nsobject.rs index f59b073..35a2312 100644 --- a/src/store/nsobject.rs +++ b/src/store/nsobject.rs @@ -5,21 +5,6 @@ use crate::store::{ use std::path::PathBuf; use std::sync::OnceLock; -pub static REPO_ROOT: OnceLock = OnceLock::new(); - -pub fn init(repo_root: &PathBuf) { - let _ = REPO_ROOT.set(repo_root.clone()); -} - -pub fn get_repo_root() -> PathBuf { - match REPO_ROOT.get() { - Some(path) => path.clone(), - None => { - panic!("fatal: 'REPO_ROOT' not set, you must initialize nsobject before using it!") - } - } -} - type NsObjectChilds = Vec>; pub struct NsObject { diff --git a/src/store/structs.rs b/src/store/structs.rs index 33d3c37..e9fb84e 100644 --- a/src/store/structs.rs +++ b/src/store/structs.rs @@ -1,22 +1,60 @@ -use crate::store::nsobject::get_repo_root; -use std::path::PathBuf; +use crate::utils::{path, tests}; use crypto::digest::Digest; use crypto::sha1::Sha1; use std::ops::{Deref, DerefMut}; -use crate::utils::path; +use std::path::PathBuf; +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()])); + +static REPO_ROOT: OnceLock = OnceLock::new(); + +pub fn init(repo_root: &Option) { + if tests::is_var_setup() { + REPO_ROOT_DEV.lock().unwrap()[0] = repo_root.clone().unwrap(); + return; + } + + 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"); + } +} + +pub fn get_repo_root() -> PathBuf { + if tests::is_var_setup() { + return REPO_ROOT_DEV.lock().unwrap()[0].clone(); + } + + match REPO_ROOT.get() { + Some(path) => path.clone(), + None => { + panic!("fatal: 'REPO_ROOT' not set, you must initialize nsobject before using it!") + } + } +} #[derive(Debug, PartialEq, Clone)] pub struct ObjPath { - path: PathBuf + path: PathBuf, } impl Deref for ObjPath { type Target = PathBuf; - fn deref(&self) -> &PathBuf { &self.path } + fn deref(&self) -> &PathBuf { + &self.path + } } impl DerefMut for ObjPath { - fn deref_mut(&mut self) -> &mut PathBuf { &mut self.path } + fn deref_mut(&mut self) -> &mut PathBuf { + &mut self.path + } } pub fn to_obj_path(path: &PathBuf) -> ObjPath { @@ -25,28 +63,36 @@ pub fn to_obj_path(path: &PathBuf) -> ObjPath { impl Into for &PathBuf { fn into(self) -> ObjPath { - ObjPath { path: path::to_repo_relative(self, &get_repo_root())} + ObjPath { + path: path::to_repo_relative(self), + } } } impl Into for PathBuf { fn into(self) -> ObjPath { - ObjPath { path: path::to_repo_relative(&self, &get_repo_root())} + ObjPath { + path: path::to_repo_relative(&self), + } } } #[derive(Debug, PartialEq)] pub struct NsObjPath { - path: PathBuf + path: PathBuf, } impl Deref for NsObjPath { type Target = PathBuf; - fn deref(&self) -> &PathBuf { &self.path } + fn deref(&self) -> &PathBuf { + &self.path + } } impl DerefMut for NsObjPath { - fn deref_mut(&mut self) -> &mut PathBuf { &mut self.path } + fn deref_mut(&mut self) -> &mut PathBuf { + &mut self.path + } } impl From<&str> for NsObjPath { diff --git a/src/subcommands.rs b/src/subcommands.rs index e2eb32e..edd2185 100644 --- a/src/subcommands.rs +++ b/src/subcommands.rs @@ -1,3 +1,4 @@ pub mod add; pub mod init; +pub mod reset; pub mod status; diff --git a/src/subcommands/reset.rs b/src/subcommands/reset.rs new file mode 100644 index 0000000..594cd3d --- /dev/null +++ b/src/subcommands/reset.rs @@ -0,0 +1,17 @@ +use clap::{Arg, ArgAction, ArgMatches, Command}; + +use crate::commands; +use crate::commands::reset::ResetArgs; +use crate::config::config::Config; + +pub fn create() -> Command { + Command::new("reset") + .about("Clear the index") +} + +pub fn handler(args: &ArgMatches) { + commands::reset::exec( + ResetArgs {}, + Config::new(), + ); +} diff --git a/src/utils.rs b/src/utils.rs index 4da9789..f8f797b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1 +1,2 @@ pub mod path; +pub mod tests; diff --git a/src/utils/path.rs b/src/utils/path.rs index d5c565b..c05f53a 100644 --- a/src/utils/path.rs +++ b/src/utils/path.rs @@ -1,7 +1,15 @@ -use std::path::{Path, PathBuf, Component}; +use std::path::{Component, Path, PathBuf}; +use crate::store::structs; -pub fn to_repo_relative(path: &PathBuf, root: &PathBuf) -> PathBuf { - path.strip_prefix(root).unwrap().to_path_buf() +pub fn to_repo_relative(path: &PathBuf) -> PathBuf { + let root = structs::get_repo_root(); + path.strip_prefix(&root) + .expect(&format!( + "Expect '{}' to be in the repo '{}'", + path.display(), + root.display() + )) + .to_path_buf() } pub fn to_string(path: &PathBuf) -> String { @@ -18,9 +26,7 @@ pub fn to_string(path: &PathBuf) -> String { /// This function ensures a given path ending with '/' still /// ends with '/' after normalization. pub fn normalize_path>(path: P) -> PathBuf { - let ends_with_slash = path.as_ref() - .to_str() - .map_or(false, |s| s.ends_with('/')); + let ends_with_slash = path.as_ref().to_str().map_or(false, |s| s.ends_with('/')); let mut normalized = PathBuf::new(); for component in path.as_ref().components() { match &component { diff --git a/src/utils/tests.rs b/src/utils/tests.rs new file mode 100644 index 0000000..7edab7a --- /dev/null +++ b/src/utils/tests.rs @@ -0,0 +1,15 @@ +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() +}