Make --ignore a b c work with directories and files

This commit is contained in:
Mark 2023-11-04 15:44:22 +01:00
parent e8e5b363ff
commit 7595d2482c
2 changed files with 16 additions and 26 deletions

View File

@ -17,7 +17,7 @@ pub struct Args {
/// directories to ignore. /// directories to ignore.
/// can be paths relative to <source> (like backups/) or paths starting with <source> (like my_source/backups/). /// 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. /// if <index> starts with <source>, it is automatically ignored and doesn't need to be specified.
#[arg(long)] #[arg(long, num_args(0..))]
pub ignore: Vec<PathBuf>, pub ignore: Vec<PathBuf>,
/// don't ask for confirmation, just apply the changes. /// don't ask for confirmation, just apply the changes.
#[arg(long)] #[arg(long)]

View File

@ -5,19 +5,19 @@ use crate::{indexchanges::IndexChange, indexfile::IndexFile};
pub fn perform_index_diff<'a>( pub fn perform_index_diff<'a>(
source: &Path, source: &Path,
index: &'a Path, index: &'a Path,
mut ignore_subdirs: Vec<&'a Path>, mut ignore_paths: Vec<&'a Path>,
) -> io::Result<Vec<IndexChange>> { ) -> io::Result<Vec<IndexChange>> {
let mut changes = Vec::new(); let mut changes = Vec::new();
if let Ok(inner_index) = index.strip_prefix(source) { if let Ok(inner_index) = index.strip_prefix(source) {
eprintln!("[info] source contains index, but index will not be part of the backup."); eprintln!("[info] source contains index, but index will not be part of the backup.");
ignore_subdirs.push(inner_index); ignore_paths.push(inner_index);
} }
rec( rec(
source.as_ref(), source.as_ref(),
Path::new(""), Path::new(""),
index, index,
&mut changes, &mut changes,
&ignore_subdirs, &ignore_paths,
)?; )?;
Ok(changes) Ok(changes)
} }
@ -30,15 +30,8 @@ fn rec(
index_files: &Path, index_files: &Path,
// 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? ignore_paths: &Vec<&Path>,
ignore_subdirs: &Vec<&Path>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
for ii in ignore_subdirs {
if rel_path.starts_with(ii) {
return Ok(());
}
}
// used to find removals // used to find removals
let index_rel_path = index_files.join(rel_path); let index_rel_path = index_files.join(rel_path);
let mut index_entries = match fs::read_dir(&index_rel_path) { let mut index_entries = match fs::read_dir(&index_rel_path) {
@ -57,33 +50,30 @@ fn rec(
// find changes/adds // find changes/adds
for entry in source_files { for entry in source_files {
let entry = entry?; let entry = entry?;
let rel_path = rel_path.join(entry.file_name());
// ignore entries
if ignore_paths.iter().any(|ii| &rel_path == ii) {
continue;
}
let metadata = entry.metadata()?; let metadata = entry.metadata()?;
let in_index_and_is_dir = index_entries.remove(&entry.file_name()); let in_index_and_is_dir = index_entries.remove(&entry.file_name());
if metadata.is_dir() { if metadata.is_dir() {
if let Some(false) = in_index_and_is_dir { if let Some(false) = in_index_and_is_dir {
// is dir, but was file -> remove file // is dir, but was file -> remove file
changes.push(IndexChange::RemoveFile(rel_path.join(entry.file_name()))); changes.push(IndexChange::RemoveFile(rel_path.clone()));
} }
rec( rec(source, &rel_path, index_files, changes, ignore_paths)?;
source,
&rel_path.join(entry.file_name()),
index_files,
changes,
ignore_subdirs,
)?;
} else { } else {
if let Some(true) = in_index_and_is_dir { if let Some(true) = in_index_and_is_dir {
// is file, but was dir -> remove dir // is file, but was dir -> remove dir
changes.push(IndexChange::RemoveDir(rel_path.join(entry.file_name()))); changes.push(IndexChange::RemoveDir(rel_path.clone()));
} }
let newif = IndexFile::new_from_metadata(&metadata); let newif = IndexFile::new_from_metadata(&metadata);
let oldif = IndexFile::from_path(&index_files.join(rel_path).join(entry.file_name())); let oldif = IndexFile::from_path(&index_files.join(&rel_path));
match oldif { match oldif {
Ok(Ok(oldif)) if oldif == newif => {} Ok(Ok(oldif)) if oldif == newif => {}
_ => changes.push(IndexChange::AddFile( _ => changes.push(IndexChange::AddFile(rel_path, newif)),
rel_path.join(entry.file_name()),
newif,
)),
} }
} }
} }