diff --git a/changelog/new.txt b/changelog/new.txt index fdebaec..200fa7f 100644 --- a/changelog/new.txt +++ b/changelog/new.txt @@ -5,6 +5,7 @@ Breaking changes: Bugs fixed: - restore: Warm-up options given by the command line didn't work. This has been fixed. - backup showed 1 dir as changed when backing up without parent. This has been fixed. +- diff: The options --no-atime and --ignore-devid had no effect and are now removed. New features: - backup: Backing up (small) files is now much more parallelized. diff --git a/src/backend/ignore.rs b/src/backend/ignore.rs index f536e38..1a09d30 100644 --- a/src/backend/ignore.rs +++ b/src/backend/ignore.rs @@ -25,8 +25,7 @@ use super::{Node, ReadSource, ReadSourceEntry, ReadSourceOpen}; pub struct LocalSource { builder: WalkBuilder, walker: Walk, - with_atime: bool, - ignore_devid: bool, + save_opts: LocalSourceSaveOptions, #[cfg(not(windows))] cache: UsersCache, } @@ -34,7 +33,7 @@ pub struct LocalSource { #[serde_as] #[derive(Default, Clone, Parser, Deserialize, Merge)] #[serde(default, rename_all = "kebab-case", deny_unknown_fields)] -pub struct LocalSourceOptions { +pub struct LocalSourceSaveOptions { /// Save access time for files and directories #[clap(long)] #[merge(strategy = merge::bool::overwrite_false)] @@ -44,7 +43,12 @@ pub struct LocalSourceOptions { #[clap(long)] #[merge(strategy = merge::bool::overwrite_false)] ignore_devid: bool, +} +#[serde_as] +#[derive(Default, Clone, Parser, Deserialize, Merge)] +#[serde(default, rename_all = "kebab-case", deny_unknown_fields)] +pub struct LocalSourceFilterOptions { /// Glob pattern to exclude/include (can be specified multiple times) #[clap(long, help_heading = "Exclude options")] #[merge(strategy = merge::vec::overwrite_empty)] @@ -87,7 +91,11 @@ pub struct LocalSourceOptions { } impl LocalSource { - pub fn new(opts: LocalSourceOptions, backup_paths: &[impl AsRef]) -> Result { + pub fn new( + save_opts: LocalSourceSaveOptions, + filter_opts: LocalSourceFilterOptions, + backup_paths: &[impl AsRef], + ) -> Result { let mut walk_builder = WalkBuilder::new(&backup_paths[0]); for path in &backup_paths[1..] { @@ -96,22 +104,22 @@ impl LocalSource { let mut override_builder = OverrideBuilder::new("/"); - for g in opts.glob { + for g in filter_opts.glob { override_builder.add(&g)?; } - for file in opts.glob_file { + for file in filter_opts.glob_file { for line in std::fs::read_to_string(file)?.lines() { override_builder.add(line)?; } } override_builder.case_insensitive(true)?; - for g in opts.iglob { + for g in filter_opts.iglob { override_builder.add(&g)?; } - for file in opts.iglob_file { + for file in filter_opts.iglob_file { for line in std::fs::read_to_string(file)?.lines() { override_builder.add(line)?; } @@ -121,16 +129,16 @@ impl LocalSource { .follow_links(false) .hidden(false) .ignore(false) - .git_ignore(opts.git_ignore) + .git_ignore(filter_opts.git_ignore) .sort_by_file_path(Path::cmp) - .same_file_system(opts.one_file_system) - .max_filesize(opts.exclude_larger_than.map(|s| s.as_u64())) + .same_file_system(filter_opts.one_file_system) + .max_filesize(filter_opts.exclude_larger_than.map(|s| s.as_u64())) .overrides(override_builder.build()?); - if !opts.exclude_if_present.is_empty() { + if !filter_opts.exclude_if_present.is_empty() { walk_builder.filter_entry(move |entry| match entry.file_type() { Some(tpe) if tpe.is_dir() => { - for file in &opts.exclude_if_present { + for file in &filter_opts.exclude_if_present { if entry.path().join(file).exists() { return false; } @@ -147,8 +155,7 @@ impl LocalSource { Ok(Self { builder, walker, - with_atime: opts.with_atime, - ignore_devid: opts.ignore_devid, + save_opts, #[cfg(not(windows))] cache: UsersCache::new(), }) @@ -201,8 +208,8 @@ impl Iterator for LocalSource { .map(|e| { map_entry( e?, - self.with_atime, - self.ignore_devid, + self.save_opts.with_atime, + self.save_opts.ignore_devid, #[cfg(not(windows))] &self.cache, ) diff --git a/src/commands/backup.rs b/src/commands/backup.rs index 91ad0d4..6fb82c5 100644 --- a/src/commands/backup.rs +++ b/src/commands/backup.rs @@ -12,7 +12,9 @@ use toml::Value; use super::{bytes, progress_bytes, progress_counter, GlobalOpts, RusticConfig}; use crate::archiver::Archiver; -use crate::backend::{DryRunBackend, LocalSource, LocalSourceOptions, StdinSource}; +use crate::backend::{ + DryRunBackend, LocalSource, LocalSourceFilterOptions, LocalSourceSaveOptions, StdinSource, +}; use crate::index::IndexBackend; use crate::repofile::{ PathList, SnapshotFile, SnapshotGroup, SnapshotGroupCriterion, SnapshotOptions, @@ -86,7 +88,11 @@ pub(super) struct Opts { #[clap(flatten)] #[serde(flatten)] - ignore_opts: LocalSourceOptions, + ignore_save_opts: LocalSourceSaveOptions, + + #[clap(flatten)] + #[serde(flatten)] + ignore_filter_opts: LocalSourceFilterOptions, #[clap(flatten, next_help_heading = "Snapshot options")] #[serde(flatten)] @@ -240,7 +246,11 @@ pub(super) fn execute( let src = StdinSource::new(path.clone())?; archiver.archive(src, path, as_path.as_ref(), &p)? } else { - let src = LocalSource::new(opts.ignore_opts.clone(), &backup_path)?; + let src = LocalSource::new( + opts.ignore_save_opts.clone(), + opts.ignore_filter_opts.clone(), + &backup_path, + )?; archiver.archive(src, &backup_path[0], as_path.as_ref(), &p)? }; diff --git a/src/commands/diff.rs b/src/commands/diff.rs index 30d8b6e..e812a8b 100644 --- a/src/commands/diff.rs +++ b/src/commands/diff.rs @@ -5,7 +5,10 @@ use anyhow::{anyhow, bail, Context, Result}; use clap::Parser; use super::{progress_counter, RusticConfig}; -use crate::backend::{LocalDestination, LocalSource, LocalSourceOptions, ReadSourceEntry}; +use crate::backend::{ + LocalDestination, LocalSource, LocalSourceFilterOptions, LocalSourceSaveOptions, + ReadSourceEntry, +}; use crate::blob::{Node, NodeStreamer, NodeType, Tree}; use crate::commands::helpers::progress_spinner; use crate::crypto::hash; @@ -32,7 +35,7 @@ pub(super) struct Opts { no_content: bool, #[clap(flatten)] - ignore_opts: LocalSourceOptions, + ignore_opts: LocalSourceFilterOptions, #[clap( flatten, @@ -88,7 +91,12 @@ pub(super) fn execute( .metadata() .with_context(|| format!("Error accessing {path2:?}"))? .is_dir(); - let src = LocalSource::new(opts.ignore_opts, &[&path2])?.map(|item| { + let src = LocalSource::new( + LocalSourceSaveOptions::default(), + opts.ignore_opts, + &[&path2], + )? + .map(|item| { let ReadSourceEntry { path, node, .. } = item?; let path = if is_dir { // remove given path prefix for dirs as local path