comparison rust/hg-core/src/filepatterns.rs @ 47378:777c3d231913

rust: Make some file path parameters less generic These are not widely used APIs that benefit from being maximally flexible, taking an explicit `&Path` borrow is fine and simplifies their internals. Differential Revision: https://phab.mercurial-scm.org/D10833
author Simon Sapin <simon.sapin@octobus.net>
date Wed, 02 Jun 2021 18:14:44 +0200
parents 26114bd6ec60
children f6bb181c75f8
comparison
equal deleted inserted replaced
47377:26127236b229 47378:777c3d231913
316 InvalidSyntax(PathBuf, Vec<u8>), 316 InvalidSyntax(PathBuf, Vec<u8>),
317 /// File path 317 /// File path
318 NoSuchFile(PathBuf), 318 NoSuchFile(PathBuf),
319 } 319 }
320 320
321 pub fn parse_pattern_file_contents<P: AsRef<Path>>( 321 pub fn parse_pattern_file_contents(
322 lines: &[u8], 322 lines: &[u8],
323 file_path: P, 323 file_path: &Path,
324 warn: bool, 324 warn: bool,
325 ) -> Result<(Vec<IgnorePattern>, Vec<PatternFileWarning>), PatternError> { 325 ) -> Result<(Vec<IgnorePattern>, Vec<PatternFileWarning>), PatternError> {
326 let comment_regex = Regex::new(r"((?:^|[^\\])(?:\\\\)*)#.*").unwrap(); 326 let comment_regex = Regex::new(r"((?:^|[^\\])(?:\\\\)*)#.*").unwrap();
327 327
328 #[allow(clippy::trivial_regex)] 328 #[allow(clippy::trivial_regex)]
355 355
356 if let Some(rel_syntax) = SYNTAXES.get(syntax) { 356 if let Some(rel_syntax) = SYNTAXES.get(syntax) {
357 current_syntax = rel_syntax; 357 current_syntax = rel_syntax;
358 } else if warn { 358 } else if warn {
359 warnings.push(PatternFileWarning::InvalidSyntax( 359 warnings.push(PatternFileWarning::InvalidSyntax(
360 file_path.as_ref().to_owned(), 360 file_path.to_owned(),
361 syntax.to_owned(), 361 syntax.to_owned(),
362 )); 362 ));
363 } 363 }
364 continue; 364 continue;
365 } 365 }
382 inputs.push(IgnorePattern::new( 382 inputs.push(IgnorePattern::new(
383 parse_pattern_syntax(&line_syntax).map_err(|e| match e { 383 parse_pattern_syntax(&line_syntax).map_err(|e| match e {
384 PatternError::UnsupportedSyntax(syntax) => { 384 PatternError::UnsupportedSyntax(syntax) => {
385 PatternError::UnsupportedSyntaxInFile( 385 PatternError::UnsupportedSyntaxInFile(
386 syntax, 386 syntax,
387 file_path.as_ref().to_string_lossy().into(), 387 file_path.to_string_lossy().into(),
388 line_number, 388 line_number,
389 ) 389 )
390 } 390 }
391 _ => e, 391 _ => e,
392 })?, 392 })?,
393 &line, 393 &line,
394 &file_path, 394 file_path,
395 )); 395 ));
396 } 396 }
397 Ok((inputs, warnings)) 397 Ok((inputs, warnings))
398 } 398 }
399 399
400 pub fn read_pattern_file<P: AsRef<Path>>( 400 pub fn read_pattern_file(
401 file_path: P, 401 file_path: &Path,
402 warn: bool, 402 warn: bool,
403 ) -> Result<(Vec<IgnorePattern>, Vec<PatternFileWarning>), PatternError> { 403 ) -> Result<(Vec<IgnorePattern>, Vec<PatternFileWarning>), PatternError> {
404 let mut f = match File::open(file_path.as_ref()) { 404 let mut f = match File::open(file_path) {
405 Ok(f) => Ok(f), 405 Ok(f) => Ok(f),
406 Err(e) => match e.kind() { 406 Err(e) => match e.kind() {
407 std::io::ErrorKind::NotFound => { 407 std::io::ErrorKind::NotFound => {
408 return Ok(( 408 return Ok((
409 vec![], 409 vec![],
410 vec![PatternFileWarning::NoSuchFile( 410 vec![PatternFileWarning::NoSuchFile(file_path.to_owned())],
411 file_path.as_ref().to_owned(),
412 )],
413 )) 411 ))
414 } 412 }
415 _ => Err(e), 413 _ => Err(e),
416 }, 414 },
417 }?; 415 }?;
429 pub pattern: Vec<u8>, 427 pub pattern: Vec<u8>,
430 pub source: PathBuf, 428 pub source: PathBuf,
431 } 429 }
432 430
433 impl IgnorePattern { 431 impl IgnorePattern {
434 pub fn new( 432 pub fn new(syntax: PatternSyntax, pattern: &[u8], source: &Path) -> Self {
435 syntax: PatternSyntax,
436 pattern: &[u8],
437 source: impl AsRef<Path>,
438 ) -> Self {
439 Self { 433 Self {
440 syntax, 434 syntax,
441 pattern: pattern.to_owned(), 435 pattern: pattern.to_owned(),
442 source: source.as_ref().to_owned(), 436 source: source.to_owned(),
443 } 437 }
444 } 438 }
445 } 439 }
446 440
447 pub type PatternResult<T> = Result<T, PatternError>; 441 pub type PatternResult<T> = Result<T, PatternError>;
450 /// patterns. 444 /// patterns.
451 /// 445 ///
452 /// `subinclude:` is not treated as a special pattern here: unraveling them 446 /// `subinclude:` is not treated as a special pattern here: unraveling them
453 /// needs to occur in the "ignore" phase. 447 /// needs to occur in the "ignore" phase.
454 pub fn get_patterns_from_file( 448 pub fn get_patterns_from_file(
455 pattern_file: impl AsRef<Path>, 449 pattern_file: &Path,
456 root_dir: impl AsRef<Path>, 450 root_dir: &Path,
457 ) -> PatternResult<(Vec<IgnorePattern>, Vec<PatternFileWarning>)> { 451 ) -> PatternResult<(Vec<IgnorePattern>, Vec<PatternFileWarning>)> {
458 let (patterns, mut warnings) = read_pattern_file(&pattern_file, true)?; 452 let (patterns, mut warnings) = read_pattern_file(pattern_file, true)?;
459 let patterns = patterns 453 let patterns = patterns
460 .into_iter() 454 .into_iter()
461 .flat_map(|entry| -> PatternResult<_> { 455 .flat_map(|entry| -> PatternResult<_> {
462 let IgnorePattern { 456 let IgnorePattern {
463 syntax, pattern, .. 457 syntax, pattern, ..
464 } = &entry; 458 } = &entry;
465 Ok(match syntax { 459 Ok(match syntax {
466 PatternSyntax::Include => { 460 PatternSyntax::Include => {
467 let inner_include = 461 let inner_include =
468 root_dir.as_ref().join(get_path_from_bytes(&pattern)); 462 root_dir.join(get_path_from_bytes(&pattern));
469 let (inner_pats, inner_warnings) = get_patterns_from_file( 463 let (inner_pats, inner_warnings) =
470 &inner_include, 464 get_patterns_from_file(&inner_include, root_dir)?;
471 root_dir.as_ref(),
472 )?;
473 warnings.extend(inner_warnings); 465 warnings.extend(inner_warnings);
474 inner_pats 466 inner_pats
475 } 467 }
476 _ => vec![entry], 468 _ => vec![entry],
477 }) 469 })
494 pub root: PathBuf, 486 pub root: PathBuf,
495 } 487 }
496 488
497 impl SubInclude { 489 impl SubInclude {
498 pub fn new( 490 pub fn new(
499 root_dir: impl AsRef<Path>, 491 root_dir: &Path,
500 pattern: &[u8], 492 pattern: &[u8],
501 source: impl AsRef<Path>, 493 source: &Path,
502 ) -> Result<SubInclude, HgPathError> { 494 ) -> Result<SubInclude, HgPathError> {
503 let normalized_source = 495 let normalized_source =
504 normalize_path_bytes(&get_bytes_from_path(source)); 496 normalize_path_bytes(&get_bytes_from_path(source));
505 497
506 let source_root = get_path_from_bytes(&normalized_source); 498 let source_root = get_path_from_bytes(&normalized_source);
508 source_root.parent().unwrap_or_else(|| source_root.deref()); 500 source_root.parent().unwrap_or_else(|| source_root.deref());
509 501
510 let path = source_root.join(get_path_from_bytes(pattern)); 502 let path = source_root.join(get_path_from_bytes(pattern));
511 let new_root = path.parent().unwrap_or_else(|| path.deref()); 503 let new_root = path.parent().unwrap_or_else(|| path.deref());
512 504
513 let prefix = canonical_path(&root_dir, &root_dir, new_root)?; 505 let prefix = canonical_path(root_dir, root_dir, new_root)?;
514 506
515 Ok(Self { 507 Ok(Self {
516 prefix: path_to_hg_path_buf(prefix).and_then(|mut p| { 508 prefix: path_to_hg_path_buf(prefix).and_then(|mut p| {
517 if !p.is_empty() { 509 if !p.is_empty() {
518 p.push(b'/'); 510 p.push(b'/');
525 } 517 }
526 } 518 }
527 519
528 /// Separate and pre-process subincludes from other patterns for the "ignore" 520 /// Separate and pre-process subincludes from other patterns for the "ignore"
529 /// phase. 521 /// phase.
530 pub fn filter_subincludes( 522 pub fn filter_subincludes<'a>(
531 ignore_patterns: &[IgnorePattern], 523 ignore_patterns: &'a [IgnorePattern],
532 root_dir: impl AsRef<Path>, 524 root_dir: &Path,
533 ) -> Result<(Vec<SubInclude>, Vec<&IgnorePattern>), HgPathError> { 525 ) -> Result<(Vec<SubInclude>, Vec<&'a IgnorePattern>), HgPathError> {
534 let mut subincludes = vec![]; 526 let mut subincludes = vec![];
535 let mut others = vec![]; 527 let mut others = vec![];
536 528
537 for ignore_pattern in ignore_patterns.iter() { 529 for ignore_pattern in ignore_patterns.iter() {
538 let IgnorePattern { 530 let IgnorePattern {
539 syntax, 531 syntax,
540 pattern, 532 pattern,
541 source, 533 source,
542 } = ignore_pattern; 534 } = ignore_pattern;
543 if *syntax == PatternSyntax::SubInclude { 535 if *syntax == PatternSyntax::SubInclude {
544 subincludes.push(SubInclude::new(&root_dir, pattern, &source)?); 536 subincludes.push(SubInclude::new(root_dir, pattern, &source)?);
545 } else { 537 } else {
546 others.push(ignore_pattern) 538 others.push(ignore_pattern)
547 } 539 }
548 } 540 }
549 Ok((subincludes, others)) 541 Ok((subincludes, others))