Pass around Arc<FileAbstraction> internally

Because the iterators need to be able to check whether the file exists
_in the backend_ (not on disk, but in the backend, because of in-memory
test for example), we need to be able to pass the backend to the
iterator intermediate type.

This patch implements this. It does so by changing the internal backend
member of the store from `Box<FileAbstraction>` to
`Arc<FileAbstraction>`, which gives us the ability to clone the
reference to the backend easily without needing to rely on lifetimes
here, because of the Arc.

Also, less boxes are always good.
This commit is contained in:
Matthias Beyer 2018-05-01 20:47:25 +02:00
parent b86ed2ffa9
commit 42e2f18fb3
2 changed files with 17 additions and 13 deletions

View file

@ -18,9 +18,11 @@
//
use std::path::PathBuf;
use std::sync::Arc;
use error::Result;
use storeid::StoreId;
use file_abstraction::FileAbstraction;
/// A wrapper for an iterator over `PathBuf`s
pub struct PathIterator(Box<Iterator<Item = Result<PathBuf>>>);
@ -31,8 +33,10 @@ impl PathIterator {
PathIterator(iter)
}
pub fn store_id_constructing(self, storepath: PathBuf) -> StoreIdConstructingIterator {
StoreIdConstructingIterator(self, storepath)
pub fn store_id_constructing(self, storepath: PathBuf, backend: Arc<FileAbstraction>)
-> StoreIdConstructingIterator
{
StoreIdConstructingIterator(self, storepath, backend)
}
}
@ -50,7 +54,7 @@ impl Iterator for PathIterator {
/// Helper type for constructing StoreIds from a PathIterator.
///
/// Automatically ignores non-files.
pub struct StoreIdConstructingIterator(PathIterator, PathBuf);
pub struct StoreIdConstructingIterator(PathIterator, PathBuf, Arc<FileAbstraction>);
impl Iterator for StoreIdConstructingIterator {
type Item = Result<StoreId>;
@ -59,10 +63,10 @@ impl Iterator for StoreIdConstructingIterator {
while let Some(next) = self.0.next() {
match next {
Err(e) => return Some(Err(e)),
Ok(next) => if next.is_file() {
return Some(StoreId::from_full_path(&self.1, next))
} else {
continue
Ok(next) => match self.2.exists(&next) {
Err(e) => return Some(Err(e)),
Ok(true) => return Some(StoreId::from_full_path(&self.1, next)),
Ok(false) => { continue },
}
}
}

View file

@ -137,7 +137,7 @@ impl Iterator for Walk {
impl StoreEntry {
fn new(id: StoreId, backend: &Box<FileAbstraction>) -> Result<StoreEntry> {
fn new(id: StoreId, backend: &Arc<FileAbstraction>) -> Result<StoreEntry> {
let pb = id.clone().into_pathbuf()?;
#[cfg(feature = "fs-lock")]
@ -214,7 +214,7 @@ pub struct Store {
/// The backend to use
///
/// This provides the filesystem-operation functions (or pretends to)
backend: Box<FileAbstraction>,
backend: Arc<FileAbstraction>,
}
impl Store {
@ -235,7 +235,7 @@ impl Store {
/// - On success: Store object
///
pub fn new(location: PathBuf, store_config: &Option<Value>) -> Result<Store> {
let backend = Box::new(FSFileAbstraction::default());
let backend = Arc::new(FSFileAbstraction::default());
Store::new_with_backend(location, store_config, backend)
}
@ -245,7 +245,7 @@ impl Store {
/// Do not use directly, only for testing purposes.
pub fn new_with_backend(location: PathBuf,
store_config: &Option<Value>,
backend: Box<FileAbstraction>) -> Result<Store> {
backend: Arc<FileAbstraction>) -> Result<Store> {
use configuration::*;
debug!("Building new Store object");
@ -299,7 +299,7 @@ impl Store {
/// to stdout, we need to be able to replace the in-memory backend with the real filesystem
/// backend.
///
pub fn reset_backend(&mut self, mut backend: Box<FileAbstraction>) -> Result<()> {
pub fn reset_backend(&mut self, mut backend: Arc<FileAbstraction>) -> Result<()> {
self.backend
.drain()
.and_then(|drain| backend.fill(drain))
@ -744,7 +744,7 @@ impl Store {
pub fn entries(&self) -> Result<StoreIdIteratorWithStore> {
self.backend
.pathes_recursively(self.path().clone())
.map(|i| i.store_id_constructing(self.path().clone()))
.map(|i| i.store_id_constructing(self.path().clone(), self.backend.clone()))
.map(Box::new)
.map(|it| StoreIdIteratorWithStore::new(it, self))
}