Mercurial > public > mercurial-scm > hg
view rust/hg-core/src/operations/dirstate_status.rs @ 47096:3c11c24b82b6
dirstate-tree: Add `WithBasename` wrapper for `HgPath`
In the tree-shaped dirstate we want to have nodes representing files or
directories, where directory nodes contain a map associating "base" names
to child nodes for child files and directories.
Many dirstate operations expect a full path from the repository root, but
re-concatenating string from nested map keys all the time might be expensive.
Instead, `WithBasename` stores a full path for these operations but
behaves as its base name (last path component) for equality and comparison.
Additionally `inclusive_ancestors` provides the successive map keys
that are needed when inserting a new dirstate node at a given full path.
Differential Revision: https://phab.mercurial-scm.org/D10365
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Thu, 08 Apr 2021 20:12:24 +0200 |
parents | 787ff5d21bcd |
children | 9c6b458a08e1 |
line wrap: on
line source
// 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>); impl<'a, M: ?Sized + Matcher + Sync> Status<'a, M> { pub(crate) fn run(&self) -> Result<LookupAndStatus<'a>, StatusError> { 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)) } }