add --ignore

This commit is contained in:
Mark 2023-11-04 15:11:20 +01:00
parent d1cc067bef
commit e8e5b363ff
4 changed files with 52 additions and 18 deletions

0
Cargo.toml Normal file → Executable file
View File

View File

@ -14,4 +14,12 @@ pub struct Args {
/// where your backup will be stored /// where your backup will be stored
#[arg()] #[arg()]
pub target: Option<PathBuf>, pub target: Option<PathBuf>,
/// directories to ignore.
/// can be paths relative to <source> (like backups/) or paths starting with <source> (like my_source/backups/).
/// if <index> starts with <source>, it is automatically ignored and doesn't need to be specified.
#[arg(long)]
pub ignore: Vec<PathBuf>,
/// don't ask for confirmation, just apply the changes.
#[arg(long)]
pub noconfirm: bool,
} }

View File

@ -19,7 +19,14 @@ fn main() {
let args = args::Args::parse(); let args = args::Args::parse();
// index diff // index diff
eprintln!("performing index diff..."); eprintln!("performing index diff...");
let changes = match perform_index_diff(&args.source, &args.index) { let source = &args.source;
let index = &args.index;
let ignore_subdirs = args
.ignore
.iter()
.map(|path| path.strip_prefix(source).unwrap_or(path))
.collect();
let changes = match perform_index_diff(source, index, ignore_subdirs) {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
eprintln!("Failed to generate index diff:\n {e}"); eprintln!("Failed to generate index diff:\n {e}");
@ -44,12 +51,25 @@ fn main() {
eprintln!(" + add/update file"); eprintln!(" + add/update file");
eprintln!(" - remove file"); eprintln!(" - remove file");
eprintln!(" [-] remove directory (and all contents!)"); eprintln!(" [-] remove directory (and all contents!)");
eprintln!("Press Enter to to apply these actions."); // apply changes after confirming
if !args.noconfirm {
let mut line = String::new();
loop {
if args.target.is_none() { if args.target.is_none() {
eprintln!("[WARN] You didn't set a `target` directory!\n[WARN] Be careful not to update your index without actually applying the changes to the `target` filesystem!"); eprintln!("[WARN] You didn't set a `target` directory!\n[WARN] Be careful not to update your index without actually applying the changes to the `target` filesystem!\nType 'Ok' and press enter to continue.");
} else {
eprintln!("Exclude unwanted directories/files using --ignore,\nor press enter to apply the changes.");
}
line.clear();
std::io::stdin().read_line(&mut line).unwrap();
let line = line.trim().to_lowercase();
if line == "exit" {
return;
} else if args.target.is_some() || line == "ok" {
break;
}
}
} }
// apply changes
if std::io::stdin().read_line(&mut String::new()).is_ok() {
match apply_indexchanges(&args.source, &args.index, &args.target, &changes) { match apply_indexchanges(&args.source, &args.index, &args.target, &changes) {
Ok(()) => {} Ok(()) => {}
Err(e) => { Err(e) => {
@ -58,5 +78,4 @@ fn main() {
} }
} }
} }
}
} }

View File

@ -2,14 +2,22 @@ use std::{collections::HashMap, fs, io, path::Path};
use crate::{indexchanges::IndexChange, indexfile::IndexFile}; use crate::{indexchanges::IndexChange, indexfile::IndexFile};
pub fn perform_index_diff(source: &Path, index: &Path) -> io::Result<Vec<IndexChange>> { pub fn perform_index_diff<'a>(
source: &Path,
index: &'a Path,
mut ignore_subdirs: Vec<&'a Path>,
) -> io::Result<Vec<IndexChange>> {
let mut changes = Vec::new(); let mut changes = Vec::new();
if let Ok(inner_index) = index.strip_prefix(source) {
eprintln!("[info] source contains index, but index will not be part of the backup.");
ignore_subdirs.push(inner_index);
}
rec( rec(
source.as_ref(), source.as_ref(),
Path::new(""), Path::new(""),
index, index,
&mut changes, &mut changes,
index.strip_prefix(source).ok(), &ignore_subdirs,
)?; )?;
Ok(changes) Ok(changes)
} }
@ -23,11 +31,10 @@ fn rec(
// list of changes to be made // list of changes to be made
changes: &mut Vec<IndexChange>, changes: &mut Vec<IndexChange>,
// if the index is part of `source`, where exactly is it? // if the index is part of `source`, where exactly is it?
inner_index: Option<&Path>, ignore_subdirs: &Vec<&Path>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
if let Some(ii) = &inner_index { for ii in ignore_subdirs {
if rel_path.starts_with(ii) { if rel_path.starts_with(ii) {
eprintln!("[info] source contains index, but index will not be part of the backup.");
return Ok(()); return Ok(());
} }
} }
@ -62,7 +69,7 @@ fn rec(
&rel_path.join(entry.file_name()), &rel_path.join(entry.file_name()),
index_files, index_files,
changes, changes,
inner_index, ignore_subdirs,
)?; )?;
} else { } else {
if let Some(true) = in_index_and_is_dir { if let Some(true) = in_index_and_is_dir {