1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#[derive(Clone, Debug)]
pub struct ProtectedBranches {
    ignores: ignore::gitignore::Gitignore,
}

impl ProtectedBranches {
    pub fn new<'p>(patterns: impl IntoIterator<Item = &'p str>) -> eyre::Result<Self> {
        let mut ignores = ignore::gitignore::GitignoreBuilder::new("");
        for pattern in patterns {
            ignores.add_line(None, pattern)?;
        }
        let ignores = ignores.build()?;
        Ok(Self { ignores })
    }

    pub fn is_protected(&self, name: &str) -> bool {
        let name_match = self.ignores.matched_path_or_any_parents(name, false);
        match name_match {
            ignore::Match::None => false,
            ignore::Match::Ignore(glob) => {
                log::trace!("{}: ignored {:?}", name, glob.original());
                true
            }
            ignore::Match::Whitelist(glob) => {
                log::trace!("{}: allowed {:?}", name, glob.original());
                false
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn empty_allows_all() {
        let protect = ProtectedBranches::new(None).unwrap();
        assert!(!protect.is_protected("main"));
    }

    #[test]
    fn protect_branch() {
        let protect = ProtectedBranches::new(Some("main")).unwrap();
        assert!(protect.is_protected("main"));
        assert!(!protect.is_protected("feature"));
    }

    #[test]
    fn negation_patterns() {
        let protect = ProtectedBranches::new(vec!["v*", "!very"]).unwrap();
        assert!(protect.is_protected("v1.0.0"));
        assert!(!protect.is_protected("very"));
        assert!(!protect.is_protected("feature"));
    }

    #[test]
    fn folders() {
        let protect = ProtectedBranches::new(vec!["release/"]).unwrap();
        assert!(!protect.is_protected("release"));
        assert!(protect.is_protected("release/v1.0.0"));
        assert!(!protect.is_protected("feature"));
    }
}