diff --git a/lib/src/ignore.rs b/lib/src/ignore.rs index 2dcb97b..1cbfaac 100644 --- a/lib/src/ignore.rs +++ b/lib/src/ignore.rs @@ -7,3 +7,4 @@ pub use filter::*; mod files; mod filter; +pub mod tree; diff --git a/lib/src/ignore/files.rs b/lib/src/ignore/files.rs index 92682af..450cdc5 100644 --- a/lib/src/ignore/files.rs +++ b/lib/src/ignore/files.rs @@ -1,7 +1,3 @@ -use git_config::{ - file::{from_paths, GitConfig}, - values::Path as GitPath, -}; use std::{ collections::HashSet, env, @@ -9,6 +5,10 @@ use std::{ path::{Path, PathBuf}, }; +use git_config::{ + file::{from_paths, GitConfig}, + values::Path as GitPath, +}; use tokio::fs::{metadata, read_dir}; use tracing::{trace, trace_span}; @@ -474,7 +474,7 @@ impl DirTourist { pub(crate) async fn add_last_file_to_filter( &mut self, - files: &mut Vec, + files: &mut [IgnoreFile], errors: &mut Vec, ) { if let Some(ig) = files.last() { diff --git a/lib/src/ignore/filter.rs b/lib/src/ignore/filter.rs index 55b3684..d1ea6df 100644 --- a/lib/src/ignore/filter.rs +++ b/lib/src/ignore/filter.rs @@ -88,10 +88,6 @@ impl IgnoreFilterer { for (file, content) in files_contents.into_iter().flatten() { let _span = trace_span!("loading ignore file", ?file).entered(); for line in content.lines() { - if line.is_empty() || line.starts_with('#') { - continue; - } - trace!(?line, "adding ignore line"); builder .add_line(file.applies_in.clone(), line) diff --git a/lib/src/ignore/tree.rs b/lib/src/ignore/tree.rs new file mode 100644 index 0000000..405ffb0 --- /dev/null +++ b/lib/src/ignore/tree.rs @@ -0,0 +1,79 @@ +//! IgnoreTree manages [GitIgnore] instances for a directory tree. +//! +//! A [GitIgnore] is only meant to be used for files that cover a single +//! directory. That makes it annoying to use when you have ignore files +//! in many directories, and some global ignore files too. +//! +//! This module provides a similar interface, but supports loading +//! ignore files directly for any path, or for the global space. + +// This module is a candidate for a new crate. +// TODO: do our own parsing? having all these builders around is meh + +use std::{ + collections::BTreeMap, + path::{Path, PathBuf}, +}; + +use ignore::{ + gitignore::{Gitignore, GitignoreBuilder, Glob}, + Error as IgnoreError, Match, +}; + +/// An interface for many ignore files in a directory tree. +/// +/// This is conceptually a tree of [GitIgnore] instances, rooted at the +/// origin, and the matcher methods figure out which one to call on. +#[derive(Debug)] +pub struct IgnoreTree { + origin: PathBuf, + ignores: BTreeMap, + compiled: BTreeMap, +} + +impl IgnoreTree { + /// Create a new IgnoreTree at the given origin. + /// + /// The origin is the root of the tree which contains ignore files. Adding + /// ignores that are higher up than the origin will silently discard them, + /// as they wouldn't have any effect anyway. To add ignores from global + /// ignore files, use the dedicated method instead of providing their path. + pub fn new(origin: impl AsRef) -> Self { + let origin = origin.as_ref(); + Self { + origin: origin.to_owned(), + ignores: BTreeMap::new(), + compiled: BTreeMap::new(), + } + } + + /// Add a line from an ignore file at a particular path. + /// + /// The `at` path should be to the directory _containing_ the ignore file, + /// not to the ignore file itself. + pub fn add_local_line(&mut self, at: impl AsRef, line: &str) -> Result<(), IgnoreError> { + todo!() + } + + /// Add a line from an ignore file for the global ignore space. + pub fn add_global_line(&mut self, line: &str) -> Result<(), IgnoreError> { + self.add_local_line("", line) + } + + /// Returns the total number of ignore globs. + pub fn num_ignores(&self) -> u64 { + todo!() + } + + /// Returns the total number of whitelisted globs. + pub fn num_whitelists(&self) -> u64 { + todo!() + } + + /// Returns whether the given path (file or directory) matched a pattern. + // TODO: grow our own return type for this + pub fn matched(&self, path: impl AsRef, is_dir: bool) -> Match<&Glob> { + // do the "is in tree, check parents, otherwise don't" dance ourselves + todo!() + } +}