Skip to content

Commit a161e33

Browse files
committed
A sketch of the parser API for ignore files (#301)
Use an iterator for flexibility, while parsing what matters and leaving details to the caller, like generating the actual glob from the pre-escaped string.
1 parent d6bee3f commit a161e33

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

git-attributes/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ doctest = false
1313
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1414

1515
[dependencies]
16+
bstr = { version = "0.2.13", default-features = false, features = ["std"]}
17+
bitflags = "1.3.2"

git-attributes/src/lib.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,59 @@
11
#![forbid(unsafe_code, rust_2018_idioms)]
2+
3+
pub mod ignore {
4+
pub mod pattern {
5+
use bitflags::bitflags;
6+
7+
bitflags! {
8+
pub struct Mode: u32 {
9+
const NO_DIR = 1 << 0;
10+
// TODO: find a much better name!
11+
const ENDS_WITH = 1 << 1;
12+
const MUST_BE_DIR = 1 << 2;
13+
const NEGATIVE = 1 << 3;
14+
}
15+
}
16+
}
17+
}
18+
19+
pub mod parse {
20+
pub mod ignore {
21+
use crate::ignore;
22+
use bstr::{BStr, BString, ByteSlice};
23+
24+
pub struct Iter<'a> {
25+
cursor: &'a BStr,
26+
}
27+
28+
impl<'a> Iter<'a> {
29+
pub fn new(buf: &'a [u8]) -> Self {
30+
Iter { cursor: buf.as_bstr() }
31+
}
32+
}
33+
34+
impl<'a> Iterator for Iter<'a> {
35+
type Item = (BString, ignore::pattern::Mode);
36+
37+
fn next(&mut self) -> Option<Self::Item> {
38+
if self.cursor.is_empty() {
39+
return None;
40+
}
41+
let mut lines = self.cursor.lines();
42+
let res = None;
43+
while let Some(line) = lines.next() {
44+
if line.starts_with(b"#") {
45+
continue;
46+
}
47+
todo!("handle escapes and trim trailing non-escaped whitespace")
48+
}
49+
if let Some(next_line) = lines.next() {
50+
self.cursor = next_line.as_bstr();
51+
}
52+
res
53+
}
54+
}
55+
}
56+
pub fn ignore(buf: &[u8]) -> ignore::Iter<'_> {
57+
ignore::Iter::new(buf)
58+
}
59+
}

git-attributes/tests/attributes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
mod parse {
2+
mod ignore {
3+
#[test]
4+
fn comments_are_ignored() {
5+
assert!(git_attributes::parse::ignore(b"# hello world").next().is_none());
6+
}
7+
}
8+
}

0 commit comments

Comments
 (0)