Mercurial > hg
diff rust/hg-core/src/dirstate/dirstate_map.rs @ 45610:496537c9c1b4
rust: start plugging the dirstate tree behind a feature gate
The previous patch added the `dirstate-tree` feature gate to enable the two
dirstate implementations to co-habit while the tree-based one gets better.
This patch copies over the code that differs, be it because the algorithm
changed or because the borrowing rules are different.
Indeed, `DirstateTree` is not observationally equivalent to the std `HashMap` in
the APIs we use: it does not have the `Entry` API (yet?) and its iterator
returns owned values instead of references. This last point is because the
implementation needs to be changed to a more clever and efficient solution.
Differential Revision: https://phab.mercurial-scm.org/D9133
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Wed, 30 Sep 2020 18:10:29 +0200 |
parents | c35db907363d |
children | 5bae4bc9bd42 |
line wrap: on
line diff
--- a/rust/hg-core/src/dirstate/dirstate_map.rs Wed Sep 30 18:10:53 2020 +0200 +++ b/rust/hg-core/src/dirstate/dirstate_map.rs Wed Sep 30 18:10:29 2020 +0200 @@ -16,7 +16,6 @@ CopyMap, DirsMultiset, DirstateEntry, DirstateError, DirstateMapError, DirstateParents, DirstateParseError, FastHashMap, StateMap, }; -use core::borrow::Borrow; use micro_timer::timed; use std::collections::HashSet; use std::convert::TryInto; @@ -67,7 +66,7 @@ } pub fn clear(&mut self) { - self.state_map.clear(); + self.state_map = StateMap::default(); self.copy_map.clear(); self.file_fold_map = None; self.non_normal_set = None; @@ -189,18 +188,15 @@ ) { for filename in filenames { let mut changed = false; - self.state_map - .entry(filename.to_owned()) - .and_modify(|entry| { - if entry.state == EntryState::Normal && entry.mtime == now - { - changed = true; - *entry = DirstateEntry { - mtime: MTIME_UNSET, - ..*entry - }; - } - }); + if let Some(entry) = self.state_map.get_mut(&filename) { + if entry.state == EntryState::Normal && entry.mtime == now { + changed = true; + *entry = DirstateEntry { + mtime: MTIME_UNSET, + ..*entry + }; + } + } if changed { self.get_non_normal_other_parent_entries() .0 @@ -257,6 +253,7 @@ ) } + #[cfg(not(feature = "dirstate-tree"))] pub fn set_non_normal_other_parent_entries(&mut self, force: bool) { if !force && self.non_normal_set.is_some() @@ -285,6 +282,34 @@ self.non_normal_set = Some(non_normal); self.other_parent_set = Some(other_parent); } + #[cfg(feature = "dirstate-tree")] + pub fn set_non_normal_other_parent_entries(&mut self, force: bool) { + if !force + && self.non_normal_set.is_some() + && self.other_parent_set.is_some() + { + return; + } + let mut non_normal = HashSet::new(); + let mut other_parent = HashSet::new(); + + for ( + filename, + DirstateEntry { + state, size, mtime, .. + }, + ) in self.state_map.iter() + { + if state != EntryState::Normal || mtime == MTIME_UNSET { + non_normal.insert(filename.to_owned()); + } + if state == EntryState::Normal && size == SIZE_FROM_OTHER_PARENT { + other_parent.insert(filename.to_owned()); + } + } + self.non_normal_set = Some(non_normal); + self.other_parent_set = Some(other_parent); + } /// Both of these setters and their uses appear to be the simplest way to /// emulate a Python lazy property, but it is ugly and unidiomatic. @@ -398,17 +423,33 @@ self.set_non_normal_other_parent_entries(true); Ok(packed) } - + #[cfg(not(feature = "dirstate-tree"))] pub fn build_file_fold_map(&mut self) -> &FileFoldMap { if let Some(ref file_fold_map) = self.file_fold_map { return file_fold_map; } let mut new_file_fold_map = FileFoldMap::default(); - for (filename, DirstateEntry { state, .. }) in self.state_map.borrow() - { + + for (filename, DirstateEntry { state, .. }) in self.state_map.iter() { if *state == EntryState::Removed { new_file_fold_map - .insert(normalize_case(filename), filename.to_owned()); + .insert(normalize_case(&filename), filename.to_owned()); + } + } + self.file_fold_map = Some(new_file_fold_map); + self.file_fold_map.as_ref().unwrap() + } + #[cfg(feature = "dirstate-tree")] + pub fn build_file_fold_map(&mut self) -> &FileFoldMap { + if let Some(ref file_fold_map) = self.file_fold_map { + return file_fold_map; + } + let mut new_file_fold_map = FileFoldMap::default(); + + for (filename, DirstateEntry { state, .. }) in self.state_map.iter() { + if state == EntryState::Removed { + new_file_fold_map + .insert(normalize_case(&filename), filename.to_owned()); } } self.file_fold_map = Some(new_file_fold_map);