From 6566b426979b3caa222d415559457359d35c089a Mon Sep 17 00:00:00 2001 From: Mark <> Date: Sat, 29 Jun 2024 15:36:48 +0200 Subject: [PATCH] improve messages, ... --- src/args.rs | 1 + src/config.rs | 8 +++++--- src/main.rs | 7 +++++-- src/update_index.rs | 39 ++++++++++++++++++++++++++++++--------- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/args.rs b/src/args.rs index 1880530..128c7db 100755 --- a/src/args.rs +++ b/src/args.rs @@ -20,6 +20,7 @@ pub struct Args { #[arg(long)] pub noconfirm: bool, + /// the file in which you specified what files/directories should be ignored #[arg(long)] pub ignore: Option, diff --git a/src/config.rs b/src/config.rs index bac2411..37653cb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,7 +7,7 @@ use std::{ #[derive(Clone, Copy, Debug)] pub struct FsEntry<'a> { pub path: &'a Path, - pub is_directory: bool, + pub is_directory: Option, } #[derive(Debug)] @@ -73,12 +73,14 @@ impl Specifier { match self { Self::Except(inner) => inner.matches(entry).map(std::ops::Not::not), Self::Entries(path) => path.matches(entry.path).then_some(true), - Self::Files(path) => (!entry.is_directory && path.matches(entry.path)).then_some(true), + Self::Files(path) => { + (entry.is_directory == Some(false) && path.matches(entry.path)).then_some(true) + } Self::InDir { dir, inner } => { if inner.0.is_empty() { // this has no inner things, so we just check for this directory // if this is a directory and it matches, then return true - (entry.is_directory && dir.matches(entry.path)).then_some(true) + (entry.is_directory == Some(true) && dir.matches(entry.path)).then_some(true) } else { // this has inner things, so, for every matching parent, // get the relative path (by removing the parent), ... diff --git a/src/main.rs b/src/main.rs index ec29cd5..05021b4 100755 --- a/src/main.rs +++ b/src/main.rs @@ -79,8 +79,11 @@ fn main() { &args.settings, ) { Ok(c) => c, - Err(e) => { - eprintln!("Failed to generate index diff:\n {e}"); + Err((what, path, err)) => { + eprintln!( + "Failed to generate index diff:\n {what}\n {}\n {err}", + path.to_string_lossy() + ); exit(EXIT_DIFF_FAILED as _); } }; diff --git a/src/update_index.rs b/src/update_index.rs index 03e1bbb..7e93ded 100755 --- a/src/update_index.rs +++ b/src/update_index.rs @@ -1,4 +1,8 @@ -use std::{collections::HashMap, fs, io, path::Path}; +use std::{ + collections::HashMap, + fs, io, + path::{Path, PathBuf}, +}; use clap::Args; @@ -33,7 +37,7 @@ pub fn perform_index_diff<'a>( target: Option<&'a Path>, mut ignore: Ignore, settings: &Settings, -) -> io::Result> { +) -> Result, (String, PathBuf, io::Error)> { let mut changes = Vec::new(); if let Ok(inner_index) = index.strip_prefix(source) { eprintln!("[info] source contains index at {inner_index:?}, but index will not be part of the backup."); @@ -72,7 +76,7 @@ fn rec( changes: &mut Vec, ignore: &Ignore, settings: &Settings, -) -> Result<(), io::Error> { +) -> Result<(), (String, PathBuf, io::Error)> { // used to find removals let index_rel_path = index_files.join(rel_path); let mut index_entries = match fs::read_dir(&index_rel_path) { @@ -83,26 +87,43 @@ fn rec( Ok(e) => e .into_iter() .filter_map(|v| v.ok()) - .map(|v| Ok((v.file_name(), v.file_type()?.is_dir()))) - .collect::>()?, + .map(|v| { + Ok(( + v.file_name(), + v.file_type() + .map_err(|e| ("getting file type".to_owned(), v.path(), e))? + .is_dir(), + )) + }) + .collect::>()?, }; // compare source files with index - let source_files = fs::read_dir(source.join(rel_path))?.collect::>(); + let source_files_path = source.join(rel_path); + let source_files = fs::read_dir(&source_files_path) + .map_err(|e| ("getting entries".to_owned(), source_files_path.clone(), e))? + .collect::>(); // find changes/adds for entry in source_files { - let entry = entry?; + let entry = entry.map_err(|e| { + ( + "error with an entry within this directory".to_owned(), + source_files_path.clone(), + e, + ) + })?; let rel_path = rel_path.join(entry.file_name()); - let metadata = entry.metadata()?; + let metadata = entry.metadata(); // ignore entries let fs_entry = FsEntry { path: &rel_path, - is_directory: metadata.is_dir(), + is_directory: metadata.as_ref().ok().map(|v| v.is_dir()), }; if ignore.matches_or_default(&fs_entry) { continue; } + let metadata = metadata.map_err(|e| ("getting metadata (you have to ignore this using a * pattern instead of + or /, because we don't know if it's a directory or not)".to_owned(), entry.path(), e))?; let in_index_and_is_dir = index_entries.remove(&entry.file_name()); if metadata.is_dir() { if let Some(false) = in_index_and_is_dir {