##// 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 dmap: &'a DirstateMap,
221 dmap: &'a DirstateMap,
222 root_dir: impl AsRef<Path> + Sync + Send + 'a,
222 root_dir: impl AsRef<Path> + Sync + Send + 'a,
223 options: StatusOptions,
223 options: StatusOptions,
224 traversed_sender: crossbeam::Sender<HgPathBuf>,
224 ) -> impl ParallelIterator<Item = IoResult<(&'a HgPath, Dispatch)>> {
225 ) -> impl ParallelIterator<Item = IoResult<(&'a HgPath, Dispatch)>> {
225 files
226 files
226 .unwrap_or(&DEFAULT_WORK)
227 .unwrap_or(&DEFAULT_WORK)
@@ -255,6 +256,13 b" fn walk_explicit<'a>("
255 Some(Ok((normalized, Dispatch::Unknown)))
256 Some(Ok((normalized, Dispatch::Unknown)))
256 } else {
257 } else {
257 if file_type.is_dir() {
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 Some(Ok((
266 Some(Ok((
259 normalized,
267 normalized,
260 Dispatch::Directory {
268 Dispatch::Directory {
@@ -302,6 +310,9 b' pub struct StatusOptions {'
302 pub list_clean: bool,
310 pub list_clean: bool,
303 pub list_unknown: bool,
311 pub list_unknown: bool,
304 pub list_ignored: bool,
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 /// Dispatch a single entry (file, folder, symlink...) found during `traverse`.
318 /// Dispatch a single entry (file, folder, symlink...) found during `traverse`.
@@ -319,6 +330,7 b" fn handle_traversed_entry<'a>("
319 options: StatusOptions,
330 options: StatusOptions,
320 filename: HgPathBuf,
331 filename: HgPathBuf,
321 dir_entry: DirEntry,
332 dir_entry: DirEntry,
333 traversed_sender: crossbeam::Sender<HgPathBuf>,
322 ) -> IoResult<()> {
334 ) -> IoResult<()> {
323 let file_type = dir_entry.file_type()?;
335 let file_type = dir_entry.file_type()?;
324 let entry_option = dmap.get(&filename);
336 let entry_option = dmap.get(&filename);
@@ -341,6 +353,7 b" fn handle_traversed_entry<'a>("
341 options,
353 options,
342 entry_option,
354 entry_option,
343 filename,
355 filename,
356 traversed_sender,
344 );
357 );
345 } else if file_type.is_file() || file_type.is_symlink() {
358 } else if file_type.is_file() || file_type.is_symlink() {
346 if let Some(entry) = entry_option {
359 if let Some(entry) = entry_option {
@@ -407,6 +420,7 b" fn handle_traversed_dir<'a>("
407 options: StatusOptions,
420 options: StatusOptions,
408 entry_option: Option<&'a DirstateEntry>,
421 entry_option: Option<&'a DirstateEntry>,
409 directory: HgPathBuf,
422 directory: HgPathBuf,
423 traversed_sender: crossbeam::Sender<HgPathBuf>,
410 ) {
424 ) {
411 scope.spawn(move |_| {
425 scope.spawn(move |_| {
412 // Nested `if` until `rust-lang/rust#53668` is stable
426 // Nested `if` until `rust-lang/rust#53668` is stable
@@ -433,6 +447,7 b" fn handle_traversed_dir<'a>("
433 ignore_fn,
447 ignore_fn,
434 dir_ignore_fn,
448 dir_ignore_fn,
435 options,
449 options,
450 traversed_sender,
436 )
451 )
437 .unwrap_or_else(|e| files_sender.send(Err(e)).unwrap())
452 .unwrap_or_else(|e| files_sender.send(Err(e)).unwrap())
438 }
453 }
@@ -451,9 +466,15 b" fn traverse_dir<'a>("
451 ignore_fn: &IgnoreFnType,
466 ignore_fn: &IgnoreFnType,
452 dir_ignore_fn: &IgnoreFnType,
467 dir_ignore_fn: &IgnoreFnType,
453 options: StatusOptions,
468 options: StatusOptions,
469 traversed_sender: crossbeam::Sender<HgPathBuf>,
454 ) -> IoResult<()> {
470 ) -> IoResult<()> {
455 let directory = directory.as_ref();
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 let visit_entries = match matcher.visit_children_set(directory) {
478 let visit_entries = match matcher.visit_children_set(directory) {
458 VisitChildrenSet::Empty => return Ok(()),
479 VisitChildrenSet::Empty => return Ok(()),
459 VisitChildrenSet::This | VisitChildrenSet::Recursive => None,
480 VisitChildrenSet::This | VisitChildrenSet::Recursive => None,
@@ -510,6 +531,7 b" fn traverse_dir<'a>("
510 options,
531 options,
511 filename,
532 filename,
512 dir_entry,
533 dir_entry,
534 traversed_sender.clone(),
513 )?;
535 )?;
514 }
536 }
515 }
537 }
@@ -533,6 +555,7 b" fn traverse<'a>("
533 dir_ignore_fn: &IgnoreFnType,
555 dir_ignore_fn: &IgnoreFnType,
534 options: StatusOptions,
556 options: StatusOptions,
535 results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
557 results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
558 traversed_sender: crossbeam::Sender<HgPathBuf>,
536 ) -> IoResult<()> {
559 ) -> IoResult<()> {
537 let root_dir = root_dir.as_ref();
560 let root_dir = root_dir.as_ref();
538
561
@@ -550,6 +573,7 b" fn traverse<'a>("
550 &ignore_fn,
573 &ignore_fn,
551 &dir_ignore_fn,
574 &dir_ignore_fn,
552 options,
575 options,
576 traversed_sender,
553 )?;
577 )?;
554
578
555 // Disconnect the channel so the receiver stops waiting
579 // Disconnect the channel so the receiver stops waiting
@@ -640,11 +664,14 b" pub struct DirstateStatus<'a> {"
640 pub ignored: Vec<Cow<'a, HgPath>>,
664 pub ignored: Vec<Cow<'a, HgPath>>,
641 pub unknown: Vec<Cow<'a, HgPath>>,
665 pub unknown: Vec<Cow<'a, HgPath>>,
642 pub bad: Vec<(Cow<'a, HgPath>, BadMatch)>,
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 #[timed]
671 #[timed]
646 fn build_response<'a>(
672 fn build_response<'a>(
647 results: impl IntoIterator<Item = (Cow<'a, HgPath>, Dispatch)>,
673 results: impl IntoIterator<Item = (Cow<'a, HgPath>, Dispatch)>,
674 traversed: Vec<HgPathBuf>,
648 ) -> (Vec<Cow<'a, HgPath>>, DirstateStatus<'a>) {
675 ) -> (Vec<Cow<'a, HgPath>>, DirstateStatus<'a>) {
649 let mut lookup = vec![];
676 let mut lookup = vec![];
650 let mut modified = vec![];
677 let mut modified = vec![];
@@ -683,6 +710,7 b" fn build_response<'a>("
683 ignored,
710 ignored,
684 unknown,
711 unknown,
685 bad,
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 let files = matcher.file_set();
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 // Step 1: check the files explicitly mentioned by the user
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 // Collect results into a `Vec` because we do very few lookups in most
892 // Collect results into a `Vec` because we do very few lookups in most
856 // cases.
893 // cases.
@@ -888,6 +925,7 b" pub fn status<'a: 'c, 'b: 'c, 'c>("
888 &dir_ignore_fn,
925 &dir_ignore_fn,
889 options,
926 options,
890 &mut results,
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