From bec4d7cbb90259d5d2f5856cd5f093cff93e8a17 Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Mon, 26 Jun 2023 09:04:56 +0200 Subject: [PATCH 1/2] fix rustfmt --- crates/rustic_core/src/repository.rs | 2 +- src/commands/init.rs | 9 +++++---- src/commands/key.rs | 9 +++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/rustic_core/src/repository.rs b/crates/rustic_core/src/repository.rs index 1eb5b4367..de8cf31ae 100644 --- a/crates/rustic_core/src/repository.rs +++ b/crates/rustic_core/src/repository.rs @@ -9,6 +9,7 @@ use std::{ use bytes::Bytes; use log::{debug, error, info}; +use dialoguer::Password; use nom::{ branch::alt, bytes::complete::{is_not, tag}, @@ -18,7 +19,6 @@ use nom::{ sequence::delimited, IResult, }; -use dialoguer::Password; use serde_with::{serde_as, DisplayFromStr}; diff --git a/src/commands/init.rs b/src/commands/init.rs index 350637dec..24700349e 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -80,10 +80,11 @@ pub(crate) fn save_config( let key = Key::new(); let pass = password.map_or_else( - || match Password::new().with_prompt("enter password for new key") - .allow_empty_password(true) - .with_confirmation("confirm password", "passwords do not match") - .interact() + || match Password::new() + .with_prompt("enter password for new key") + .allow_empty_password(true) + .with_confirmation("confirm password", "passwords do not match") + .interact() { Ok(it) => it, Err(err) => { diff --git a/src/commands/key.rs b/src/commands/key.rs index a544735b1..94607ab20 100644 --- a/src/commands/key.rs +++ b/src/commands/key.rs @@ -79,10 +79,11 @@ impl AddCmd { let key = repo.key; let pass = self.new_password_file.as_ref().map_or_else( - || match Password::new().with_prompt("enter password for new key") - .allow_empty_password(true) - .with_confirmation("confirm password", "passwords do not match") - .interact() + || match Password::new() + .with_prompt("enter password for new key") + .allow_empty_password(true) + .with_confirmation("confirm password", "passwords do not match") + .interact() { Ok(it) => it, Err(err) => { From 47a865c061bc7df4957c2a957acf6b608d0cf5d1 Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Mon, 26 Jun 2023 09:04:46 +0200 Subject: [PATCH 2/2] prune: Don't abort if time is unset for pack-to-delete --- changelog/new.txt | 2 ++ crates/rustic_core/src/commands/check.rs | 11 +++++--- crates/rustic_core/src/commands/prune.rs | 34 ++++++++++++++---------- crates/rustic_core/src/error.rs | 2 -- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/changelog/new.txt b/changelog/new.txt index e50807a37..7211335c3 100644 --- a/changelog/new.txt +++ b/changelog/new.txt @@ -3,6 +3,7 @@ Changes in version x.x.x: Breaking changes: Bugs fixed: +- prune did abort when no time was set for a pack-do-delete. This case is now handled correctly. New features: - New global configuration paths are available, located at /etc/rustic/*.toml or %PROGRAMDATA%/rustic/config/*.toml, depending on your platform. @@ -13,3 +14,4 @@ New features: - fix: wait for password-command to successfully exit, allowing to input something into the command, and read password from stdout. - repoinfo: Added new options --json, --only-files, --only-index - Creation of new keys now enforces confirmation of entered key. This helps to prevent mistype of passwords during the initial entry +- Check: Add check if time is set for packs-to-delete \ No newline at end of file diff --git a/crates/rustic_core/src/commands/check.rs b/crates/rustic_core/src/commands/check.rs index d354218e7..13977a76b 100644 --- a/crates/rustic_core/src/commands/check.rs +++ b/crates/rustic_core/src/commands/check.rs @@ -199,7 +199,7 @@ fn check_packs( IndexType::FullTrees }); - let mut process_pack = |p: IndexPack| { + let mut process_pack = |p: IndexPack, check_time: bool| { let blob_type = p.blob_type(); let pack_size = p.pack_size(); _ = packs.insert(p.id, pack_size); @@ -207,6 +207,11 @@ fn check_packs( _ = tree_packs.insert(p.id, pack_size); } + // Check if time is set _ + if check_time && p.time.is_none() { + error!("pack {}: No time is set! Run prune to correct this!", p.id); + } + // check offsests in index let mut expected_offset: u32 = 0; let mut blobs = p.blobs; @@ -234,10 +239,10 @@ fn check_packs( let index = index?.1; index_collector.extend(index.packs.clone()); for p in index.packs { - process_pack(p); + process_pack(p, false); } for p in index.packs_to_delete { - process_pack(p); + process_pack(p, true); } } diff --git a/crates/rustic_core/src/commands/prune.rs b/crates/rustic_core/src/commands/prune.rs index 3e22f2391..bfaa53cd9 100644 --- a/crates/rustic_core/src/commands/prune.rs +++ b/crates/rustic_core/src/commands/prune.rs @@ -2,7 +2,7 @@ /// App-local prelude includes `app_reader()`/`app_writer()`/`app_config()` /// accessors along with logging macros. Customize as you see fit. -use log::info; +use log::{info, warn}; use std::{ cmp::Ordering, @@ -279,6 +279,7 @@ enum PackToDo { Repack, MarkDelete, KeepMarked, + KeepMarkedAndCorrect, Recover, Delete, } @@ -370,7 +371,7 @@ impl PrunePack { stats.packs_to_delete.remove += 1; stats.size_to_delete.remove += u64::from(self.size); } - PackToDo::KeepMarked => { + PackToDo::KeepMarked | PackToDo::KeepMarkedAndCorrect => { stats.packs_to_delete.keep += 1; stats.size_to_delete.keep += u64::from(self.size); } @@ -571,15 +572,16 @@ impl PrunePlan { .push((pi, PartlyUsed, index_num, pack_num)); } } - (true, 0, _) => { - let local_date_time = - pack.time.ok_or(CommandErrorKind::NoTimeInPacksToDelete)?; - if self.time - local_date_time >= keep_delete { + (true, 0, _) => match pack.time { + Some(local_date_time) if self.time - local_date_time >= keep_delete => { pack.set_todo(PackToDo::Delete, &pi, &mut self.stats); - } else { - pack.set_todo(PackToDo::KeepMarked, &pi, &mut self.stats); } - } + None => { + warn!("pack to delete {}: no time set, this should not happen! Keeping this pack.", pack.id); + pack.set_todo(PackToDo::KeepMarkedAndCorrect, &pi, &mut self.stats); + } + Some(_) => pack.set_todo(PackToDo::KeepMarked, &pi, &mut self.stats), + }, (true, 1.., _) => { // needed blobs; mark this pack for recovery pack.set_todo(PackToDo::Recover, &pi, &mut self.stats); @@ -685,7 +687,10 @@ impl PrunePlan { PackToDo::Repack => { check_size()?; } - PackToDo::MarkDelete | PackToDo::Delete | PackToDo::KeepMarked => {} + PackToDo::MarkDelete + | PackToDo::Delete + | PackToDo::KeepMarked + | PackToDo::KeepMarkedAndCorrect => {} } } @@ -746,7 +751,6 @@ impl PrunePlan { opts: &PruneOpts, ) -> RusticResult<()> { repo.warm_up_wait(self.repack_packs().into_iter())?; - let be = &repo.dbe; let pb = &repo.pb; @@ -891,12 +895,14 @@ impl PrunePlan { indexer.write().unwrap().add_remove(pack)?; } } - PackToDo::KeepMarked => { + PackToDo::KeepMarked | PackToDo::KeepMarkedAndCorrect => { if opts.instant_delete { delete_pack(pack); } else { - // keep pack: add to new index - let pack = pack.into_index_pack(); + // keep pack: add to new index; keep the timestamp. + // Note the timestap shouldn't be None here, however if it is not not set, use the current time to heal the entry! + let time = pack.time.unwrap_or(self.time); + let pack = pack.into_index_pack_with_time(time); indexer.write().unwrap().add_remove(pack)?; } } diff --git a/crates/rustic_core/src/error.rs b/crates/rustic_core/src/error.rs index 38dea4a97..a37386107 100644 --- a/crates/rustic_core/src/error.rs +++ b/crates/rustic_core/src/error.rs @@ -146,8 +146,6 @@ pub enum CommandErrorKind { PathIsNoDir(String), /// used blobs are missing: blob {0} doesn't existing BlobsMissing(Id), - /// packs_to_delete doesn't contain `time`. - NoTimeInPacksToDelete, /// used pack {0}: size does not match! Expected size: {1}, real size: {2} PackSizeNotMatching(Id, u32, u32), /// "used pack {0} does not exist!