diff --git a/lib/core/libimagstore/src/file_abstraction/fs.rs b/lib/core/libimagstore/src/file_abstraction/fs.rs index bb47f275..51206314 100644 --- a/lib/core/libimagstore/src/file_abstraction/fs.rs +++ b/lib/core/libimagstore/src/file_abstraction/fs.rs @@ -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 { + use walkdir::WalkDir; + + let i : Result, 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>(p: A) -> ::std::io::Result { diff --git a/lib/core/libimagstore/src/file_abstraction/inmemory.rs b/lib/core/libimagstore/src/file_abstraction/inmemory.rs index 42ebf319..5134281b 100644 --- a/lib/core/libimagstore/src/file_abstraction/inmemory.rs +++ b/lib/core/libimagstore/src/file_abstraction/inmemory.rs @@ -32,6 +32,7 @@ use super::FileAbstractionInstance; use super::Drain; use store::Entry; use storeid::StoreId; +use file_abstraction::iter::PathIterator; type Backend = Arc>>>; @@ -171,5 +172,20 @@ impl FileAbstraction for InMemoryFileAbstraction { Ok(()) } + + fn pathes_recursively(&self, _basepath: PathBuf) -> Result { + debug!("Getting all pathes"); + let keys : Vec = 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()))) + } } diff --git a/lib/core/libimagstore/src/file_abstraction/iter.rs b/lib/core/libimagstore/src/file_abstraction/iter.rs new file mode 100644 index 00000000..1ae7c335 --- /dev/null +++ b/lib/core/libimagstore/src/file_abstraction/iter.rs @@ -0,0 +1,41 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer 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>); + +impl PathIterator { + + pub fn new(iter: Box>) -> PathIterator { + PathIterator(iter) + } + +} + +impl Iterator for PathIterator { + type Item = PathBuf; + + fn next(&mut self) -> Option { + self.0.next() + } + +} + diff --git a/lib/core/libimagstore/src/file_abstraction/mod.rs b/lib/core/libimagstore/src/file_abstraction/mod.rs index 07362c35..f34a6f1e 100644 --- a/lib/core/libimagstore/src/file_abstraction/mod.rs +++ b/lib/core/libimagstore/src/file_abstraction/mod.rs @@ -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; fn fill<'a>(&'a mut self, d: Drain) -> Result<(), SE>; + + fn pathes_recursively(&self, basepath: PathBuf) -> Result; } /// An abstraction trait over actions on files diff --git a/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs b/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs index 4ed0b067..725ecf5a 100644 --- a/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs +++ b/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs @@ -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 FileAbstraction for StdIoFileAbstraction { fn fill(&mut self, d: Drain) -> Result<(), SE> { self.0.fill(d) } + + fn pathes_recursively(&self, basepath: PathBuf) -> Result { + self.0.pathes_recursively(basepath) + } } diff --git a/lib/core/libimagstore/src/file_abstraction/stdio/out.rs b/lib/core/libimagstore/src/file_abstraction/stdio/out.rs index 950947f2..23f961f2 100644 --- a/lib/core/libimagstore/src/file_abstraction/stdio/out.rs +++ b/lib/core/libimagstore/src/file_abstraction/stdio/out.rs @@ -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 FileAbstraction for StdoutFileAbstraction { Ok(()) } + fn pathes_recursively(&self, basepath: PathBuf) -> Result { + self.mem.pathes_recursively(basepath) + } + } diff --git a/lib/core/libimagstore/src/store.rs b/lib/core/libimagstore/src/store.rs index fed4ca0b..4fec02c1 100644 --- a/lib/core/libimagstore/src/store.rs +++ b/lib/core/libimagstore/src/store.rs @@ -785,13 +785,21 @@ impl Store { /// Get _all_ entries in the store (by id as iterator) pub fn entries(&self) -> Result { - 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> = 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()))) + }) }