15 }, |
15 }, |
16 FastHashMap, PatternError, |
16 FastHashMap, PatternError, |
17 }; |
17 }; |
18 use lazy_static::lazy_static; |
18 use lazy_static::lazy_static; |
19 use regex::bytes::{NoExpand, Regex}; |
19 use regex::bytes::{NoExpand, Regex}; |
20 use std::fs::File; |
|
21 use std::io::Read; |
|
22 use std::ops::Deref; |
20 use std::ops::Deref; |
23 use std::path::{Path, PathBuf}; |
21 use std::path::{Path, PathBuf}; |
24 use std::vec::Vec; |
22 use std::vec::Vec; |
25 |
23 |
26 lazy_static! { |
24 lazy_static! { |
408 } |
406 } |
409 |
407 |
410 pub fn read_pattern_file( |
408 pub fn read_pattern_file( |
411 file_path: &Path, |
409 file_path: &Path, |
412 warn: bool, |
410 warn: bool, |
|
411 inspect_pattern_bytes: &mut impl FnMut(&[u8]), |
413 ) -> Result<(Vec<IgnorePattern>, Vec<PatternFileWarning>), PatternError> { |
412 ) -> Result<(Vec<IgnorePattern>, Vec<PatternFileWarning>), PatternError> { |
414 let mut f = match File::open(file_path) { |
413 match std::fs::read(file_path) { |
415 Ok(f) => Ok(f), |
414 Ok(contents) => { |
416 Err(e) => match e.kind() { |
415 inspect_pattern_bytes(&contents); |
417 std::io::ErrorKind::NotFound => { |
416 parse_pattern_file_contents(&contents, file_path, warn) |
418 return Ok(( |
417 } |
419 vec![], |
418 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(( |
420 vec![PatternFileWarning::NoSuchFile(file_path.to_owned())], |
419 vec![], |
421 )) |
420 vec![PatternFileWarning::NoSuchFile(file_path.to_owned())], |
422 } |
421 )), |
423 _ => Err(e), |
422 Err(e) => Err(e.into()), |
424 }, |
423 } |
425 }?; |
|
426 let mut contents = Vec::new(); |
|
427 |
|
428 f.read_to_end(&mut contents)?; |
|
429 |
|
430 Ok(parse_pattern_file_contents(&contents, file_path, warn)?) |
|
431 } |
424 } |
432 |
425 |
433 /// Represents an entry in an "ignore" file. |
426 /// Represents an entry in an "ignore" file. |
434 #[derive(Debug, Eq, PartialEq, Clone)] |
427 #[derive(Debug, Eq, PartialEq, Clone)] |
435 pub struct IgnorePattern { |
428 pub struct IgnorePattern { |
456 /// The former are expanded in place, while `PatternSyntax::ExpandedSubInclude` |
449 /// The former are expanded in place, while `PatternSyntax::ExpandedSubInclude` |
457 /// is used for the latter to form a tree of patterns. |
450 /// is used for the latter to form a tree of patterns. |
458 pub fn get_patterns_from_file( |
451 pub fn get_patterns_from_file( |
459 pattern_file: &Path, |
452 pattern_file: &Path, |
460 root_dir: &Path, |
453 root_dir: &Path, |
|
454 inspect_pattern_bytes: &mut impl FnMut(&[u8]), |
461 ) -> PatternResult<(Vec<IgnorePattern>, Vec<PatternFileWarning>)> { |
455 ) -> PatternResult<(Vec<IgnorePattern>, Vec<PatternFileWarning>)> { |
462 let (patterns, mut warnings) = read_pattern_file(pattern_file, true)?; |
456 let (patterns, mut warnings) = |
|
457 read_pattern_file(pattern_file, true, inspect_pattern_bytes)?; |
463 let patterns = patterns |
458 let patterns = patterns |
464 .into_iter() |
459 .into_iter() |
465 .flat_map(|entry| -> PatternResult<_> { |
460 .flat_map(|entry| -> PatternResult<_> { |
466 Ok(match &entry.syntax { |
461 Ok(match &entry.syntax { |
467 PatternSyntax::Include => { |
462 PatternSyntax::Include => { |
468 let inner_include = |
463 let inner_include = |
469 root_dir.join(get_path_from_bytes(&entry.pattern)); |
464 root_dir.join(get_path_from_bytes(&entry.pattern)); |
470 let (inner_pats, inner_warnings) = |
465 let (inner_pats, inner_warnings) = get_patterns_from_file( |
471 get_patterns_from_file(&inner_include, root_dir)?; |
466 &inner_include, |
|
467 root_dir, |
|
468 inspect_pattern_bytes, |
|
469 )?; |
472 warnings.extend(inner_warnings); |
470 warnings.extend(inner_warnings); |
473 inner_pats |
471 inner_pats |
474 } |
472 } |
475 PatternSyntax::SubInclude => { |
473 PatternSyntax::SubInclude => { |
476 let mut sub_include = SubInclude::new( |
474 let mut sub_include = SubInclude::new( |
480 )?; |
478 )?; |
481 let (inner_patterns, inner_warnings) = |
479 let (inner_patterns, inner_warnings) = |
482 get_patterns_from_file( |
480 get_patterns_from_file( |
483 &sub_include.path, |
481 &sub_include.path, |
484 &sub_include.root, |
482 &sub_include.root, |
|
483 inspect_pattern_bytes, |
485 )?; |
484 )?; |
486 sub_include.included_patterns = inner_patterns; |
485 sub_include.included_patterns = inner_patterns; |
487 warnings.extend(inner_warnings); |
486 warnings.extend(inner_warnings); |
488 vec![IgnorePattern { |
487 vec![IgnorePattern { |
489 syntax: PatternSyntax::ExpandedSubInclude(Box::new( |
488 syntax: PatternSyntax::ExpandedSubInclude(Box::new( |