Sebastian Thielmake fmt251b6df4 years agoHistory
118 lines · 4.4 KB · Rust
RawDownload
mod ignore {    use std::io::Read;     use bstr::{BStr, ByteSlice};    use git_attributes::{Ignore, Match, MatchGroup};    use git_glob::pattern::Case;     struct Expectations<'a> {        lines: bstr::Lines<'a>,    }     impl<'a> Iterator for Expectations<'a> {        type Item = (&'a BStr, Option<(&'a BStr, usize, &'a BStr)>);         fn next(&mut self) -> Option<Self::Item> {            let line = self.lines.next()?;            let (left, value) = line.split_at(line.find_byte(b'\t').unwrap());            let value = value[1..].as_bstr();             let source_and_line = if left == b"::" {                None            } else {                let mut tokens = left.split(|b| *b == b':');                let source = tokens.next().unwrap().as_bstr();                let line_number: usize = tokens.next().unwrap().to_str_lossy().parse().ok().unwrap();                let pattern = tokens.next().unwrap().as_bstr();                Some((source, line_number, pattern))            };            Some((value, source_and_line))        }    }     #[test]    fn from_git_dir() -> crate::Result {        let dir = git_testtools::scripted_fixture_repo_read_only("make_global_and_external_and_dir_ignores.sh")?;        let repo_dir = dir.join("repo");        let git_dir = repo_dir.join(".git");        let baseline = std::fs::read(git_dir.parent().unwrap().join("git-check-ignore.baseline"))?;        let mut buf = Vec::new();        let mut group = MatchGroup::from_git_dir(git_dir, Some(dir.join("user.exclude")), &mut buf)?;         assert!(            !group.add_patterns_file("not-a-file", false, None, &mut buf)?,            "missing files are no problem and cause a negative response"        );        assert!(            group.add_patterns_file(repo_dir.join(".gitignore"), true, repo_dir.as_path().into(), &mut buf)?,            "existing files return true"        );         buf.clear();        let ignore_file = repo_dir.join("dir-with-ignore").join(".gitignore");        std::fs::File::open(&ignore_file)?.read_to_end(&mut buf)?;        group.add_patterns_buffer(&buf, ignore_file, repo_dir.as_path().into());         for (path, source_and_line) in (Expectations {            lines: baseline.lines(),        }) {            let actual = group.pattern_matching_relative_path(                path,                repo_dir                    .join(path.to_str_lossy().as_ref())                    .metadata()                    .ok()                    .map(|m| m.is_dir()),                Case::Sensitive,            );            match (actual, source_and_line) {                (                    Some(Match {                        sequence_number,                        pattern: _,                        source,                        value: _,                    }),                    Some((expected_source, line, _expected_pattern)),                ) => {                    assert_eq!(sequence_number, line, "our counting should match the one used in git");                    assert_eq!(                        source.map(|p| p.canonicalize().unwrap()),                        Some(repo_dir.join(expected_source.to_str_lossy().as_ref()).canonicalize()?)                    );                }                (None, None) => {}                (actual, expected) => panic!("actual {:?} should match {:?} with path '{}'", actual, expected, path),            }        }        Ok(())    }     #[test]    fn from_overrides() {        let input = ["simple", "pattern/"];        let group = git_attributes::MatchGroup::<Ignore>::from_overrides(input);        assert_eq!(            group.pattern_matching_relative_path("Simple", None, git_glob::pattern::Case::Fold),            Some(pattern_to_match(&git_glob::parse("simple").unwrap(), 0))        );        assert_eq!(            group.pattern_matching_relative_path("pattern", Some(true), git_glob::pattern::Case::Sensitive),            Some(pattern_to_match(&git_glob::parse("pattern/").unwrap(), 1))        );        assert_eq!(group.patterns.len(), 1);        assert_eq!(            git_attributes::PatternList::<Ignore>::from_overrides(input),            group.patterns.into_iter().next().unwrap()        );    }     fn pattern_to_match(pattern: &git_glob::Pattern, sequence_number: usize) -> Match<'_, ()> {        Match {            pattern,            value: &(),            source: None,            sequence_number,        }    }}