feat(add): start add logic and ignorer

This commit is contained in:
grimhilt 2024-08-31 23:10:06 +02:00
parent 2364cadfd5
commit fb57bd6565
10 changed files with 211 additions and 9 deletions

View File

@ -1 +1,2 @@
pub mod add;
pub mod init;

59
src/commands/add.rs Normal file
View File

@ -0,0 +1,59 @@
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 glob::glob;
use std::path::{Path, PathBuf};
pub struct AddArgs {
/// List of files/dirs to add
pub files: Vec<String>,
/// Allow ignored files
pub force: bool,
/// Select all files
pub all: bool,
}
pub fn exec(args: AddArgs, config: Config) {
// Init ignorer
let mut ignorer = Ignorer::new(config.get_root_unsafe());
ignorer.active_nsignore(!args.force);
if args.all {
return add_dir(config.get_root_unsafe(), &mut ignorer);
}
/*
for all files
if globbing
take all match glob nextsyncignore
else
if dir
add dir
add all childs with nextsyncignore
else
add files
*/
}
/// Add all files in a directory
///
/// # Parameters
/// * `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() {
continue;
}
if is dir
add_dir(new_dir, force)
else
}
*/
}

View File

@ -1,5 +1,5 @@
use crate::config::config::Config;
use std::fs::{create_dir_all, DirBuilder, File};
use std::fs::{DirBuilder, File};
use std::path::PathBuf;
pub struct InitArgs {}
@ -32,7 +32,7 @@ pub fn exec(_: InitArgs, config: Config) {
}
let mut binding = DirBuilder::new();
let mut builder = binding.recursive(true);
let builder = binding.recursive(true);
for dir in &["objects", "refs"] {
path.push(dir);

View File

@ -1,20 +1,58 @@
use std::env;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
///
/// # Parameters
/// * `execution_path`: path of the command (directory arg) or current path
/// * `root`: path of the repo
pub struct Config {
pub execution_path: PathBuf,
root: OnceLock<Option<PathBuf>>,
}
impl Config {
pub fn new(exec_path: Option<&String>) -> Self {
pub fn new() -> Self {
Config {
execution_path: match exec_path {
Some(path) => PathBuf::from(path),
None => PathBuf::from(env::current_dir().unwrap()),
execution_path: PathBuf::from(env::current_dir().unwrap()),
root: OnceLock::new(),
}
}
pub fn from(exec_path: Option<&String>) -> Self {
match exec_path {
Some(path) => Config {
execution_path: PathBuf::from(path),
root: OnceLock::new(),
},
None => Config::new(),
}
}
pub fn get_root(&self) -> &Option<PathBuf> {
self.root.get_or_init(|| {
let mut path = self.execution_path.clone();
let root = loop {
path.push(".nextsync");
if path.exists() {
path.pop();
break Some(path);
}
path.pop();
path.pop();
if path == Path::new("/") {
break None;
}
};
root
})
}
pub fn get_root_unsafe(&self) -> &PathBuf {
match self.get_root() {
Some(path) => path,
None => panic!("fatal: not a nextsync repository (or any parent up to mount point /)"),
}
}
}

View File

@ -2,6 +2,7 @@ use clap::Command;
mod commands;
mod config;
mod store;
mod subcommands;
fn main() {
@ -9,13 +10,14 @@ fn main() {
.version("1.0")
.author("grimhilt")
.about("A git-line command line tool to interact with nextcloud")
.subcommands([subcommands::init::create()]);
.subcommands([subcommands::init::create(), subcommands::add::create()]);
// .setting(clap::AppSettings::SubcommandRequiredElseHelp);
let matches = app.get_matches();
match matches.subcommand() {
Some(("init", args)) => subcommands::init::handler(args),
Some(("add", args)) => subcommands::add::handler(args),
Some((_, _)) => {}
None => {}
};

2
src/store.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod ignorer;
pub mod nsignore;

53
src/store/ignorer.rs Normal file
View File

@ -0,0 +1,53 @@
use crate::store::nsignore::{get_nsignore_file, get_nsignore_rules, is_file_ignored};
use std::path::PathBuf;
use std::sync::OnceLock;
pub struct Ignorer {
/// Path of this level
path: PathBuf,
/// Should it use the nextsyncignore file
use_nsignore: bool,
/// Nsignore's rules
rules: OnceLock<Vec<String>>,
childs: Option<Vec<Box<Ignorer>>>,
}
impl Ignorer {
pub fn new(path: &PathBuf) -> Self {
Ignorer {
path: path.to_path_buf(),
use_nsignore: true,
rules: OnceLock::new(),
childs: None,
}
}
pub fn active_nsignore(&mut self, active: bool) {
self.use_nsignore = active;
}
fn get_rules(&mut self) -> &Vec<String> {
self.rules
.get_or_init(|| match get_nsignore_file(&self.path) {
Some(nsignore_path) => get_nsignore_rules(&nsignore_path),
None => Vec::new(),
})
}
/// Returns whether a file/dir is ignored or not
///
/// * `path`:
fn is_ignored(&mut self, path: PathBuf) -> bool {
is_file_ignored(path.to_str().unwrap(), self.get_rules())
}
/// Returns whether a file/dir should be ignored by the program or not
///
/// This takes advantage of the `use_nsignore` variable set by
/// `active_nsignore`.
///
/// * `path`:
pub fn should_ignore(&mut self, path: PathBuf) -> bool {
self.use_nsignore && self.is_ignored(path)
}
}

View File

@ -1 +1,2 @@
pub mod add;
pub mod init;

46
src/subcommands/add.rs Normal file
View File

@ -0,0 +1,46 @@
use clap::{Arg, ArgAction, ArgMatches, Command};
use crate::commands;
use crate::commands::add::AddArgs;
use crate::config::config::Config;
pub fn create() -> Command {
Command::new("add")
.arg(
Arg::new("files")
.required_unless_present("all")
.conflicts_with("all")
.num_args(1..)
.value_name("FILE")
.help("Files to add"),
)
.arg(
Arg::new("force")
.short('f')
.long("force")
.action(ArgAction::SetTrue)
.help("Allow adding otherwise ignored files."),
)
.arg(
Arg::new("all")
.short('A')
.long("all")
.action(ArgAction::SetTrue)
.help("This adds, modifies, and removes index entries to match the working tree"),
)
.about("Add changes to the index")
}
pub fn handler(args: &ArgMatches) {
commands::add::exec(
AddArgs {
files: match args.get_many::<String>("files") {
None => vec![],
Some(vals) => vals.map(|s| s.to_string()).collect(),
},
force: *args.get_one::<bool>("force").unwrap(),
all: *args.get_one::<bool>("all").unwrap(),
},
Config::new(),
);
}

View File

@ -16,5 +16,5 @@ pub fn create() -> Command {
pub fn handler(args: &ArgMatches) {
let exec_dir = args.get_one::<String>("directory");
commands::init::exec(commands::init::InitArgs {}, Config::new(exec_dir));
commands::init::exec(commands::init::InitArgs {}, Config::from(exec_dir));
}