D8249: rust-status: refactor handling of unknown files

2020-03-11 Thread Raphaël Gomès
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

2020-03-06 Thread Raphaël Gomès
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);
-
-