##// END OF EJS Templates
dirstate-tree: Add tree traversal/iteration...
dirstate-tree: Add tree traversal/iteration Like Python’s, Rust’s iterators are "external" in that they are driven by a caller who calls a `next` method. This is as opposed to "internal" iterators who drive themselves and call a callback for each item. Writing an internal iterator traversing a tree is easy with recursion, but internal iterators cannot rely on the call stack in that way, they must save in an explicit object all state that they need to be preserved across two `next` calls. This algorithm uses a `Vec` as a stack that contains what would be local variables on the call stack if we could use recursion. Differential Revision: https://phab.mercurial-scm.org/D10370

File last commit:

r47863:787ff5d2 default
r47870:caa3031c default
Show More
dirstate_status.rs
73 lines | 2.8 KiB | application/rls-services+xml | RustLexer
Raphaël Gomès
hg-core: define a `dirstate_status` `Operation`...
r45673 // dirstate_status.rs
//
// Copyright 2019, Raphaël Gomès <rgomes@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::{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>);
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 impl<'a, M: ?Sized + Matcher + Sync> Status<'a, M> {
Antoine Cezar
hg-core: remove the `Operation` trait...
r45917 pub(crate) fn run(&self) -> Result<LookupAndStatus<'a>, StatusError> {
Raphaël Gomès
hg-core: define a `dirstate_status` `Operation`...
r45673 let (traversed_sender, traversed_receiver) =
Simon Sapin
rust: use crossbeam-channel crate directly...
r46669 crossbeam_channel::unbounded();
Raphaël Gomès
hg-core: define a `dirstate_status` `Operation`...
r45673
// 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(),
Raphaël Gomès
rust-status: don't bubble up os errors, translate them to bad matches...
r46466 );
Raphaël Gomès
hg-core: define a `dirstate_status` `Operation`...
r45673 }
}
_ => {
unreachable!("There can only be directories in `work`")
}
}
}
}
if !self.matcher.is_exact() {
if self.options.list_unknown {
Raphaël Gomès
rust-status: don't bubble up os errors, translate them to bad matches...
r46466 self.handle_unknowns(&mut results);
Raphaël Gomès
hg-core: define a `dirstate_status` `Operation`...
r45673 } 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))
}
}