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 super::Drain;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
use storeid::StoreId;
|
use storeid::StoreId;
|
||||||
|
use file_abstraction::iter::PathIterator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FSFileAbstractionInstance {
|
pub enum FSFileAbstractionInstance {
|
||||||
|
@ -99,7 +100,6 @@ impl FileAbstractionInstance for FSFileAbstractionInstance {
|
||||||
}
|
}
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `FSFileAbstraction` state type
|
/// `FSFileAbstraction` state type
|
||||||
|
@ -150,6 +150,24 @@ impl FileAbstraction for FSFileAbstraction {
|
||||||
acc.and_then(|_| self.new_instance(path).write_file_content(&element))
|
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> {
|
fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
|
||||||
|
|
|
@ -32,6 +32,7 @@ use super::FileAbstractionInstance;
|
||||||
use super::Drain;
|
use super::Drain;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
use storeid::StoreId;
|
use storeid::StoreId;
|
||||||
|
use file_abstraction::iter::PathIterator;
|
||||||
|
|
||||||
type Backend = Arc<Mutex<RefCell<HashMap<PathBuf, Entry>>>>;
|
type Backend = Arc<Mutex<RefCell<HashMap<PathBuf, Entry>>>>;
|
||||||
|
|
||||||
|
@ -171,5 +172,20 @@ impl FileAbstraction for InMemoryFileAbstraction {
|
||||||
|
|
||||||
Ok(())
|
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 fs;
|
||||||
mod inmemory;
|
mod inmemory;
|
||||||
|
mod iter;
|
||||||
pub mod stdio;
|
pub mod stdio;
|
||||||
|
|
||||||
pub use self::fs::FSFileAbstraction;
|
pub use self::fs::FSFileAbstraction;
|
||||||
pub use self::fs::FSFileAbstractionInstance;
|
pub use self::fs::FSFileAbstractionInstance;
|
||||||
pub use self::inmemory::InMemoryFileAbstraction;
|
pub use self::inmemory::InMemoryFileAbstraction;
|
||||||
pub use self::inmemory::InMemoryFileAbstractionInstance;
|
pub use self::inmemory::InMemoryFileAbstractionInstance;
|
||||||
|
use self::iter::PathIterator;
|
||||||
|
|
||||||
/// An abstraction trait over filesystem actions
|
/// An abstraction trait over filesystem actions
|
||||||
pub trait FileAbstraction : Debug {
|
pub trait FileAbstraction : Debug {
|
||||||
|
@ -45,6 +47,8 @@ pub trait FileAbstraction : Debug {
|
||||||
|
|
||||||
fn drain(&self) -> Result<Drain, SE>;
|
fn drain(&self) -> Result<Drain, SE>;
|
||||||
fn fill<'a>(&'a mut self, d: Drain) -> Result<(), 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
|
/// An abstraction trait over actions on files
|
||||||
|
|
|
@ -36,6 +36,7 @@ use super::FileAbstractionInstance;
|
||||||
use super::Drain;
|
use super::Drain;
|
||||||
use super::InMemoryFileAbstraction;
|
use super::InMemoryFileAbstraction;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
|
use file_abstraction::iter::PathIterator;
|
||||||
|
|
||||||
pub mod mapper;
|
pub mod mapper;
|
||||||
pub mod out;
|
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> {
|
fn fill(&mut self, d: Drain) -> Result<(), SE> {
|
||||||
self.0.fill(d)
|
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::Drain;
|
||||||
use super::InMemoryFileAbstraction;
|
use super::InMemoryFileAbstraction;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
|
use file_abstraction::iter::PathIterator;
|
||||||
|
|
||||||
use super::mapper::Mapper;
|
use super::mapper::Mapper;
|
||||||
|
|
||||||
|
@ -151,6 +152,10 @@ impl<W: Write, M: Mapper> FileAbstraction for StdoutFileAbstraction<W, M> {
|
||||||
Ok(())
|
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)
|
/// Get _all_ entries in the store (by id as iterator)
|
||||||
pub fn entries(&self) -> Result<StoreIdIterator> {
|
pub fn entries(&self) -> Result<StoreIdIterator> {
|
||||||
let iter = Walk::new(self.path().clone(), "")
|
self.backend
|
||||||
.filter_map(|id| match id {
|
.pathes_recursively(self.path().clone())
|
||||||
StoreObject::Id(sid) => Some(sid),
|
.and_then(|iter| {
|
||||||
_ => None
|
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