[Request] [+-- ] D8663: hg-core: define a `dirstate_status` `Operation`
Alphare (Raphaël Gomès)
phabricator at mercurial-scm.org
Thu Jun 25 09:03:34 UTC 2020
Alphare created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REVISION SUMMARY
This is 3/3 in a series of patches to improve dirstate status' code.
Following in the footsteps of a46e36b82461 <https://phab.mercurial-scm.org/rHGa46e36b824612be16b38a1c1cd11160c293d115b>, we move the main status
functionality to an `Operation`. This will most likely be subject to change in
the future (what function signature, what parameters, etc., but we will see
when `rhg` gets `hg status` support.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D8663
AFFECTED FILES
rust/hg-core/src/dirstate/status.rs
rust/hg-core/src/operations/dirstate_status.rs
rust/hg-core/src/operations/mod.rs
CHANGE DETAILS
diff --git a/rust/hg-core/src/operations/mod.rs b/rust/hg-core/src/operations/mod.rs
--- a/rust/hg-core/src/operations/mod.rs
+++ b/rust/hg-core/src/operations/mod.rs
@@ -1,3 +1,4 @@
+mod dirstate_status;
mod find_root;
pub use find_root::{FindRoot, FindRootError, FindRootErrorKind};
diff --git a/rust/hg-core/src/operations/dirstate_status.rs b/rust/hg-core/src/operations/dirstate_status.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/operations/dirstate_status.rs
@@ -0,0 +1,76 @@
+// dirstate_status.rs
+//
+// Copyright 2019, Raphaël Gomès <rgomes at octobus.net>
+//
+// This software may be used and distributed according to the terms of the
+// GNU General Public License version 2 or any later version.
+
+use crate::dirstate::status::{build_response, Dispatch, HgPathCow, Status};
+use crate::matchers::Matcher;
+use crate::operations::Operation;
+use crate::{DirstateStatus, StatusError};
+
+/// A tuple of the paths that need to be checked in the filelog because it's
+/// ambiguous whether they've changed, and the rest of the already dispatched
+/// files.
+pub type LookupAndStatus<'a> = (Vec<HgPathCow<'a>>, DirstateStatus<'a>);
+
+impl<'a, M: Matcher + Sync> Operation<LookupAndStatus<'a>> for Status<'a, M> {
+ type Error = StatusError;
+
+ fn run(&self) -> Result<LookupAndStatus<'a>, Self::Error> {
+ let (traversed_sender, traversed_receiver) =
+ crossbeam::channel::unbounded();
+
+ // Step 1: check the files explicitly mentioned by the user
+ let (work, mut results) = self.walk_explicit(traversed_sender.clone());
+
+ if !work.is_empty() {
+ // Hashmaps are quite a bit slower to build than vecs, so only
+ // build it if needed.
+ let old_results = results.iter().cloned().collect();
+
+ // Step 2: recursively check the working directory for changes if
+ // needed
+ for (dir, dispatch) in work {
+ match dispatch {
+ Dispatch::Directory { was_file } => {
+ if was_file {
+ results.push((dir.to_owned(), Dispatch::Removed));
+ }
+ if self.options.list_ignored
+ || self.options.list_unknown
+ && !self.dir_ignore(&dir)
+ {
+ self.traverse(
+ &dir,
+ &old_results,
+ &mut results,
+ traversed_sender.clone(),
+ )?;
+ }
+ }
+ _ => {
+ unreachable!("There can only be directories in `work`")
+ }
+ }
+ }
+ }
+
+ if !self.matcher.is_exact() {
+ if self.options.list_unknown {
+ self.handle_unknowns(&mut results)?;
+ } else {
+ // TODO this is incorrect, see issue6335
+ // This requires a fix in both Python and Rust that can happen
+ // with other pending changes to `status`.
+ self.extend_from_dmap(&mut results);
+ }
+ }
+
+ drop(traversed_sender);
+ let traversed = traversed_receiver.into_iter().collect();
+
+ Ok(build_response(results, traversed))
+ }
+}
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
@@ -13,6 +13,7 @@
dirstate::SIZE_FROM_OTHER_PARENT,
filepatterns::PatternFileWarning,
matchers::{get_ignore_function, Matcher, VisitChildrenSet},
+ operations::Operation,
utils::{
files::{find_dirs, HgMetadata},
hg_path::{
@@ -101,7 +102,7 @@
/// We have a good mix of owned (from directory traversal) and borrowed (from
/// the dirstate/explicit) paths, this comes up a lot.
-type HgPathCow<'a> = Cow<'a, HgPath>;
+pub type HgPathCow<'a> = Cow<'a, HgPath>;
/// A path with its computed ``Dispatch`` information
type DispatchedPath<'a> = (HgPathCow<'a>, Dispatch);
@@ -294,9 +295,9 @@
/// and how, compared to the revision we're based on
pub struct Status<'a, M: Matcher + Sync> {
dmap: &'a DirstateMap,
- matcher: &'a M,
+ pub(crate) matcher: &'a M,
root_dir: PathBuf,
- options: StatusOptions,
+ pub(crate) options: StatusOptions,
ignore_fn: IgnoreFnType<'a>,
}
@@ -708,7 +709,7 @@
/// This takes a mutable reference to the results to account for the
/// `extend` in timings
#[timed]
- fn handle_unknowns(
+ pub fn handle_unknowns(
&self,
results: &mut Vec<DispatchedPath<'a>>,
) -> IoResult<()> {
@@ -787,7 +788,7 @@
/// This takes a mutable reference to the results to account for the
/// `extend` in timings
#[timed]
- fn extend_from_dmap(&self, results: &mut Vec<DispatchedPath<'a>>) {
+ pub fn extend_from_dmap(&self, results: &mut Vec<DispatchedPath<'a>>) {
results.par_extend(self.dmap.par_iter().flat_map(
move |(filename, entry)| {
let filename: &HgPath = filename;
@@ -837,7 +838,7 @@
}
#[timed]
-fn build_response<'a>(
+pub fn build_response<'a>(
results: impl IntoIterator<Item = DispatchedPath<'a>>,
traversed: Vec<HgPathBuf>,
) -> (Vec<HgPathCow<'a>>, DirstateStatus<'a>) {
@@ -899,56 +900,8 @@
(Vec<HgPathCow<'a>>, DirstateStatus<'a>),
Vec<PatternFileWarning>,
)> {
- let (traversed_sender, traversed_receiver) =
- crossbeam::channel::unbounded();
- let (st, warnings) =
+ let (status, warnings) =
Status::new(dmap, matcher, root_dir, ignore_files, options)?;
- // Step 1: check the files explicitly mentioned by the user
- let (work, mut results) = st.walk_explicit(traversed_sender.clone());
-
- if !work.is_empty() {
- // Hashmaps are quite a bit slower to build than vecs, so only build it
- // if needed.
- let old_results = results.iter().cloned().collect();
-
- // Step 2: recursively check the working directory for changes if
- // needed
- for (dir, dispatch) in work {
- match dispatch {
- Dispatch::Directory { was_file } => {
- if was_file {
- results.push((dir.to_owned(), Dispatch::Removed));
- }
- if options.list_ignored
- || options.list_unknown && !st.dir_ignore(&dir)
- {
- st.traverse(
- &dir,
- &old_results,
- &mut results,
- traversed_sender.clone(),
- )?;
- }
- }
- _ => unreachable!("There can only be directories in `work`"),
- }
- }
- }
-
- if !matcher.is_exact() {
- if options.list_unknown {
- st.handle_unknowns(&mut results)?;
- } else {
- // TODO this is incorrect, see issue6335
- // This requires a fix in both Python and Rust that can happen
- // with other pending changes to `status`.
- st.extend_from_dmap(&mut results);
- }
- }
-
- drop(traversed_sender);
- let traversed = traversed_receiver.into_iter().collect();
-
- Ok((build_response(results, traversed), warnings))
+ Ok((status.run()?, warnings))
}
To: Alphare, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mercurial-scm.org/pipermail/mercurial-patches/attachments/20200625/0207b131/attachment-0001.html>
More information about the Mercurial-patches
mailing list