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