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,6 +61,20 @@ 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

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(
}
};
let local_obj = Obj::from_local_path(&entry.path().into());
if entry.path().is_dir() {
if entry.path().ends_with(".nextsync") {
continue;
}
let local_obj = Obj::from_local_path(&entry.path().into());
if entry.path().is_dir() {
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()
}