diff --git a/crates/core/src/backend.rs b/crates/core/src/backend.rs index 780db270..5fb34656 100644 --- a/crates/core/src/backend.rs +++ b/crates/core/src/backend.rs @@ -17,7 +17,7 @@ use anyhow::Result; use bytes::Bytes; use chrono::{DateTime, Local}; use enum_map::Enum; -use log::trace; +use log::{debug, trace}; #[cfg(test)] use mockall::mock; @@ -356,7 +356,8 @@ pub trait WriteBackend: ReadBackend { /// # Errors /// /// If the file could not be read. - fn lock(&self, _tpe: FileType, _id: &Id, _until: Option>) -> Result<()> { + fn lock(&self, tpe: FileType, id: &Id, until: Option>) -> Result<()> { + debug!("no locking implemented. {tpe:?}, {id}, {until:?}"); Ok(()) } } diff --git a/crates/core/src/backend/cache.rs b/crates/core/src/backend/cache.rs index 69f0eb86..1a46e9ff 100644 --- a/crates/core/src/backend/cache.rs +++ b/crates/core/src/backend/cache.rs @@ -8,6 +8,7 @@ use std::{ use anyhow::Result; use bytes::Bytes; +use chrono::{DateTime, Local}; use dirs::cache_dir; use log::{trace, warn}; use walkdir::WalkDir; @@ -210,6 +211,14 @@ impl WriteBackend for CachedBackend { } self.be.remove(tpe, id, cacheable) } + + fn can_lock(&self) -> bool { + self.be.can_lock() + } + + fn lock(&self, tpe: FileType, id: &Id, until: Option>) -> Result<()> { + self.be.lock(tpe, id, until) + } } /// Backend that caches data in a directory. diff --git a/crates/core/src/backend/decrypt.rs b/crates/core/src/backend/decrypt.rs index 8c307a5c..f9e7c1ed 100644 --- a/crates/core/src/backend/decrypt.rs +++ b/crates/core/src/backend/decrypt.rs @@ -2,6 +2,7 @@ use std::{num::NonZeroU32, sync::Arc}; use anyhow::Result; use bytes::Bytes; +use chrono::{DateTime, Local}; use crossbeam_channel::{unbounded, Receiver}; use rayon::prelude::*; use zstd::stream::{copy_encode, decode_all, encode_all}; @@ -581,6 +582,14 @@ impl WriteBackend for DecryptBackend { fn remove(&self, tpe: FileType, id: &Id, cacheable: bool) -> Result<()> { self.be.remove(tpe, id, cacheable) } + + fn can_lock(&self) -> bool { + self.be.can_lock() + } + + fn lock(&self, tpe: FileType, id: &Id, until: Option>) -> Result<()> { + self.be.lock(tpe, id, until) + } } #[cfg(test)] diff --git a/crates/core/src/backend/dry_run.rs b/crates/core/src/backend/dry_run.rs index e93c9023..261bcdd6 100644 --- a/crates/core/src/backend/dry_run.rs +++ b/crates/core/src/backend/dry_run.rs @@ -1,5 +1,6 @@ use anyhow::Result; use bytes::Bytes; +use chrono::{DateTime, Local}; use zstd::decode_all; use crate::{ @@ -156,4 +157,12 @@ impl WriteBackend for DryRunBackend { self.be.remove(tpe, id, cacheable) } } + + fn can_lock(&self) -> bool { + self.be.can_lock() + } + + fn lock(&self, tpe: FileType, id: &Id, until: Option>) -> Result<()> { + self.be.lock(tpe, id, until) + } } diff --git a/crates/core/src/backend/hotcold.rs b/crates/core/src/backend/hotcold.rs index 75a1f750..798005d6 100644 --- a/crates/core/src/backend/hotcold.rs +++ b/crates/core/src/backend/hotcold.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use anyhow::Result; use bytes::Bytes; +use chrono::{DateTime, Local}; use crate::{ backend::{FileType, ReadBackend, WriteBackend}, @@ -98,4 +99,12 @@ impl WriteBackend for HotColdBackend { } Ok(()) } + + fn can_lock(&self) -> bool { + self.be.can_lock() + } + + fn lock(&self, tpe: FileType, id: &Id, until: Option>) -> Result<()> { + self.be.lock(tpe, id, until) + } } diff --git a/crates/core/src/commands/lock.rs b/crates/core/src/commands/lock.rs index 3c2aac02..81354afb 100644 --- a/crates/core/src/commands/lock.rs +++ b/crates/core/src/commands/lock.rs @@ -23,7 +23,7 @@ use crate::{ configfile::ConfigId, IndexFile, IndexId, KeyId, PackId, RepoId, SnapshotFile, SnapshotId, }, repository::{Open, Repository}, - BlobId, TreeId, + BlobId, TreeId, WriteBackend, }; pub(super) mod constants { @@ -52,6 +52,10 @@ impl LockOptions { snapshots: &[SnapshotFile], now: DateTime, ) -> RusticResult<()> { + if !repo.be.can_lock() { + return Err(CommandErrorKind::NoLockingConfigured.into()); + } + let pb = &repo.pb; let be = repo.dbe(); @@ -82,6 +86,10 @@ impl LockOptions { snapshots: &[SnapshotFile], now: DateTime, ) -> RusticResult<()> { + if !repo.be.can_lock() { + return Err(CommandErrorKind::NoLockingConfigured.into()); + } + let mut new_snaps = Vec::new(); let mut remove_snaps = Vec::new(); let mut lock_snaps = Vec::new(); @@ -119,6 +127,9 @@ impl LockOptions { index_files: Vec<(IndexId, IndexFile)>, packs: &BTreeSet, ) -> RusticResult<()> { + if !repo.be.can_lock() { + return Err(CommandErrorKind::NoLockingConfigured.into()); + } let mut lock_packs = Vec::new(); let mut remove_index = Vec::new(); @@ -182,6 +193,10 @@ pub fn lock_all_files( repo: &Repository, until: Option>, ) -> RusticResult<()> { + if !repo.be.can_lock() { + return Err(CommandErrorKind::NoLockingConfigured.into()); + } + let p = &repo .pb .progress_spinner(format!("listing {:?} files..", ID::TYPE)); diff --git a/crates/core/src/error.rs b/crates/core/src/error.rs index 9300e020..b248e5f0 100644 --- a/crates/core/src/error.rs +++ b/crates/core/src/error.rs @@ -231,6 +231,8 @@ pub enum CommandErrorKind { PackIdNotFoundinIndex(PackId), /// Blob Id {0:?} not found in index BlobIdNotFoundinIndex(BlobId), + /// No locking capability configured for the backend + NoLockingConfigured, } /// [`CryptoErrorKind`] describes the errors that can happen while dealing with Cryptographic functions