dirstate-tree: Add "non normal" and "from other parent" sets
Unlike the other DirstateMap implementation, these sets are not materialized
separately in memory. Instead we traverse the main tree.
Differential Revision: https://phab.mercurial-scm.org/D10492
--- a/rust/hg-core/src/dirstate.rs Fri Apr 09 12:55:35 2021 +0200
+++ b/rust/hg-core/src/dirstate.rs Fri Apr 09 13:13:19 2021 +0200
@@ -34,6 +34,16 @@
pub size: i32,
}
+impl DirstateEntry {
+ pub fn is_non_normal(&self) -> bool {
+ self.state != EntryState::Normal || self.mtime == MTIME_UNSET
+ }
+
+ pub fn is_from_other_parent(&self) -> bool {
+ self.state == EntryState::Normal && self.size == SIZE_FROM_OTHER_PARENT
+ }
+}
+
#[derive(BytesCast)]
#[repr(C)]
struct RawEntry {
@@ -44,6 +54,8 @@
length: unaligned::I32Be,
}
+const MTIME_UNSET: i32 = -1;
+
/// A `DirstateEntry` with a size of `-2` means that it was merged from the
/// other parent. This allows revert to pick the right status back during a
/// merge.
--- a/rust/hg-core/src/dirstate/dirstate_map.rs Fri Apr 09 12:55:35 2021 +0200
+++ b/rust/hg-core/src/dirstate/dirstate_map.rs Fri Apr 09 13:13:19 2021 +0200
@@ -10,7 +10,7 @@
use crate::errors::HgError;
use crate::revlog::node::NULL_NODE;
use crate::{
- dirstate::{parsers::PARENT_SIZE, EntryState, SIZE_FROM_OTHER_PARENT},
+ dirstate::{parsers::PARENT_SIZE, EntryState},
pack_dirstate, parse_dirstate,
utils::{
files::normalize_case,
@@ -27,8 +27,6 @@
pub type FileFoldMap = FastHashMap<HgPathBuf, HgPathBuf>;
-const MTIME_UNSET: i32 = -1;
-
#[derive(Default)]
pub struct DirstateMap {
state_map: StateMap,
@@ -99,13 +97,13 @@
}
self.state_map.insert(filename.to_owned(), entry.to_owned());
- if entry.state != EntryState::Normal || entry.mtime == MTIME_UNSET {
+ if entry.is_non_normal() {
self.get_non_normal_other_parent_entries()
.0
.insert(filename.to_owned());
}
- if entry.size == SIZE_FROM_OTHER_PARENT {
+ if entry.is_from_other_parent() {
self.get_non_normal_other_parent_entries()
.1
.insert(filename.to_owned());
@@ -199,14 +197,12 @@
}
}
- pub fn non_normal_entries_remove(
- &mut self,
- key: impl AsRef<HgPath>,
- ) -> bool {
+ pub fn non_normal_entries_remove(&mut self, key: impl AsRef<HgPath>) {
self.get_non_normal_other_parent_entries()
.0
- .remove(key.as_ref())
+ .remove(key.as_ref());
}
+
pub fn non_normal_entries_union(
&mut self,
other: HashSet<HgPathBuf>,
@@ -257,18 +253,11 @@
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 {
+ for (filename, entry) in self.state_map.iter() {
+ if entry.is_non_normal() {
non_normal.insert(filename.to_owned());
}
- if *state == EntryState::Normal && *size == SIZE_FROM_OTHER_PARENT
- {
+ if entry.is_from_other_parent() {
other_parent.insert(filename.to_owned());
}
}
--- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs Fri Apr 09 12:55:35 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs Fri Apr 09 13:13:19 2021 +0200
@@ -397,40 +397,61 @@
}
}
- fn non_normal_entries_contains(&mut self, _key: &HgPath) -> bool {
- todo!()
+ fn non_normal_entries_contains(&mut self, key: &HgPath) -> bool {
+ self.get_node(key)
+ .and_then(|node| node.entry.as_ref())
+ .map_or(false, DirstateEntry::is_non_normal)
}
- fn non_normal_entries_remove(&mut self, _key: &HgPath) -> bool {
- todo!()
+ fn non_normal_entries_remove(&mut self, _key: &HgPath) {
+ // Do nothing, this `DirstateMap` does not have a separate "non normal
+ // entries" set that need to be kept up to date
}
fn non_normal_or_other_parent_paths(
&mut self,
) -> Box<dyn Iterator<Item = &HgPathBuf> + '_> {
- todo!()
+ Box::new(self.iter_nodes().filter_map(|(path, node)| {
+ node.entry
+ .as_ref()
+ .filter(|entry| {
+ entry.is_non_normal() || entry.is_from_other_parent()
+ })
+ .map(|_| path.full_path())
+ }))
}
fn set_non_normal_other_parent_entries(&mut self, _force: bool) {
- todo!()
+ // Do nothing, this `DirstateMap` does not have a separate "non normal
+ // entries" and "from other parent" sets that need to be recomputed
}
fn iter_non_normal_paths(
&mut self,
) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
- todo!()
+ self.iter_non_normal_paths_panic()
}
fn iter_non_normal_paths_panic(
&self,
) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
- todo!()
+ Box::new(self.iter_nodes().filter_map(|(path, node)| {
+ node.entry
+ .as_ref()
+ .filter(|entry| entry.is_non_normal())
+ .map(|_| path.full_path())
+ }))
}
fn iter_other_parent_paths(
&mut self,
) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> {
- todo!()
+ Box::new(self.iter_nodes().filter_map(|(path, node)| {
+ node.entry
+ .as_ref()
+ .filter(|entry| entry.is_from_other_parent())
+ .map(|_| path.full_path())
+ }))
}
fn has_tracked_dir(
--- a/rust/hg-core/src/dirstate_tree/dispatch.rs Fri Apr 09 12:55:35 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/dispatch.rs Fri Apr 09 13:13:19 2021 +0200
@@ -45,7 +45,7 @@
fn non_normal_entries_contains(&mut self, key: &HgPath) -> bool;
- fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool;
+ fn non_normal_entries_remove(&mut self, key: &HgPath);
fn non_normal_or_other_parent_paths(
&mut self,
@@ -179,7 +179,7 @@
non_normal.contains(key)
}
- fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool {
+ fn non_normal_entries_remove(&mut self, key: &HgPath) {
self.non_normal_entries_remove(key)
}