D8249: rust-status: refactor handling of unknown files
Closed by commit rHG5f6a504dc0bd: rust-status: refactor handling of unknown files (authored by Alphare). This revision was automatically updated to reflect the committed changes. This revision was not accepted when it landed; it landed in state "Needs Review". REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D8249?vs=20563=20730 CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D8249/new/ REVISION DETAIL https://phab.mercurial-scm.org/D8249 AFFECTED FILES rust/hg-core/src/dirstate/status.rs CHANGE DETAILS diff --git a/rust/hg-core/src/dirstate/status.rs b/rust/hg-core/src/dirstate/status.rs --- a/rust/hg-core/src/dirstate/status.rs +++ b/rust/hg-core/src/dirstate/status.rs @@ -597,6 +597,85 @@ } } +/// This takes a mutable reference to the results to account for the `extend` +/// in timings +fn handle_unknowns<'a>( +dmap: &'a DirstateMap, +matcher: &(impl Matcher + Sync), +root_dir: impl AsRef + Sync + Send + Copy, +options: StatusOptions, +results: Vec<(Cow<'a, HgPath>, Dispatch)>, +) -> IoResult<()> { +let to_visit: Vec<(, )> = if results.is_empty() +&& matcher.matches_everything() +{ +dmap.iter().map(|(f, e)| (f.deref(), e)).collect() +} else { +// Only convert to a hashmap if needed. +let old_results: FastHashMap<_, _> = results.iter().cloned().collect(); +dmap.iter() +.filter_map(move |(f, e)| { +if !old_results.contains_key(f.deref()) && matcher.matches(f) { +Some((f.deref(), e)) +} else { +None +} +}) +.collect() +}; + +// We walked all dirs under the roots that weren't ignored, and +// everything that matched was stat'ed and is already in results. +// The rest must thus be ignored or under a symlink. +let path_auditor = PathAuditor::new(root_dir); + +// TODO don't collect. Find a way of replicating the behavior of +// `itertools::process_results`, but for `rayon::ParallelIterator` +let new_results: IoResult> = to_visit +.into_par_iter() +.filter_map(|(filename, entry)| -> Option> { +// Report ignored items in the dmap as long as they are not +// under a symlink directory. +if path_auditor.check(filename) { +// TODO normalize for case-insensitive filesystems +let buf = match hg_path_to_path_buf(filename) { +Ok(x) => x, +Err(e) => return Some(Err(e.into())), +}; +Some(Ok(( +Cow::Borrowed(filename), +match root_dir.as_ref().join().symlink_metadata() { +// File was just ignored, no links, and exists +Ok(meta) => { +let metadata = HgMetadata::from_metadata(meta); +dispatch_found( +filename, +*entry, +metadata, +_map, +options, +) +} +// File doesn't exist +Err(_) => dispatch_missing(entry.state), +}, +))) +} else { +// It's either missing or under a symlink directory which +// we, in this case, report as missing. +Some(Ok(( +Cow::Borrowed(filename), +dispatch_missing(entry.state), +))) +} +}) +.collect(); + +results.par_extend(new_results?); + +Ok(()) +} + /// Get the status of files in the working directory. /// /// This is the current entry-point for `hg-core` and is realistically unusable @@ -683,64 +762,7 @@ // symlink directory. if options.list_unknown { -let to_visit: Box> = -if results.is_empty() && matcher.matches_everything() { -Box::new(dmap.iter().map(|(f, e)| (f.deref(), e))) -} else { -// Only convert to a hashmap if needed. -let old_results: FastHashMap<_, _> = -results.iter().cloned().collect(); -Box::new(dmap.iter().filter_map(move |(f, e)| { -if !old_results.contains_key(f.deref()) -&& matcher.matches(f) -{ -Some((f.deref(), e)) -} else { -None -} -})) -}; -let mut to_visit: Vec<_> = to_visit.collect(); -to_visit.sort_by(|a, b| a.0.cmp()); - -//
D8249: rust-status: refactor handling of unknown files
Alphare created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D8249 AFFECTED FILES rust/hg-core/src/dirstate/status.rs CHANGE DETAILS diff --git a/rust/hg-core/src/dirstate/status.rs b/rust/hg-core/src/dirstate/status.rs --- a/rust/hg-core/src/dirstate/status.rs +++ b/rust/hg-core/src/dirstate/status.rs @@ -597,6 +597,85 @@ } } +/// This takes a mutable reference to the results to account for the `extend` +/// in timings +fn handle_unknowns<'a>( +dmap: &'a DirstateMap, +matcher: &(impl Matcher + Sync), +root_dir: impl AsRef + Sync + Send + Copy, +options: StatusOptions, +results: Vec<(Cow<'a, HgPath>, Dispatch)>, +) -> IoResult<()> { +let to_visit: Vec<(, )> = if results.is_empty() +&& matcher.matches_everything() +{ +dmap.iter().map(|(f, e)| (f.deref(), e)).collect() +} else { +// Only convert to a hashmap if needed. +let old_results: FastHashMap<_, _> = results.iter().cloned().collect(); +dmap.iter() +.filter_map(move |(f, e)| { +if !old_results.contains_key(f.deref()) && matcher.matches(f) { +Some((f.deref(), e)) +} else { +None +} +}) +.collect() +}; + +// We walked all dirs under the roots that weren't ignored, and +// everything that matched was stat'ed and is already in results. +// The rest must thus be ignored or under a symlink. +let path_auditor = PathAuditor::new(root_dir); + +// TODO don't collect. Find a way of replicating the behavior of +// `itertools::process_results`, but for `rayon::ParallelIterator` +let new_results: IoResult> = to_visit +.into_par_iter() +.filter_map(|(filename, entry)| -> Option> { +// Report ignored items in the dmap as long as they are not +// under a symlink directory. +if path_auditor.check(filename) { +// TODO normalize for case-insensitive filesystems +let buf = match hg_path_to_path_buf(filename) { +Ok(x) => x, +Err(e) => return Some(Err(e.into())), +}; +Some(Ok(( +Cow::Borrowed(filename), +match root_dir.as_ref().join().symlink_metadata() { +// File was just ignored, no links, and exists +Ok(meta) => { +let metadata = HgMetadata::from_metadata(meta); +dispatch_found( +filename, +*entry, +metadata, +_map, +options, +) +} +// File doesn't exist +Err(_) => dispatch_missing(entry.state), +}, +))) +} else { +// It's either missing or under a symlink directory which +// we, in this case, report as missing. +Some(Ok(( +Cow::Borrowed(filename), +dispatch_missing(entry.state), +))) +} +}) +.collect(); + +results.par_extend(new_results?); + +Ok(()) +} + /// Get the status of files in the working directory. /// /// This is the current entry-point for `hg-core` and is realistically unusable @@ -683,64 +762,7 @@ // symlink directory. if options.list_unknown { -let to_visit: Box> = -if results.is_empty() && matcher.matches_everything() { -Box::new(dmap.iter().map(|(f, e)| (f.deref(), e))) -} else { -// Only convert to a hashmap if needed. -let old_results: FastHashMap<_, _> = -results.iter().cloned().collect(); -Box::new(dmap.iter().filter_map(move |(f, e)| { -if !old_results.contains_key(f.deref()) -&& matcher.matches(f) -{ -Some((f.deref(), e)) -} else { -None -} -})) -}; -let mut to_visit: Vec<_> = to_visit.collect(); -to_visit.sort_by(|a, b| a.0.cmp()); - -// We walked all dirs under the roots that weren't ignored, and -// everything that matched was stat'ed and is already in results. -// The rest must thus be ignored or under a symlink. -let path_auditor = PathAuditor::new(root_dir); - -