Show More
@@ -109,6 +109,10 b" pub type HgPathCow<'a> = Cow<'a, HgPath>" | |||
|
109 | 109 | /// A path with its computed ``Dispatch`` information |
|
110 | 110 | type DispatchedPath<'a> = (HgPathCow<'a>, Dispatch); |
|
111 | 111 | |
|
112 | /// The conversion from `HgPath` to a real fs path failed. | |
|
113 | /// `22` is the error code for "Invalid argument" | |
|
114 | const INVALID_PATH_DISPATCH: Dispatch = Dispatch::Bad(BadMatch::OsError(22)); | |
|
115 | ||
|
112 | 116 | /// Dates and times that are outside the 31-bit signed range are compared |
|
113 | 117 | /// modulo 2^31. This should prevent hg from behaving badly with very large |
|
114 | 118 | /// files or corrupt dates while still having a high probability of detecting |
@@ -217,6 +221,12 b' fn dispatch_missing(state: EntryState) -' | |||
|
217 | 221 | } |
|
218 | 222 | } |
|
219 | 223 | |
|
224 | fn dispatch_os_error(e: &std::io::Error) -> Dispatch { | |
|
225 | Dispatch::Bad(BadMatch::OsError( | |
|
226 | e.raw_os_error().expect("expected real OS error"), | |
|
227 | )) | |
|
228 | } | |
|
229 | ||
|
220 | 230 | lazy_static! { |
|
221 | 231 | static ref DEFAULT_WORK: HashSet<&'static HgPath> = { |
|
222 | 232 | let mut h = HashSet::new(); |
@@ -372,13 +382,18 b' where' | |||
|
372 | 382 | .file_set() |
|
373 | 383 | .unwrap_or(&DEFAULT_WORK) |
|
374 | 384 | .par_iter() |
|
375 |
.map(|&filename| -> Option< |
|
|
385 | .flat_map(|&filename| -> Option<_> { | |
|
376 | 386 | // TODO normalization |
|
377 | 387 | let normalized = filename; |
|
378 | 388 | |
|
379 | 389 | let buf = match hg_path_to_path_buf(normalized) { |
|
380 | 390 | Ok(x) => x, |
|
381 |
Err( |
|
|
391 | Err(_) => { | |
|
392 | return Some(( | |
|
393 | Cow::Borrowed(normalized), | |
|
394 | INVALID_PATH_DISPATCH, | |
|
395 | )) | |
|
396 | } | |
|
382 | 397 | }; |
|
383 | 398 | let target = self.root_dir.join(buf); |
|
384 | 399 | let st = target.symlink_metadata(); |
@@ -389,7 +404,7 b' where' | |||
|
389 | 404 | return if file_type.is_file() || file_type.is_symlink() |
|
390 | 405 | { |
|
391 | 406 | if let Some(entry) = in_dmap { |
|
392 |
return Some( |
|
|
407 | return Some(( | |
|
393 | 408 | Cow::Borrowed(normalized), |
|
394 | 409 | dispatch_found( |
|
395 | 410 | &normalized, |
@@ -398,26 +413,26 b' where' | |||
|
398 | 413 | &self.dmap.copy_map, |
|
399 | 414 | self.options, |
|
400 | 415 | ), |
|
401 |
)) |
|
|
416 | )); | |
|
402 | 417 | } |
|
403 |
Some( |
|
|
418 | Some(( | |
|
404 | 419 | Cow::Borrowed(normalized), |
|
405 | 420 | Dispatch::Unknown, |
|
406 |
)) |
|
|
421 | )) | |
|
407 | 422 | } else if file_type.is_dir() { |
|
408 | 423 | if self.options.collect_traversed_dirs { |
|
409 | 424 | traversed_sender |
|
410 | 425 | .send(normalized.to_owned()) |
|
411 | 426 | .expect("receiver should outlive sender"); |
|
412 | 427 | } |
|
413 |
Some( |
|
|
428 | Some(( | |
|
414 | 429 | Cow::Borrowed(normalized), |
|
415 | 430 | Dispatch::Directory { |
|
416 | 431 | was_file: in_dmap.is_some(), |
|
417 | 432 | }, |
|
418 |
)) |
|
|
433 | )) | |
|
419 | 434 | } else { |
|
420 |
Some( |
|
|
435 | Some(( | |
|
421 | 436 | Cow::Borrowed(normalized), |
|
422 | 437 | Dispatch::Bad(BadMatch::BadType( |
|
423 | 438 | // TODO do more than unknown |
@@ -428,22 +443,20 b' where' | |||
|
428 | 443 | // users. |
|
429 | 444 | BadType::Unknown, |
|
430 | 445 | )), |
|
431 |
)) |
|
|
446 | )) | |
|
432 | 447 | }; |
|
433 | 448 | } |
|
434 | 449 | Err(_) => { |
|
435 | 450 | if let Some(entry) = in_dmap { |
|
436 |
return Some( |
|
|
451 | return Some(( | |
|
437 | 452 | Cow::Borrowed(normalized), |
|
438 | 453 | dispatch_missing(entry.state), |
|
439 |
)) |
|
|
454 | )); | |
|
440 | 455 | } |
|
441 | 456 | } |
|
442 | 457 | }; |
|
443 | 458 | None |
|
444 | 459 | }) |
|
445 | .flatten() | |
|
446 | .filter_map(Result::ok) | |
|
447 | 460 | .partition(|(_, dispatch)| match dispatch { |
|
448 | 461 | Dispatch::Directory { .. } => true, |
|
449 | 462 | _ => false, |
@@ -462,7 +475,7 b' where' | |||
|
462 | 475 | old_results: &FastHashMap<HgPathCow<'a>, Dispatch>, |
|
463 | 476 | results: &mut Vec<DispatchedPath<'a>>, |
|
464 | 477 | traversed_sender: crossbeam::Sender<HgPathBuf>, |
|
465 | ) -> IoResult<()> { | |
|
478 | ) { | |
|
466 | 479 | // The traversal is done in parallel, so use a channel to gather |
|
467 | 480 | // entries. `crossbeam::Sender` is `Sync`, while `mpsc::Sender` |
|
468 | 481 | // is not. |
@@ -474,25 +487,17 b' where' | |||
|
474 | 487 | path, |
|
475 | 488 | &old_results, |
|
476 | 489 | traversed_sender, |
|
477 |
) |
|
|
490 | ); | |
|
478 | 491 | |
|
479 | 492 | // Disconnect the channel so the receiver stops waiting |
|
480 | 493 | drop(files_transmitter); |
|
481 | 494 | |
|
482 | // TODO don't collect. Find a way of replicating the behavior of | |
|
483 | // `itertools::process_results`, but for `rayon::ParallelIterator` | |
|
484 | let new_results: IoResult<Vec<(Cow<HgPath>, Dispatch)>> = | |
|
485 | files_receiver | |
|
486 | .into_iter() | |
|
487 | .map(|item| { | |
|
488 | let (f, d) = item?; | |
|
489 | Ok((Cow::Owned(f), d)) | |
|
490 | }) | |
|
491 | .collect(); | |
|
495 | let new_results = files_receiver | |
|
496 | .into_iter() | |
|
497 | .par_bridge() | |
|
498 | .map(|(f, d)| (Cow::Owned(f), d)); | |
|
492 | 499 | |
|
493 |
results.par_extend(new_results |
|
|
494 | ||
|
495 | Ok(()) | |
|
500 | results.par_extend(new_results); | |
|
496 | 501 | } |
|
497 | 502 | |
|
498 | 503 | /// Dispatch a single entry (file, folder, symlink...) found during |
@@ -501,7 +506,7 b' where' | |||
|
501 | 506 | fn handle_traversed_entry<'b>( |
|
502 | 507 | &'a self, |
|
503 | 508 | scope: &rayon::Scope<'b>, |
|
504 |
files_sender: &'b crossbeam::Sender< |
|
|
509 | files_sender: &'b crossbeam::Sender<(HgPathBuf, Dispatch)>, | |
|
505 | 510 | old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>, |
|
506 | 511 | filename: HgPathBuf, |
|
507 | 512 | dir_entry: DirEntry, |
@@ -534,7 +539,7 b' where' | |||
|
534 | 539 | { |
|
535 | 540 | let metadata = dir_entry.metadata()?; |
|
536 | 541 | files_sender |
|
537 |
.send( |
|
|
542 | .send(( | |
|
538 | 543 | filename.to_owned(), |
|
539 | 544 | dispatch_found( |
|
540 | 545 | &filename, |
@@ -543,7 +548,7 b' where' | |||
|
543 | 548 | &self.dmap.copy_map, |
|
544 | 549 | self.options, |
|
545 | 550 | ), |
|
546 |
)) |
|
|
551 | )) | |
|
547 | 552 | .unwrap(); |
|
548 | 553 | } |
|
549 | 554 | } else if (self.matcher.matches_everything() |
@@ -556,17 +561,17 b' where' | |||
|
556 | 561 | { |
|
557 | 562 | if self.options.list_ignored { |
|
558 | 563 | files_sender |
|
559 |
.send |
|
|
564 | .send((filename.to_owned(), Dispatch::Ignored)) | |
|
560 | 565 | .unwrap(); |
|
561 | 566 | } |
|
562 | 567 | } else if self.options.list_unknown { |
|
563 | 568 | files_sender |
|
564 |
.send |
|
|
569 | .send((filename.to_owned(), Dispatch::Unknown)) | |
|
565 | 570 | .unwrap(); |
|
566 | 571 | } |
|
567 | 572 | } else if self.is_ignored(&filename) && self.options.list_ignored { |
|
568 | 573 | files_sender |
|
569 |
.send |
|
|
574 | .send((filename.to_owned(), Dispatch::Ignored)) | |
|
570 | 575 | .unwrap(); |
|
571 | 576 | } |
|
572 | 577 | } else if let Some(entry) = entry_option { |
@@ -575,10 +580,7 b' where' | |||
|
575 | 580 | || self.matcher.matches(&filename) |
|
576 | 581 | { |
|
577 | 582 | files_sender |
|
578 | .send(Ok(( | |
|
579 | filename.to_owned(), | |
|
580 | dispatch_missing(entry.state), | |
|
581 | ))) | |
|
583 | .send((filename.to_owned(), dispatch_missing(entry.state))) | |
|
582 | 584 | .unwrap(); |
|
583 | 585 | } |
|
584 | 586 | } |
@@ -590,7 +592,7 b' where' | |||
|
590 | 592 | fn handle_traversed_dir<'b>( |
|
591 | 593 | &'a self, |
|
592 | 594 | scope: &rayon::Scope<'b>, |
|
593 |
files_sender: &'b crossbeam::Sender< |
|
|
595 | files_sender: &'b crossbeam::Sender<(HgPathBuf, Dispatch)>, | |
|
594 | 596 | old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>, |
|
595 | 597 | entry_option: Option<&'a DirstateEntry>, |
|
596 | 598 | directory: HgPathBuf, |
@@ -606,10 +608,10 b' where' | |||
|
606 | 608 | || self.matcher.matches(&directory) |
|
607 | 609 | { |
|
608 | 610 | files_sender |
|
609 |
.send( |
|
|
611 | .send(( | |
|
610 | 612 | directory.to_owned(), |
|
611 | 613 | dispatch_missing(entry.state), |
|
612 |
)) |
|
|
614 | )) | |
|
613 | 615 | .unwrap(); |
|
614 | 616 | } |
|
615 | 617 | } |
@@ -621,7 +623,6 b' where' | |||
|
621 | 623 | &old_results, |
|
622 | 624 | traversed_sender, |
|
623 | 625 | ) |
|
624 | .unwrap_or_else(|e| files_sender.send(Err(e)).unwrap()) | |
|
625 | 626 | } |
|
626 | 627 | }); |
|
627 | 628 | } |
@@ -630,11 +631,11 b' where' | |||
|
630 | 631 | /// entries in a separate thread. |
|
631 | 632 | fn traverse_dir( |
|
632 | 633 | &self, |
|
633 |
files_sender: &crossbeam::Sender< |
|
|
634 | files_sender: &crossbeam::Sender<(HgPathBuf, Dispatch)>, | |
|
634 | 635 | directory: impl AsRef<HgPath>, |
|
635 | 636 | old_results: &FastHashMap<Cow<HgPath>, Dispatch>, |
|
636 | 637 | traversed_sender: crossbeam::Sender<HgPathBuf>, |
|
637 | ) -> IoResult<()> { | |
|
638 | ) { | |
|
638 | 639 | let directory = directory.as_ref(); |
|
639 | 640 | |
|
640 | 641 | if self.options.collect_traversed_dirs { |
@@ -644,38 +645,33 b' where' | |||
|
644 | 645 | } |
|
645 | 646 | |
|
646 | 647 | let visit_entries = match self.matcher.visit_children_set(directory) { |
|
647 |
VisitChildrenSet::Empty => return |
|
|
648 | VisitChildrenSet::Empty => return, | |
|
648 | 649 | VisitChildrenSet::This | VisitChildrenSet::Recursive => None, |
|
649 | 650 | VisitChildrenSet::Set(set) => Some(set), |
|
650 | 651 | }; |
|
651 |
let buf = hg_path_to_path_buf(directory) |
|
|
652 | let buf = match hg_path_to_path_buf(directory) { | |
|
653 | Ok(b) => b, | |
|
654 | Err(_) => { | |
|
655 | files_sender | |
|
656 | .send((directory.to_owned(), INVALID_PATH_DISPATCH)) | |
|
657 | .expect("receiver should outlive sender"); | |
|
658 | return; | |
|
659 | } | |
|
660 | }; | |
|
652 | 661 | let dir_path = self.root_dir.join(buf); |
|
653 | 662 | |
|
654 | 663 | let skip_dot_hg = !directory.as_bytes().is_empty(); |
|
655 | 664 | let entries = match list_directory(dir_path, skip_dot_hg) { |
|
656 | 665 | Err(e) => { |
|
657 | return match e.kind() { | |
|
658 | ErrorKind::NotFound | ErrorKind::PermissionDenied => { | |
|
659 | files_sender | |
|
660 | .send(Ok(( | |
|
661 | directory.to_owned(), | |
|
662 | Dispatch::Bad(BadMatch::OsError( | |
|
663 | // Unwrapping here is OK because the error | |
|
664 | // always is a | |
|
665 | // real os error | |
|
666 | e.raw_os_error().unwrap(), | |
|
667 | )), | |
|
668 | ))) | |
|
669 | .expect("receiver should outlive sender"); | |
|
670 | Ok(()) | |
|
671 | } | |
|
672 | _ => Err(e), | |
|
673 | }; | |
|
666 | files_sender | |
|
667 | .send((directory.to_owned(), dispatch_os_error(&e))) | |
|
668 | .expect("receiver should outlive sender"); | |
|
669 | return; | |
|
674 | 670 | } |
|
675 | 671 | Ok(entries) => entries, |
|
676 | 672 | }; |
|
677 | 673 | |
|
678 |
rayon::scope(|scope| |
|
|
674 | rayon::scope(|scope| { | |
|
679 | 675 | for (filename, dir_entry) in entries { |
|
680 | 676 | if let Some(ref set) = visit_entries { |
|
681 | 677 | if !set.contains(filename.deref()) { |
@@ -690,17 +686,26 b' where' | |||
|
690 | 686 | }; |
|
691 | 687 | |
|
692 | 688 | if !old_results.contains_key(filename.deref()) { |
|
693 | self.handle_traversed_entry( | |
|
689 | match self.handle_traversed_entry( | |
|
694 | 690 | scope, |
|
695 | 691 | files_sender, |
|
696 | 692 | old_results, |
|
697 | 693 | filename, |
|
698 | 694 | dir_entry, |
|
699 | 695 | traversed_sender.clone(), |
|
700 |
) |
|
|
696 | ) { | |
|
697 | Err(e) => { | |
|
698 | files_sender | |
|
699 | .send(( | |
|
700 | directory.to_owned(), | |
|
701 | dispatch_os_error(&e), | |
|
702 | )) | |
|
703 | .expect("receiver should outlive sender"); | |
|
704 | } | |
|
705 | Ok(_) => {} | |
|
706 | } | |
|
701 | 707 | } |
|
702 | 708 | } |
|
703 | Ok(()) | |
|
704 | 709 | }) |
|
705 | 710 | } |
|
706 | 711 | |
@@ -716,14 +721,23 b' where' | |||
|
716 | 721 | .fs_iter(self.root_dir.clone()) |
|
717 | 722 | .par_bridge() |
|
718 | 723 | .filter(|(path, _)| self.matcher.matches(path)) |
|
719 |
. |
|
|
724 | .map(move |(filename, shortcut)| { | |
|
720 | 725 | let entry = match shortcut { |
|
721 | 726 | StatusShortcut::Entry(e) => e, |
|
722 | 727 | StatusShortcut::Dispatch(d) => { |
|
723 |
return |
|
|
728 | return (Cow::Owned(filename), d) | |
|
724 | 729 | } |
|
725 | 730 | }; |
|
726 |
let filename_as_path = hg_path_to_path_buf(&filename) |
|
|
731 | let filename_as_path = match hg_path_to_path_buf(&filename) | |
|
732 | { | |
|
733 | Ok(f) => f, | |
|
734 | Err(_) => { | |
|
735 | return ( | |
|
736 | Cow::Owned(filename), | |
|
737 | INVALID_PATH_DISPATCH, | |
|
738 | ) | |
|
739 | } | |
|
740 | }; | |
|
727 | 741 | let meta = self |
|
728 | 742 | .root_dir |
|
729 | 743 | .join(filename_as_path) |
@@ -734,10 +748,10 b' where' | |||
|
734 | 748 | if !(m.file_type().is_file() |
|
735 | 749 | || m.file_type().is_symlink()) => |
|
736 | 750 | { |
|
737 |
|
|
|
751 | ( | |
|
738 | 752 | Cow::Owned(filename), |
|
739 | 753 | dispatch_missing(entry.state), |
|
740 |
) |
|
|
754 | ) | |
|
741 | 755 | } |
|
742 | 756 | Ok(m) => { |
|
743 | 757 | let dispatch = dispatch_found( |
@@ -747,7 +761,7 b' where' | |||
|
747 | 761 | &self.dmap.copy_map, |
|
748 | 762 | self.options, |
|
749 | 763 | ); |
|
750 |
|
|
|
764 | (Cow::Owned(filename), dispatch) | |
|
751 | 765 | } |
|
752 | 766 | Err(e) |
|
753 | 767 | if e.kind() == ErrorKind::NotFound |
@@ -758,12 +772,14 b' where' | |||
|
758 | 772 | // It happens if the dirstate contains `foo/bar` |
|
759 | 773 | // and foo is not a |
|
760 | 774 | // directory |
|
761 |
|
|
|
775 | ( | |
|
762 | 776 | Cow::Owned(filename), |
|
763 | 777 | dispatch_missing(entry.state), |
|
764 |
) |
|
|
778 | ) | |
|
765 | 779 | } |
|
766 |
Err(e) => |
|
|
780 | Err(e) => { | |
|
781 | (Cow::Owned(filename), dispatch_os_error(&e)) | |
|
782 | } | |
|
767 | 783 | } |
|
768 | 784 | }), |
|
769 | 785 | ); |
@@ -776,10 +792,18 b' where' | |||
|
776 | 792 | #[cfg(not(feature = "dirstate-tree"))] |
|
777 | 793 | #[timed] |
|
778 | 794 | pub fn extend_from_dmap(&self, results: &mut Vec<DispatchedPath<'a>>) { |
|
779 |
results.par_extend(self.dmap.par_iter(). |
|
|
795 | results.par_extend(self.dmap.par_iter().map( | |
|
780 | 796 | move |(filename, entry)| { |
|
781 | 797 | let filename: &HgPath = filename; |
|
782 |
let filename_as_path = hg_path_to_path_buf(filename) |
|
|
798 | let filename_as_path = match hg_path_to_path_buf(filename) { | |
|
799 | Ok(f) => f, | |
|
800 | Err(_) => { | |
|
801 | return ( | |
|
802 | Cow::Borrowed(filename), | |
|
803 | INVALID_PATH_DISPATCH, | |
|
804 | ) | |
|
805 | } | |
|
806 | }; | |
|
783 | 807 | let meta = |
|
784 | 808 | self.root_dir.join(filename_as_path).symlink_metadata(); |
|
785 | 809 | match meta { |
@@ -787,12 +811,12 b' where' | |||
|
787 | 811 | if !(m.file_type().is_file() |
|
788 | 812 | || m.file_type().is_symlink()) => |
|
789 | 813 | { |
|
790 |
|
|
|
814 | ( | |
|
791 | 815 | Cow::Borrowed(filename), |
|
792 | 816 | dispatch_missing(entry.state), |
|
793 |
) |
|
|
817 | ) | |
|
794 | 818 | } |
|
795 |
Ok(m) => |
|
|
819 | Ok(m) => ( | |
|
796 | 820 | Cow::Borrowed(filename), |
|
797 | 821 | dispatch_found( |
|
798 | 822 | filename, |
@@ -801,7 +825,7 b' where' | |||
|
801 | 825 | &self.dmap.copy_map, |
|
802 | 826 | self.options, |
|
803 | 827 | ), |
|
804 |
) |
|
|
828 | ), | |
|
805 | 829 | Err(e) |
|
806 | 830 | if e.kind() == ErrorKind::NotFound |
|
807 | 831 | || e.raw_os_error() == Some(20) => |
@@ -811,12 +835,12 b' where' | |||
|
811 | 835 | // It happens if the dirstate contains `foo/bar` |
|
812 | 836 | // and foo is not a |
|
813 | 837 | // directory |
|
814 |
|
|
|
838 | ( | |
|
815 | 839 | Cow::Borrowed(filename), |
|
816 | 840 | dispatch_missing(entry.state), |
|
817 |
) |
|
|
841 | ) | |
|
818 | 842 | } |
|
819 |
Err(e) => |
|
|
843 | Err(e) => (Cow::Borrowed(filename), dispatch_os_error(&e)), | |
|
820 | 844 | } |
|
821 | 845 | }, |
|
822 | 846 | )); |
@@ -830,10 +854,7 b' where' | |||
|
830 | 854 | /// `extend` in timings |
|
831 | 855 | #[cfg(not(feature = "dirstate-tree"))] |
|
832 | 856 | #[timed] |
|
833 | pub fn handle_unknowns( | |
|
834 | &self, | |
|
835 | results: &mut Vec<DispatchedPath<'a>>, | |
|
836 | ) -> IoResult<()> { | |
|
857 | pub fn handle_unknowns(&self, results: &mut Vec<DispatchedPath<'a>>) { | |
|
837 | 858 | let to_visit: Vec<(&HgPath, &DirstateEntry)> = |
|
838 | 859 | if results.is_empty() && self.matcher.matches_everything() { |
|
839 | 860 | self.dmap.iter().map(|(f, e)| (f.deref(), e)).collect() |
@@ -857,21 +878,23 b' where' | |||
|
857 | 878 | |
|
858 | 879 | let path_auditor = PathAuditor::new(&self.root_dir); |
|
859 | 880 | |
|
860 | // TODO don't collect. Find a way of replicating the behavior of | |
|
861 | // `itertools::process_results`, but for `rayon::ParallelIterator` | |
|
862 | let new_results: IoResult<Vec<_>> = to_visit | |
|
863 | .into_par_iter() | |
|
864 | .filter_map(|(filename, entry)| -> Option<IoResult<_>> { | |
|
881 | let new_results = to_visit.into_par_iter().filter_map( | |
|
882 | |(filename, entry)| -> Option<_> { | |
|
865 | 883 | // Report ignored items in the dmap as long as they are not |
|
866 | 884 | // under a symlink directory. |
|
867 | 885 | if path_auditor.check(filename) { |
|
868 | 886 | // TODO normalize for case-insensitive filesystems |
|
869 | 887 | let buf = match hg_path_to_path_buf(filename) { |
|
870 | 888 | Ok(x) => x, |
|
871 |
Err( |
|
|
889 | Err(_) => { | |
|
890 | return Some(( | |
|
891 | Cow::Owned(filename.to_owned()), | |
|
892 | INVALID_PATH_DISPATCH, | |
|
893 | )); | |
|
894 | } | |
|
872 | 895 | }; |
|
873 |
Some( |
|
|
874 |
Cow:: |
|
|
896 | Some(( | |
|
897 | Cow::Owned(filename.to_owned()), | |
|
875 | 898 | match self.root_dir.join(&buf).symlink_metadata() { |
|
876 | 899 | // File was just ignored, no links, and exists |
|
877 | 900 | Ok(meta) => { |
@@ -887,21 +910,19 b' where' | |||
|
887 | 910 | // File doesn't exist |
|
888 | 911 | Err(_) => dispatch_missing(entry.state), |
|
889 | 912 | }, |
|
890 |
)) |
|
|
913 | )) | |
|
891 | 914 | } else { |
|
892 | 915 | // It's either missing or under a symlink directory which |
|
893 | 916 | // we, in this case, report as missing. |
|
894 |
Some( |
|
|
895 |
Cow:: |
|
|
917 | Some(( | |
|
918 | Cow::Owned(filename.to_owned()), | |
|
896 | 919 | dispatch_missing(entry.state), |
|
897 |
)) |
|
|
920 | )) | |
|
898 | 921 | } |
|
899 |
} |
|
|
900 |
|
|
|
922 | }, | |
|
923 | ); | |
|
901 | 924 | |
|
902 |
results.par_extend(new_results |
|
|
903 | ||
|
904 | Ok(()) | |
|
925 | results.par_extend(new_results); | |
|
905 | 926 | } |
|
906 | 927 | } |
|
907 | 928 |
@@ -56,7 +56,7 b" impl<'a, M: Matcher + Sync> Status<'a, M" | |||
|
56 | 56 | .expect("old results should exist"), |
|
57 | 57 | &mut results, |
|
58 | 58 | traversed_sender.clone(), |
|
59 |
) |
|
|
59 | ); | |
|
60 | 60 | } |
|
61 | 61 | } |
|
62 | 62 | _ => { |
@@ -104,7 +104,7 b" impl<'a, M: Matcher + Sync> Status<'a, M" | |||
|
104 | 104 | &old_results, |
|
105 | 105 | &mut results, |
|
106 | 106 | traversed_sender.clone(), |
|
107 |
) |
|
|
107 | ); | |
|
108 | 108 | } |
|
109 | 109 | } |
|
110 | 110 | _ => { |
@@ -116,7 +116,7 b" impl<'a, M: Matcher + Sync> Status<'a, M" | |||
|
116 | 116 | |
|
117 | 117 | if !self.matcher.is_exact() { |
|
118 | 118 | if self.options.list_unknown { |
|
119 |
self.handle_unknowns(&mut results) |
|
|
119 | self.handle_unknowns(&mut results); | |
|
120 | 120 | } else { |
|
121 | 121 | // TODO this is incorrect, see issue6335 |
|
122 | 122 | // This requires a fix in both Python and Rust that can happen |
General Comments 0
You need to be logged in to leave comments.
Login now