5 // This software may be used and distributed according to the terms of the |
5 // This software may be used and distributed according to the terms of the |
6 // GNU General Public License version 2 or any later version. |
6 // GNU General Public License version 2 or any later version. |
7 |
7 |
8 //! Handling of Mercurial-specific patterns. |
8 //! Handling of Mercurial-specific patterns. |
9 |
9 |
10 use crate::{ |
10 use crate::{utils::SliceExt, LineNumber, PatternError, PatternFileError}; |
11 utils::{files::get_path_from_bytes, SliceExt}, |
|
12 LineNumber, PatternError, PatternFileError, |
|
13 }; |
|
14 use lazy_static::lazy_static; |
11 use lazy_static::lazy_static; |
15 use regex::bytes::{NoExpand, Regex}; |
12 use regex::bytes::{NoExpand, Regex}; |
16 use std::collections::HashMap; |
13 use std::collections::HashMap; |
17 use std::fs::File; |
14 use std::fs::File; |
18 use std::io::Read; |
15 use std::io::Read; |
|
16 use std::path::{Path, PathBuf}; |
19 use std::vec::Vec; |
17 use std::vec::Vec; |
20 |
18 |
21 lazy_static! { |
19 lazy_static! { |
22 static ref RE_ESCAPE: Vec<Vec<u8>> = { |
20 static ref RE_ESCAPE: Vec<Vec<u8>> = { |
23 let mut v: Vec<Vec<u8>> = (0..=255).map(|byte| vec![byte]).collect(); |
21 let mut v: Vec<Vec<u8>> = (0..=255).map(|byte| vec![byte]).collect(); |
228 m |
226 m |
229 }; |
227 }; |
230 } |
228 } |
231 |
229 |
232 pub type PatternTuple = (Vec<u8>, LineNumber, Vec<u8>); |
230 pub type PatternTuple = (Vec<u8>, LineNumber, Vec<u8>); |
233 type WarningTuple = (Vec<u8>, Vec<u8>); |
231 type WarningTuple = (PathBuf, Vec<u8>); |
234 |
232 |
235 pub fn parse_pattern_file_contents( |
233 pub fn parse_pattern_file_contents<P: AsRef<Path>>( |
236 lines: &[u8], |
234 lines: &[u8], |
237 file_path: &[u8], |
235 file_path: P, |
238 warn: bool, |
236 warn: bool, |
239 ) -> (Vec<PatternTuple>, Vec<WarningTuple>) { |
237 ) -> (Vec<PatternTuple>, Vec<WarningTuple>) { |
240 let comment_regex = Regex::new(r"((?:^|[^\\])(?:\\\\)*)#.*").unwrap(); |
238 let comment_regex = Regex::new(r"((?:^|[^\\])(?:\\\\)*)#.*").unwrap(); |
241 let comment_escape_regex = Regex::new(r"\\#").unwrap(); |
239 let comment_escape_regex = Regex::new(r"\\#").unwrap(); |
242 let mut inputs: Vec<PatternTuple> = vec![]; |
240 let mut inputs: Vec<PatternTuple> = vec![]; |
266 let syntax = syntax.trim(); |
264 let syntax = syntax.trim(); |
267 |
265 |
268 if let Some(rel_syntax) = SYNTAXES.get(syntax) { |
266 if let Some(rel_syntax) = SYNTAXES.get(syntax) { |
269 current_syntax = rel_syntax; |
267 current_syntax = rel_syntax; |
270 } else if warn { |
268 } else if warn { |
271 warnings.push((file_path.to_owned(), syntax.to_owned())); |
269 warnings |
|
270 .push((file_path.as_ref().to_owned(), syntax.to_owned())); |
272 } |
271 } |
273 continue; |
272 continue; |
274 } |
273 } |
275 |
274 |
276 let mut line_syntax: &[u8] = ¤t_syntax; |
275 let mut line_syntax: &[u8] = ¤t_syntax; |
295 )); |
294 )); |
296 } |
295 } |
297 (inputs, warnings) |
296 (inputs, warnings) |
298 } |
297 } |
299 |
298 |
300 pub fn read_pattern_file( |
299 pub fn read_pattern_file<P: AsRef<Path>>( |
301 file_path: &[u8], |
300 file_path: P, |
302 warn: bool, |
301 warn: bool, |
303 ) -> Result<(Vec<PatternTuple>, Vec<WarningTuple>), PatternFileError> { |
302 ) -> Result<(Vec<PatternTuple>, Vec<WarningTuple>), PatternFileError> { |
304 let mut f = File::open(get_path_from_bytes(file_path))?; |
303 let mut f = File::open(file_path.as_ref())?; |
305 let mut contents = Vec::new(); |
304 let mut contents = Vec::new(); |
306 |
305 |
307 f.read_to_end(&mut contents)?; |
306 f.read_to_end(&mut contents)?; |
308 |
307 |
309 Ok(parse_pattern_file_contents(&contents, file_path, warn)) |
308 Ok(parse_pattern_file_contents(&contents, file_path, warn)) |
341 fn test_parse_pattern_file_contents() { |
340 fn test_parse_pattern_file_contents() { |
342 let lines = b"syntax: glob\n*.elc"; |
341 let lines = b"syntax: glob\n*.elc"; |
343 |
342 |
344 assert_eq!( |
343 assert_eq!( |
345 vec![(b"relglob:*.elc".to_vec(), 2, b"*.elc".to_vec())], |
344 vec![(b"relglob:*.elc".to_vec(), 2, b"*.elc".to_vec())], |
346 parse_pattern_file_contents(lines, b"file_path", false).0, |
345 parse_pattern_file_contents(lines, Path::new("file_path"), false) |
|
346 .0, |
347 ); |
347 ); |
348 |
348 |
349 let lines = b"syntax: include\nsyntax: glob"; |
349 let lines = b"syntax: include\nsyntax: glob"; |
350 |
350 |
351 assert_eq!( |
351 assert_eq!( |
352 parse_pattern_file_contents(lines, b"file_path", false).0, |
352 parse_pattern_file_contents(lines, Path::new("file_path"), false) |
|
353 .0, |
353 vec![] |
354 vec![] |
354 ); |
355 ); |
355 let lines = b"glob:**.o"; |
356 let lines = b"glob:**.o"; |
356 assert_eq!( |
357 assert_eq!( |
357 parse_pattern_file_contents(lines, b"file_path", false).0, |
358 parse_pattern_file_contents(lines, Path::new("file_path"), false) |
|
359 .0, |
358 vec![(b"relglob:**.o".to_vec(), 1, b"**.o".to_vec())] |
360 vec![(b"relglob:**.o".to_vec(), 1, b"**.o".to_vec())] |
359 ); |
361 ); |
360 } |
362 } |
361 |
363 |
362 #[test] |
364 #[test] |