ignore_check/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use {
4    anyhow::{Result, anyhow},
5    ignore::gitignore::{Gitignore, GitignoreBuilder, gitconfig_excludes_path},
6    std::{
7        collections::BTreeSet,
8        path::{Path, PathBuf},
9    },
10};
11
12/// Check if a path is ignored
13pub fn ignored(path: impl AsRef<Path>) -> Result<bool> {
14    Ok(Ignore::new(path.as_ref().parent().unwrap())?.check(path))
15}
16
17pub struct Ignore {
18    matcher: Gitignore,
19}
20
21impl Default for Ignore {
22    fn default() -> Ignore {
23        Ignore::new("").unwrap()
24    }
25}
26
27impl Ignore {
28    pub fn new(root: impl AsRef<Path>) -> Result<Ignore> {
29        let mut builder = GitignoreBuilder::new(&root);
30
31        // Add local `.gitignore` file(s)
32        let mut added = BTreeSet::new();
33        let mut dir = root.as_ref().to_path_buf();
34        loop {
35            add_path(dir.join(".gitignore"), &mut builder, &mut added)?;
36
37            if let Some(parent) = dir.parent() {
38                dir = parent.to_path_buf();
39            } else {
40                break;
41            }
42        }
43
44        // Add global (user) excludes path (`~/.gitignore`)
45        if let Some(path) = gitconfig_excludes_path() {
46            add_path(path, &mut builder, &mut added)?;
47        }
48
49        Ok(Ignore {
50            matcher: builder.build()?,
51        })
52    }
53
54    pub fn check(&self, path: impl AsRef<Path>) -> bool {
55        self.matcher
56            .matched_path_or_any_parents(&path, path.as_ref().is_dir())
57            .is_ignore()
58    }
59}
60
61fn add_path(
62    path: PathBuf,
63    builder: &mut GitignoreBuilder,
64    added: &mut BTreeSet<PathBuf>,
65) -> Result<()> {
66    if path.exists() && !added.contains(&path) {
67        match builder.add(&path) {
68            Some(e) => Err(anyhow!("Failed to add {path:?}: {e}")),
69            None => {
70                added.insert(path);
71                Ok(())
72            }
73        }
74    } else {
75        Ok(())
76    }
77}