Rewrite Store::entries() implementation
As we rely on the filesystem in Store::entries(), which is a bug and shouldn't be done, we rewrite this function and use the file_abstraction framework.
This commit is contained in:
parent
e6d96c9f83
commit
b10d63c134
7 changed files with 104 additions and 7 deletions
|
@ -29,6 +29,7 @@ use super::FileAbstractionInstance;
|
|||
use super::Drain;
|
||||
use store::Entry;
|
||||
use storeid::StoreId;
|
||||
use file_abstraction::iter::PathIterator;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FSFileAbstractionInstance {
|
||||
|
@ -99,7 +100,6 @@ impl FileAbstractionInstance for FSFileAbstractionInstance {
|
|||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// `FSFileAbstraction` state type
|
||||
|
@ -150,6 +150,24 @@ impl FileAbstraction for FSFileAbstraction {
|
|||
acc.and_then(|_| self.new_instance(path).write_file_content(&element))
|
||||
})
|
||||
}
|
||||
|
||||
fn pathes_recursively(&self, basepath: PathBuf) -> Result<PathIterator, SE> {
|
||||
use walkdir::WalkDir;
|
||||
|
||||
let i : Result<Vec<PathBuf>, SE> = WalkDir::new(basepath)
|
||||
.into_iter()
|
||||
.map(|r| {
|
||||
r.map(|e| PathBuf::from(e.path()))
|
||||
.chain_err(|| SE::from_kind(SEK::FileError))
|
||||
})
|
||||
.fold(Ok(vec![]), |acc, e| {
|
||||
acc.and_then(move |mut a| {
|
||||
a.push(try!(e));
|
||||
Ok(a)
|
||||
})
|
||||
});
|
||||
Ok(PathIterator::new(Box::new(try!(i).into_iter())))
|
||||
}
|
||||
}
|
||||
|
||||
fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
|
||||
|
|
|
@ -32,6 +32,7 @@ use super::FileAbstractionInstance;
|
|||
use super::Drain;
|
||||
use store::Entry;
|
||||
use storeid::StoreId;
|
||||
use file_abstraction::iter::PathIterator;
|
||||
|
||||
type Backend = Arc<Mutex<RefCell<HashMap<PathBuf, Entry>>>>;
|
||||
|
||||
|
@ -171,5 +172,20 @@ impl FileAbstraction for InMemoryFileAbstraction {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pathes_recursively(&self, _basepath: PathBuf) -> Result<PathIterator, SE> {
|
||||
debug!("Getting all pathes");
|
||||
let keys : Vec<PathBuf> = self
|
||||
.backend()
|
||||
.lock()
|
||||
.map_err(|_| SE::from_kind(SEK::FileError))?
|
||||
.get_mut()
|
||||
.keys()
|
||||
.map(PathBuf::from)
|
||||
.collect();
|
||||
// we collect here as this happens only in tests and in memory anyways, so no problem
|
||||
|
||||
Ok(PathIterator::new(Box::new(keys.into_iter())))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
41
lib/core/libimagstore/src/file_abstraction/iter.rs
Normal file
41
lib/core/libimagstore/src/file_abstraction/iter.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// imag - the personal information management suite for the commandline
|
||||
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; version
|
||||
// 2.1 of the License.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// A wrapper for an iterator over `PathBuf`s
|
||||
pub struct PathIterator(Box<Iterator<Item = PathBuf>>);
|
||||
|
||||
impl PathIterator {
|
||||
|
||||
pub fn new(iter: Box<Iterator<Item = PathBuf>>) -> PathIterator {
|
||||
PathIterator(iter)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Iterator for PathIterator {
|
||||
type Item = PathBuf;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,12 +27,14 @@ use storeid::StoreId;
|
|||
|
||||
mod fs;
|
||||
mod inmemory;
|
||||
mod iter;
|
||||
pub mod stdio;
|
||||
|
||||
pub use self::fs::FSFileAbstraction;
|
||||
pub use self::fs::FSFileAbstractionInstance;
|
||||
pub use self::inmemory::InMemoryFileAbstraction;
|
||||
pub use self::inmemory::InMemoryFileAbstractionInstance;
|
||||
use self::iter::PathIterator;
|
||||
|
||||
/// An abstraction trait over filesystem actions
|
||||
pub trait FileAbstraction : Debug {
|
||||
|
@ -45,6 +47,8 @@ pub trait FileAbstraction : Debug {
|
|||
|
||||
fn drain(&self) -> Result<Drain, SE>;
|
||||
fn fill<'a>(&'a mut self, d: Drain) -> Result<(), SE>;
|
||||
|
||||
fn pathes_recursively(&self, basepath: PathBuf) -> Result<PathIterator, SE>;
|
||||
}
|
||||
|
||||
/// An abstraction trait over actions on files
|
||||
|
|
|
@ -36,6 +36,7 @@ use super::FileAbstractionInstance;
|
|||
use super::Drain;
|
||||
use super::InMemoryFileAbstraction;
|
||||
use store::Entry;
|
||||
use file_abstraction::iter::PathIterator;
|
||||
|
||||
pub mod mapper;
|
||||
pub mod out;
|
||||
|
@ -121,5 +122,9 @@ impl<W: Write, M: Mapper> FileAbstraction for StdIoFileAbstraction<W, M> {
|
|||
fn fill(&mut self, d: Drain) -> Result<(), SE> {
|
||||
self.0.fill(d)
|
||||
}
|
||||
|
||||
fn pathes_recursively(&self, basepath: PathBuf) -> Result<PathIterator, SE> {
|
||||
self.0.pathes_recursively(basepath)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ use super::FileAbstractionInstance;
|
|||
use super::Drain;
|
||||
use super::InMemoryFileAbstraction;
|
||||
use store::Entry;
|
||||
use file_abstraction::iter::PathIterator;
|
||||
|
||||
use super::mapper::Mapper;
|
||||
|
||||
|
@ -151,6 +152,10 @@ impl<W: Write, M: Mapper> FileAbstraction for StdoutFileAbstraction<W, M> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn pathes_recursively(&self, basepath: PathBuf) -> Result<PathIterator, SE> {
|
||||
self.mem.pathes_recursively(basepath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -785,13 +785,21 @@ impl Store {
|
|||
|
||||
/// Get _all_ entries in the store (by id as iterator)
|
||||
pub fn entries(&self) -> Result<StoreIdIterator> {
|
||||
let iter = Walk::new(self.path().clone(), "")
|
||||
.filter_map(|id| match id {
|
||||
StoreObject::Id(sid) => Some(sid),
|
||||
_ => None
|
||||
self.backend
|
||||
.pathes_recursively(self.path().clone())
|
||||
.and_then(|iter| {
|
||||
let iter : Result<Vec<StoreId>> = iter
|
||||
.map(|path| StoreId::from_full_path(self.path(), path))
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
acc.and_then(move |mut a| {
|
||||
a.push(try!(elem));
|
||||
Ok(a)
|
||||
})
|
||||
});
|
||||
|
||||
Ok(StoreIdIterator::new(Box::new(iter)))
|
||||
let iter = try!(iter);
|
||||
Ok(StoreIdIterator::new(Box::new(iter.into_iter())))
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue