comparison rust/hg-core/src/filepatterns.rs @ 47415:0ef8231e413f

dirstate-v2: Store a hash of ignore patterns (.hgignore) Later, this help extend `read_dir` caching to directories that contain ignored files (but no unknown files). Such cache must be invalidated when ignore patterns change since a formerly-ignored file might become unknown. This helps the default configuration of `hg status` where unknown files must be listed, but ignored files are not. Differential Revision: https://phab.mercurial-scm.org/D10836
author Simon Sapin <simon.sapin@octobus.net>
date Wed, 02 Jun 2021 11:25:18 +0200
parents f6bb181c75f8
children 6d69e83e6b6e
comparison
equal deleted inserted replaced
47414:7954ee2d7cf7 47415:0ef8231e413f
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(