use std::path::PathBuf;
use tracing::*;
pub fn find_files(path: PathBuf) -> Result<FindFiles, std::io::Error> {
debug!("find_files {:?}", path);
let meta = std::fs::metadata(&path)?;
Ok(FindFiles {
stack: vec![(path, meta)],
})
}
pub struct FindFiles {
stack: Vec<(PathBuf, std::fs::Metadata)>,
}
impl Iterator for FindFiles {
type Item = (PathBuf, std::fs::Metadata);
fn next(&mut self) -> Option<Self::Item> {
while let Some((p, meta)) = self.stack.pop() {
debug!("find_files {:?}", p);
if meta.is_symlink() || meta.is_file() {
return Some((p, meta));
} else if let Ok(dir) = std::fs::read_dir(&p) {
for e in dir {
if let Ok(e) = e {
self.stack.push((e.path(), e.metadata().unwrap()));
}
}
return Some((p, meta));
} else {
error!("could not read {:?}", p);
continue;
}
}
None
}
}
pub fn find_dirs(path: PathBuf) -> Result<FindDirs, std::io::Error> {
debug!("find_files {:?}", path);
let meta = std::fs::metadata(&path)?;
Ok(FindDirs {
stack: vec![(path, meta)],
})
}
pub struct FindDirs {
stack: Vec<(PathBuf, std::fs::Metadata)>,
}
impl Iterator for FindDirs {
type Item = (PathBuf, std::fs::Metadata);
fn next(&mut self) -> Option<Self::Item> {
while let Some((p, meta)) = self.stack.pop() {
if meta.is_symlink() {
continue;
}
if let Ok(dir) = std::fs::read_dir(&p) {
for e in dir {
if let Ok(e) = e {
self.stack.push((e.path(), e.metadata().unwrap()));
}
}
return Some((p, meta));
}
}
None
}
}