feat(reset): introduce reset and fix ROOT_PATH

This commit is contained in:
grimhilt 2024-09-08 17:59:22 +02:00
parent bc6a23b76b
commit baeef1a33a
15 changed files with 178 additions and 52 deletions

View File

@ -1,3 +1,4 @@
pub mod add;
pub mod init;
pub mod status;
pub mod reset;

View File

@ -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
*/
}

11
src/commands/reset.rs Normal file
View File

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

View File

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

View File

@ -1,6 +1,7 @@
use std::env;
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use crate::store::structs;
///
/// # Parameters

View File

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

View File

@ -9,6 +9,8 @@ pub struct Ignorer {
use_nsignore: bool,
/// Nsignore's rules
rules: OnceLock<Vec<String>>,
/// Path that have been ignored by should_ignore function
pub ignored_paths: Vec<PathBuf>,
childs: Option<Vec<Box<Ignorer>>>,
}
@ -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
}
}

View File

@ -27,9 +27,9 @@ fn sort_paths_hierarchically(paths: &mut Vec<PathBuf>) {
}
#[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<IndexedObj> {
&self.indexed_objs
}
fn is_indexed(&self, obj: &IndexedObj) -> bool {
self.indexed_objs
.iter()

View File

@ -5,21 +5,6 @@ use crate::store::{
use std::path::PathBuf;
use std::sync::OnceLock;
pub static REPO_ROOT: OnceLock<PathBuf> = 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<Box<NsObject>>;
pub struct NsObject {

View File

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

View File

@ -1,3 +1,4 @@
pub mod add;
pub mod init;
pub mod reset;
pub mod status;

17
src/subcommands/reset.rs Normal file
View File

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

View File

@ -1 +1,2 @@
pub mod path;
pub mod tests;

View File

@ -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<P: AsRef<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 {

15
src/utils/tests.rs Normal file
View File

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