nextsync-rust/src/commands/add.rs
2024-03-31 19:23:32 +02:00

165 lines
5.0 KiB
Rust

use std::io::Write;
use std::path::{Path, PathBuf};
use clap::Values;
use glob::glob;
use crate::store::{self, object::Object};
use crate::utils::{self, path};
use crate::store::object::object::{Obj, ObjMethods};
use crate::utils::nextsyncignore::{self, ignore_file};
use crate::utils::path::{normalize_relative, repo_root, path_buf_to_string};
pub struct AddArgs<'a> {
pub files: Option<Values<'a>>,
pub force: bool,
pub all: bool,
}
// todo match deleted files
pub fn add(args: AddArgs) {
let mut pattern: String;
let file_vec: Vec<&str> = match args.all {
true => {
pattern = path_buf_to_string(repo_root());
pattern.push_str("/*");
vec![&pattern]
},
false => args.files.unwrap().collect(),
};
let mut added_files: Vec<String> = vec![];
let mut ignored_f = vec![];
let rules = nextsyncignore::get_rules();
for file in file_vec {
dbg!(&file);
let f = match normalize_relative(file) {
Ok(f) => f,
Err(err) => {
eprintln!("err: {} {}", file, err);
continue;
}
};
let path = repo_root().join(Path::new(&f));
match path.exists() {
true => {
add_entry(path, args.force, &mut added_files, rules.clone(), &mut ignored_f);
},
false => {
if Object::new(path.to_str().unwrap()).exists() {
// object is deleted so not present but can still be added for deletion
added_files.push(String::from(f));
} else {
// try globbing if nothing has been found
for entry in try_globbing(path) {
add_entry(entry, args.force, &mut added_files, rules.clone(), &mut ignored_f);
}
}
}
}
}
print_ignored_files(ignored_f);
write_added_files(added_files);
}
fn add_entry(entry: PathBuf, force: bool, added_files: &mut Vec<String>, rules: Vec<String>, ignored_f: &mut Vec<String>) {
// ignore nextsync config files
if path::is_nextsync_config(entry.clone()) {
return;
}
// check if the file must be ignored
if !force && ignore_file(&path_buf_to_string(entry.clone()), rules, ignored_f) {
return;
}
// add the parent if there is one and it is not already created
add_parent(entry.clone(), added_files);
added_files.push(path_buf_to_string(entry.strip_prefix(repo_root()).unwrap().to_path_buf()));
if entry.is_dir() {
add_folder_content(entry.to_path_buf(), added_files);
}
}
fn add_parent(entry: PathBuf, added_files: &mut Vec<String>) {
let test_parent = entry.strip_prefix(repo_root()).unwrap().parent();
if test_parent.is_none() || test_parent.unwrap() == PathBuf::new() {
return;
}
let parent = entry.parent().unwrap();
if !Obj::from_path(parent).exists_on_remote() {
add_parent(parent.to_path_buf(), added_files);
added_files.push(path_buf_to_string(parent.strip_prefix(repo_root()).unwrap().to_path_buf()));
}
}
fn print_ignored_files(ignored_files: Vec<String>) {
if ignored_files.len() > 0 {
// todo multiple nextsyncignore
println!("The following paths are ignored by your .nextsyncignore file:");
for file in ignored_files {
println!("{}", file);
}
}
}
fn write_added_files(added_files: Vec<String>) {
let mut index_file = store::index::open();
for file in added_files {
if store::index::alread_added(file.clone()) {
continue;
}
match writeln!(index_file, "{}", file) {
Ok(()) => (),
Err(err) => eprintln!("{}", err),
}
}
drop(index_file);
}
fn try_globbing(path: PathBuf) -> Vec<PathBuf> {
let mut paths: Vec<PathBuf> = vec![];
if let Ok(entries) = glob(path.to_str().unwrap()) {
for entry in entries {
match entry {
Ok(ppath) => paths.push(ppath),
Err(e) => {
eprintln!("err: {} incorrect pattern ({})", path.display(), e);
}
}
}
} else {
eprintln!("err: {} is not something you can add.", path.to_str().unwrap());
}
return paths;
}
fn add_folder_content(path: PathBuf, added_files: &mut Vec<String>) {
// todo check for changes
let mut folders: Vec<PathBuf> = vec![];
folders.push(path);
while let Some(folder) = folders.pop() {
if let Ok(entries) = utils::read::read_folder(folder.clone()) {
for entry in entries {
let path_entry = PathBuf::from(entry);
if !path::is_nextsync_config(path_entry.clone())
{
if path_entry.is_dir() {
folders.push(path_entry.clone());
}
added_files.push(path_buf_to_string(path_entry.strip_prefix(repo_root()).unwrap().to_path_buf()));
}
}
}
}
}