##// END OF EJS Templates
rust-status: collect traversed directories if required...
Raphaël Gomès -
r45353:c802ec4f default
parent child Browse files
Show More
@@ -221,6 +221,7 b" fn walk_explicit<'a>("
221 221 dmap: &'a DirstateMap,
222 222 root_dir: impl AsRef<Path> + Sync + Send + 'a,
223 223 options: StatusOptions,
224 traversed_sender: crossbeam::Sender<HgPathBuf>,
224 225 ) -> impl ParallelIterator<Item = IoResult<(&'a HgPath, Dispatch)>> {
225 226 files
226 227 .unwrap_or(&DEFAULT_WORK)
@@ -255,6 +256,13 b" fn walk_explicit<'a>("
255 256 Some(Ok((normalized, Dispatch::Unknown)))
256 257 } else {
257 258 if file_type.is_dir() {
259 if options.collect_traversed_dirs {
260 // The receiver always outlives the sender,
261 // so unwrap.
262 traversed_sender
263 .send(normalized.to_owned())
264 .unwrap()
265 }
258 266 Some(Ok((
259 267 normalized,
260 268 Dispatch::Directory {
@@ -302,6 +310,9 b' pub struct StatusOptions {'
302 310 pub list_clean: bool,
303 311 pub list_unknown: bool,
304 312 pub list_ignored: bool,
313 /// Whether to collect traversed dirs for applying a callback later.
314 /// Used by `hg purge` for example.
315 pub collect_traversed_dirs: bool,
305 316 }
306 317
307 318 /// Dispatch a single entry (file, folder, symlink...) found during `traverse`.
@@ -319,6 +330,7 b" fn handle_traversed_entry<'a>("
319 330 options: StatusOptions,
320 331 filename: HgPathBuf,
321 332 dir_entry: DirEntry,
333 traversed_sender: crossbeam::Sender<HgPathBuf>,
322 334 ) -> IoResult<()> {
323 335 let file_type = dir_entry.file_type()?;
324 336 let entry_option = dmap.get(&filename);
@@ -341,6 +353,7 b" fn handle_traversed_entry<'a>("
341 353 options,
342 354 entry_option,
343 355 filename,
356 traversed_sender,
344 357 );
345 358 } else if file_type.is_file() || file_type.is_symlink() {
346 359 if let Some(entry) = entry_option {
@@ -407,6 +420,7 b" fn handle_traversed_dir<'a>("
407 420 options: StatusOptions,
408 421 entry_option: Option<&'a DirstateEntry>,
409 422 directory: HgPathBuf,
423 traversed_sender: crossbeam::Sender<HgPathBuf>,
410 424 ) {
411 425 scope.spawn(move |_| {
412 426 // Nested `if` until `rust-lang/rust#53668` is stable
@@ -433,6 +447,7 b" fn handle_traversed_dir<'a>("
433 447 ignore_fn,
434 448 dir_ignore_fn,
435 449 options,
450 traversed_sender,
436 451 )
437 452 .unwrap_or_else(|e| files_sender.send(Err(e)).unwrap())
438 453 }
@@ -451,9 +466,15 b" fn traverse_dir<'a>("
451 466 ignore_fn: &IgnoreFnType,
452 467 dir_ignore_fn: &IgnoreFnType,
453 468 options: StatusOptions,
469 traversed_sender: crossbeam::Sender<HgPathBuf>,
454 470 ) -> IoResult<()> {
455 471 let directory = directory.as_ref();
456 472
473 if options.collect_traversed_dirs {
474 // The receiver always outlives the sender, so unwrap.
475 traversed_sender.send(directory.to_owned()).unwrap()
476 }
477
457 478 let visit_entries = match matcher.visit_children_set(directory) {
458 479 VisitChildrenSet::Empty => return Ok(()),
459 480 VisitChildrenSet::This | VisitChildrenSet::Recursive => None,
@@ -510,6 +531,7 b" fn traverse_dir<'a>("
510 531 options,
511 532 filename,
512 533 dir_entry,
534 traversed_sender.clone(),
513 535 )?;
514 536 }
515 537 }
@@ -533,6 +555,7 b" fn traverse<'a>("
533 555 dir_ignore_fn: &IgnoreFnType,
534 556 options: StatusOptions,
535 557 results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
558 traversed_sender: crossbeam::Sender<HgPathBuf>,
536 559 ) -> IoResult<()> {
537 560 let root_dir = root_dir.as_ref();
538 561
@@ -550,6 +573,7 b" fn traverse<'a>("
550 573 &ignore_fn,
551 574 &dir_ignore_fn,
552 575 options,
576 traversed_sender,
553 577 )?;
554 578
555 579 // Disconnect the channel so the receiver stops waiting
@@ -640,11 +664,14 b" pub struct DirstateStatus<'a> {"
640 664 pub ignored: Vec<Cow<'a, HgPath>>,
641 665 pub unknown: Vec<Cow<'a, HgPath>>,
642 666 pub bad: Vec<(Cow<'a, HgPath>, BadMatch)>,
667 /// Only filled if `collect_traversed_dirs` is `true`
668 pub traversed: Vec<HgPathBuf>,
643 669 }
644 670
645 671 #[timed]
646 672 fn build_response<'a>(
647 673 results: impl IntoIterator<Item = (Cow<'a, HgPath>, Dispatch)>,
674 traversed: Vec<HgPathBuf>,
648 675 ) -> (Vec<Cow<'a, HgPath>>, DirstateStatus<'a>) {
649 676 let mut lookup = vec![];
650 677 let mut modified = vec![];
@@ -683,6 +710,7 b" fn build_response<'a>("
683 710 ignored,
684 711 unknown,
685 712 bad,
713 traversed,
686 714 },
687 715 )
688 716 }
@@ -849,8 +877,17 b" pub fn status<'a: 'c, 'b: 'c, 'c>("
849 877
850 878 let files = matcher.file_set();
851 879
880 // `crossbeam::Sender` is `Send`, while `mpsc::Sender` is not.
881 let (traversed_sender, traversed_recv) = crossbeam::channel::unbounded();
882
852 883 // Step 1: check the files explicitly mentioned by the user
853 let explicit = walk_explicit(files, &dmap, root_dir, options);
884 let explicit = walk_explicit(
885 files,
886 &dmap,
887 root_dir,
888 options,
889 traversed_sender.clone(),
890 );
854 891
855 892 // Collect results into a `Vec` because we do very few lookups in most
856 893 // cases.
@@ -888,6 +925,7 b" pub fn status<'a: 'c, 'b: 'c, 'c>("
888 925 &dir_ignore_fn,
889 926 options,
890 927 &mut results,
928 traversed_sender.clone(),
891 929 )?;
892 930 }
893 931 }
@@ -911,5 +949,9 b" pub fn status<'a: 'c, 'b: 'c, 'c>("
911 949 }
912 950 }
913 951
914 Ok((build_response(results), warnings))
952 // Close the channel
953 drop(traversed_sender);
954 let traversed_dirs = traversed_recv.into_iter().collect();
955
956 Ok((build_response(results, traversed_dirs), warnings))
915 957 }
General Comments 0
You need to be logged in to leave comments. Login now