Mercurial > public > mercurial-scm > hg-stable
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( |