use std::path::PathBuf;
use anyhow::Context;
use crossbeam::channel::Sender;
use ignore::{Error, WalkBuilder, WalkState};
use crate::candidate_selection::messages::FileWalkerMessage;
use crate::candidate_selection::messages::FileWalkerMessage::{FileFound, WalkCompleted};
pub fn walk_paths(
path_vec: &[PathBuf],
file_event_sender: Sender<FileWalkerMessage>,
) -> anyhow::Result<()> {
let mut path_iter = path_vec.iter();
let first_path_buf = path_iter
.next()
.expect("Error: Path vector can not be empty");
let mut walker = WalkBuilder::new(first_path_buf.as_path());
for path_entry in path_iter {
walker.add(path_entry.as_path());
}
let parallel_walker = walker.threads(2).build_parallel();
parallel_walker.run(|| {
let file_event_sender = file_event_sender.clone();
Box::new(move |entry| match entry {
Ok(entry) => {
if let Some(file_type) = entry.file_type() {
if file_type.is_symlink() {
return WalkState::Skip;
}
if file_type.is_dir() {
return WalkState::Continue;
}
return match file_event_sender.send(FileFound(entry.into_path())) {
Ok(_) => WalkState::Continue,
_ => WalkState::Quit,
};
}
WalkState::Continue
}
Err(e) => {
if let Error::WithPath { path, .. } = e {
eprintln!(
"Unable to read {}",
path.to_str().unwrap_or("<unknown path>")
)
}
WalkState::Continue
}
})
});
info!("Sending WalkCompleted");
file_event_sender
.send(WalkCompleted)
.context("File events closed")?;
info!("Path walking finished");
Ok(())
}