Unified · Split
| @@ -94,9 +94,10 @@ fn parse_long_keywords(input: &[u8], p: &mut Pattern, cursor: &mut usize) -> Res · 93 unmodified lines | ||
| 94 | 94 | return Ok(()); |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | − for keyword in split_on_non_escaped_char(input, b',') { | |
| 97 | + split_on_non_escaped_char(input, b',', |keyword| { | |
| 98 | + let attr_prefix = b"attr:"; | |
| 98 | 99 | match keyword { |
| 99 | − b"attr" => continue, | |
| 100 | + b"attr" => {} | |
| 100 | 101 | b"top" => p.signature |= MagicSignature::TOP, |
| 101 | 102 | b"icase" => p.signature |= MagicSignature::ICASE, |
| 102 | 103 | b"exclude" => p.signature |= MagicSignature::EXCLUDE, |
| @@ -108,9 +109,9 @@ fn parse_long_keywords(input: &[u8], p: &mut Pattern, cursor: &mut usize) -> Res · 5 unmodified lines | ||
| 108 | 109 | MatchMode::Literal => return Err(Error::IncompatibleSearchModes), |
| 109 | 110 | _ => p.search_mode = MatchMode::PathAwareGlob, |
| 110 | 111 | }, |
| 111 | − _ if keyword.starts_with(b"attr:") => { | |
| 112 | + _ if keyword.starts_with(attr_prefix) => { | |
| 112 | 113 | if p.attributes.is_empty() { |
| 113 | − p.attributes = parse_attributes(&keyword[5..])?; | |
| 114 | + p.attributes = parse_attributes(&keyword[attr_prefix.len()..])?; | |
| 114 | 115 | } else { |
| 115 | 116 | return Err(Error::MultipleAttributeSpecifications); |
| 116 | 117 | } |
| @@ -120,25 +121,28 @@ fn parse_long_keywords(input: &[u8], p: &mut Pattern, cursor: &mut usize) -> Res · 3 unmodified lines | ||
| 120 | 121 | keyword: BString::from(keyword), |
| 121 | 122 | }); |
| 122 | 123 | } |
| 123 | − } | |
| 124 | − } | |
| 125 | − | |
| 126 | − Ok(()) | |
| 124 | + }; | |
| 125 | + Ok(()) | |
| 126 | + }) | |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | −fn split_on_non_escaped_char(input: &[u8], split_char: u8) -> Vec<&[u8]> { | |
| 130 | − let mut keywords = Vec::new(); | |
| 129 | +fn split_on_non_escaped_char( | |
| 130 | + input: &[u8], | |
| 131 | + split_char: u8, | |
| 132 | + mut f: impl FnMut(&[u8]) -> Result<(), Error>, | |
| 133 | +) -> Result<(), Error> { | |
| 131 | 134 | let mut i = 0; |
| 132 | 135 | let mut last = 0; |
| 133 | 136 | for window in input.windows(2) { |
| 134 | 137 | i += 1; |
| 135 | 138 | if window[0] != b'\\' && window[1] == split_char { |
| 136 | − keywords.push(&input[last..i]); | |
| 139 | + let keyword = &input[last..i]; | |
| 140 | + f(keyword)?; | |
| 137 | 141 | last = i + 1; |
| 138 | 142 | } |
| 139 | 143 | } |
| 140 | − keywords.push(&input[last..]); | |
| 141 | − keywords | |
| 144 | + let last_keyword = &input[last..]; | |
| 145 | + f(last_keyword) | |
| 142 | 146 | } |
| 143 | 147 | |
| 144 | 148 | fn parse_attributes(input: &[u8]) -> Result<Vec<git_attributes::Assignment>, Error> { |
| @@ -175,7 +179,7 @@ fn unescape_attribute_values(input: &BStr) -> Result<Cow<'_, BStr>, Error> { · 30 unmodified lines | ||
| 175 | 179 | match out { |
| 176 | 180 | Cow::Borrowed(_) => { |
| 177 | 181 | let end = out.len() + attr.len() + 1; |
| 178 | − out = Cow::Borrowed(&input[0..end.min(input.len())]) | |
| 182 | + out = Cow::Borrowed(&input[0..end.min(input.len())]); | |
| 179 | 183 | } |
| 180 | 184 | Cow::Owned(_) => { |
| 181 | 185 | let out = out.to_mut(); |