use crate::cancellation::{CancellationFlag, Outcome};
use ignore::{WalkBuilder, overrides::OverrideBuilder};
use std::path::Path;
pub fn wiki_tree_walker(wiki_directory: &Path) -> Result<WalkBuilder, ignore::Error> {
let mut overrides = OverrideBuilder::new(wiki_directory);
overrides
.add("!.git/")
.expect("The static .git override should be valid.")
.add("!.hg/")
.expect("The static .hg override should be valid.");
let overrides = overrides.build()?;
let mut walker_builder = WalkBuilder::new(wiki_directory);
walker_builder
.current_dir(wiki_directory)
.follow_links(true)
.hidden(false)
.parents(false)
.require_git(false)
.overrides(overrides);
Ok(walker_builder)
}
#[derive(Debug, Eq, PartialEq)]
pub enum Visibility {
Visible,
Empty,
Ignored,
}
pub fn visibility(
wiki_directory: &Path,
path: &Path,
cancellation: &CancellationFlag,
) -> Outcome<Result<Visibility, ignore::Error>> {
let target = wiki_directory.join(path);
let mut walker_builder = match wiki_tree_walker(wiki_directory) {
Ok(walker_builder) => walker_builder,
Err(error) => return Outcome::Completed(Err(error)),
};
walker_builder.filter_entry({
let target = target.clone();
move |entry| target.starts_with(entry.path()) || entry.path().starts_with(&target)
});
let mut reached = false;
for entry in walker_builder.build().flatten() {
if cancellation.is_cancelled() {
return Outcome::Cancelled;
}
if entry.path() == target {
reached = true;
}
if entry.path().starts_with(&target) && entry.file_type().is_some_and(|t| t.is_file()) {
return Outcome::Completed(Ok(Visibility::Visible));
}
}
Outcome::Completed(Ok(if reached {
Visibility::Empty
} else {
Visibility::Ignored
}))
}