--- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs Wed May 19 13:15:00 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs Wed May 19 13:15:00 2021 +0200
@@ -81,6 +81,7 @@
pub(super) fn make_mut(
&mut self,
+ _on_disk: &'on_disk [u8],
) -> Result<
&mut FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>,
DirstateV2ParseError,
@@ -95,6 +96,7 @@
pub(super) fn get(
&self,
base_name: &HgPath,
+ _on_disk: &'on_disk [u8],
) -> Result<Option<NodeRef<'tree, 'on_disk>>, DirstateV2ParseError> {
match self {
ChildNodesRef::InMemory(nodes) => Ok(nodes
@@ -151,6 +153,7 @@
impl<'tree, 'on_disk> NodeRef<'tree, 'on_disk> {
pub(super) fn full_path(
&self,
+ _on_disk: &'on_disk [u8],
) -> Result<&'tree HgPath, DirstateV2ParseError> {
match self {
NodeRef::InMemory(path, _node) => Ok(path.full_path()),
@@ -160,6 +163,7 @@
/// Returns a `Cow` that can borrow 'on_disk but is detached from 'tree
pub(super) fn full_path_cow(
&self,
+ _on_disk: &'on_disk [u8],
) -> Result<Cow<'on_disk, HgPath>, DirstateV2ParseError> {
match self {
NodeRef::InMemory(path, _node) => Ok(path.full_path().clone()),
@@ -168,6 +172,7 @@
pub(super) fn base_name(
&self,
+ _on_disk: &'on_disk [u8],
) -> Result<&'tree HgPath, DirstateV2ParseError> {
match self {
NodeRef::InMemory(path, _node) => Ok(path.base_name()),
@@ -176,6 +181,7 @@
pub(super) fn children(
&self,
+ _on_disk: &'on_disk [u8],
) -> Result<ChildNodesRef<'tree, 'on_disk>, DirstateV2ParseError> {
match self {
NodeRef::InMemory(_path, node) => Ok(node.children.as_ref()),
@@ -190,6 +196,7 @@
pub(super) fn copy_source(
&self,
+ _on_disk: &'on_disk [u8],
) -> Result<Option<&'tree HgPath>, DirstateV2ParseError> {
match self {
NodeRef::InMemory(_path, node) => {
@@ -274,6 +281,7 @@
|path, entry, copy_source| {
let tracked = entry.state.is_tracked();
let node = Self::get_or_insert_node(
+ map.on_disk,
&mut map.root,
path,
WithBasename::to_cow_borrowed,
@@ -314,10 +322,10 @@
let mut component =
components.next().expect("expected at least one components");
loop {
- if let Some(child) = children.get(component)? {
+ if let Some(child) = children.get(component, self.on_disk)? {
if let Some(next_component) = components.next() {
component = next_component;
- children = child.children()?;
+ children = child.children(self.on_disk)?;
} else {
return Ok(Some(child));
}
@@ -332,6 +340,7 @@
/// This takes `root` instead of `&mut self` so that callers can mutate
/// other fields while the returned borrow is still valid
fn get_node_mut<'tree>(
+ on_disk: &'on_disk [u8],
root: &'tree mut ChildNodes<'on_disk>,
path: &HgPath,
) -> Result<Option<&'tree mut Node<'on_disk>>, DirstateV2ParseError> {
@@ -340,7 +349,8 @@
let mut component =
components.next().expect("expected at least one components");
loop {
- if let Some(child) = children.make_mut()?.get_mut(component) {
+ if let Some(child) = children.make_mut(on_disk)?.get_mut(component)
+ {
if let Some(next_component) = components.next() {
component = next_component;
children = &mut child.children;
@@ -354,6 +364,7 @@
}
fn get_or_insert_node<'tree, 'path>(
+ on_disk: &'on_disk [u8],
root: &'tree mut ChildNodes<'on_disk>,
path: &'path HgPath,
to_cow: impl Fn(
@@ -372,7 +383,7 @@
// map already contains that key, without introducing double
// lookup?
let child_node = child_nodes
- .make_mut()?
+ .make_mut(on_disk)?
.entry(to_cow(ancestor_path))
.or_default();
if let Some(next) = inclusive_ancestor_paths.next() {
@@ -399,6 +410,7 @@
};
let node = Self::get_or_insert_node(
+ self.on_disk,
&mut self.root,
path,
WithBasename::to_cow_owned,
@@ -448,7 +460,7 @@
let mut iter = self.root.as_ref().iter();
std::iter::from_fn(move || {
while let Some(child_node) = iter.next() {
- let children = match child_node.children() {
+ let children = match child_node.children(self.on_disk) {
Ok(children) => children,
Err(error) => return Some(Err(error)),
};
@@ -476,9 +488,11 @@
paths: &[impl AsRef<HgPath>],
) -> Result<(), DirstateV2ParseError> {
for path in paths {
- if let Some(node) =
- Self::get_node_mut(&mut self.root, path.as_ref())?
- {
+ if let Some(node) = Self::get_node_mut(
+ self.on_disk,
+ &mut self.root,
+ path.as_ref(),
+ )? {
if let Some(entry) = node.entry.as_mut() {
entry.clear_mtime();
}
@@ -501,7 +515,7 @@
filter_map_results(self.iter_nodes(), move |node| {
if let Some(entry) = node.entry()? {
if predicate(&entry) {
- return Ok(Some(node.full_path()?));
+ return Ok(Some(node.full_path(self.on_disk)?));
}
}
Ok(None)
@@ -570,14 +584,15 @@
had_entry: bool,
had_copy_source: bool,
}
- fn recur(
- nodes: &mut ChildNodes,
+ fn recur<'on_disk>(
+ on_disk: &'on_disk [u8],
+ nodes: &mut ChildNodes<'on_disk>,
path: &HgPath,
) -> Result<Option<Dropped>, DirstateV2ParseError> {
let (first_path_component, rest_of_path) =
path.split_first_component();
let node = if let Some(node) =
- nodes.make_mut()?.get_mut(first_path_component)
+ nodes.make_mut(on_disk)?.get_mut(first_path_component)
{
node
} else {
@@ -585,7 +600,7 @@
};
let dropped;
if let Some(rest) = rest_of_path {
- if let Some(d) = recur(&mut node.children, rest)? {
+ if let Some(d) = recur(on_disk, &mut node.children, rest)? {
dropped = d;
if dropped.was_tracked {
node.tracked_descendants_count -= 1;
@@ -609,12 +624,12 @@
&& node.copy_source.is_none()
&& node.children.is_empty()
{
- nodes.make_mut()?.remove(first_path_component);
+ nodes.make_mut(on_disk)?.remove(first_path_component);
}
Ok(Some(dropped))
}
- if let Some(dropped) = recur(&mut self.root, filename)? {
+ if let Some(dropped) = recur(self.on_disk, &mut self.root, filename)? {
if dropped.had_entry {
self.nodes_with_entry_count -= 1
}
@@ -634,7 +649,8 @@
now: i32,
) -> Result<(), DirstateV2ParseError> {
for filename in filenames {
- if let Some(node) = Self::get_node_mut(&mut self.root, &filename)?
+ if let Some(node) =
+ Self::get_node_mut(self.on_disk, &mut self.root, &filename)?
{
if let Some(entry) = node.entry.as_mut() {
entry.clear_ambiguous_mtime(now);
@@ -735,10 +751,12 @@
for node in self.iter_nodes() {
let node = node?;
if let Some(entry) = node.entry()? {
- size +=
- packed_entry_size(node.full_path()?, node.copy_source()?);
+ size += packed_entry_size(
+ node.full_path(self.on_disk)?,
+ node.copy_source(self.on_disk)?,
+ );
if entry.mtime_is_ambiguous(now) {
- ambiguous_mtimes.push(node.full_path_cow()?)
+ ambiguous_mtimes.push(node.full_path_cow(self.on_disk)?)
}
}
}
@@ -751,9 +769,9 @@
let node = node?;
if let Some(entry) = node.entry()? {
pack_entry(
- node.full_path()?,
+ node.full_path(self.on_disk)?,
&entry,
- node.copy_source()?,
+ node.copy_source(self.on_disk)?,
&mut packed,
);
}
@@ -774,7 +792,7 @@
let node = node?;
if let Some(entry) = node.entry()? {
if entry.mtime_is_ambiguous(now) {
- paths.push(node.full_path_cow()?)
+ paths.push(node.full_path_cow(self.on_disk)?)
}
}
}
@@ -813,9 +831,9 @@
}
fn copy_map_iter(&self) -> CopyMapIter<'_> {
- Box::new(filter_map_results(self.iter_nodes(), |node| {
- Ok(if let Some(source) = node.copy_source()? {
- Some((node.full_path()?, source))
+ Box::new(filter_map_results(self.iter_nodes(), move |node| {
+ Ok(if let Some(source) = node.copy_source(self.on_disk)? {
+ Some((node.full_path(self.on_disk)?, source))
} else {
None
})
@@ -838,7 +856,7 @@
key: &HgPath,
) -> Result<Option<&HgPath>, DirstateV2ParseError> {
if let Some(node) = self.get_node(key)? {
- if let Some(source) = node.copy_source()? {
+ if let Some(source) = node.copy_source(self.on_disk)? {
return Ok(Some(source));
}
}
@@ -850,12 +868,16 @@
key: &HgPath,
) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
let count = &mut self.nodes_with_copy_source_count;
- Ok(Self::get_node_mut(&mut self.root, key)?.and_then(|node| {
- if node.copy_source.is_some() {
- *count -= 1
- }
- node.copy_source.take().map(Cow::into_owned)
- }))
+ Ok(
+ Self::get_node_mut(self.on_disk, &mut self.root, key)?.and_then(
+ |node| {
+ if node.copy_source.is_some() {
+ *count -= 1
+ }
+ node.copy_source.take().map(Cow::into_owned)
+ },
+ ),
+ )
}
fn copy_map_insert(
@@ -864,6 +886,7 @@
value: HgPathBuf,
) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
let node = Self::get_or_insert_node(
+ self.on_disk,
&mut self.root,
&key,
WithBasename::to_cow_owned,
@@ -898,9 +921,9 @@
}
fn iter(&self) -> StateMapIter<'_> {
- Box::new(filter_map_results(self.iter_nodes(), |node| {
+ Box::new(filter_map_results(self.iter_nodes(), move |node| {
Ok(if let Some(entry) = node.entry()? {
- Some((node.full_path()?, entry))
+ Some((node.full_path(self.on_disk)?, entry))
} else {
None
})
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs Wed May 19 13:15:00 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs Wed May 19 13:15:00 2021 +0200
@@ -272,7 +272,8 @@
// actual offset for the root nodes.
out.resize(header_len, 0_u8);
- let root = write_nodes(dirstate_map.root.as_ref(), &mut out)?;
+ let root =
+ write_nodes(dirstate_map, dirstate_map.root.as_ref(), &mut out)?;
let header = Header {
marker: *V2_FORMAT_MARKER,
@@ -288,6 +289,7 @@
}
fn write_nodes(
+ dirstate_map: &DirstateMap,
nodes: dirstate_map::ChildNodesRef,
out: &mut Vec<u8>,
) -> Result<ChildNodes, DirstateError> {
@@ -298,16 +300,19 @@
// First accumulate serialized nodes in a `Vec`
let mut on_disk_nodes = Vec::with_capacity(nodes.len());
for node in nodes {
- let children = write_nodes(node.children()?, out)?;
- let full_path = write_slice::<u8>(node.full_path()?.as_bytes(), out);
- let copy_source = if let Some(source) = node.copy_source()? {
- write_slice::<u8>(source.as_bytes(), out)
- } else {
- Slice {
- start: 0.into(),
- len: 0.into(),
- }
- };
+ let children = node.children(dirstate_map.on_disk)?;
+ let children = write_nodes(dirstate_map, children, out)?;
+ let full_path = node.full_path(dirstate_map.on_disk)?;
+ let full_path = write_slice::<u8>(full_path.as_bytes(), out);
+ let copy_source =
+ if let Some(source) = node.copy_source(dirstate_map.on_disk)? {
+ write_slice::<u8>(source.as_bytes(), out)
+ } else {
+ Slice {
+ start: 0.into(),
+ len: 0.into(),
+ }
+ };
on_disk_nodes.push(match node {
NodeRef::InMemory(path, node) => Node {
children,
--- a/rust/hg-core/src/dirstate_tree/status.rs Wed May 19 13:15:00 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/status.rs Wed May 19 13:15:00 2021 +0200
@@ -32,8 +32,8 @@
/// exists in one of the two trees, depending on information requested by
/// `options` we may need to traverse the remaining subtree.
#[timed]
-pub fn status<'tree>(
- dmap: &'tree mut DirstateMap,
+pub fn status<'tree, 'on_disk: 'tree>(
+ dmap: &'tree mut DirstateMap<'on_disk>,
matcher: &(dyn Matcher + Sync),
root_dir: PathBuf,
ignore_files: Vec<PathBuf>,
@@ -47,6 +47,7 @@
};
let common = StatusCommon {
+ dmap,
options,
matcher,
ignore_fn,
@@ -67,14 +68,15 @@
/// Bag of random things needed by various parts of the algorithm. Reduces the
/// number of parameters passed to functions.
-struct StatusCommon<'tree, 'a> {
+struct StatusCommon<'tree, 'a, 'on_disk: 'tree> {
+ dmap: &'tree DirstateMap<'on_disk>,
options: StatusOptions,
matcher: &'a (dyn Matcher + Sync),
ignore_fn: IgnoreFnType<'a>,
outcome: Mutex<DirstateStatus<'tree>>,
}
-impl<'tree, 'a> StatusCommon<'tree, 'a> {
+impl<'tree, 'a> StatusCommon<'tree, 'a, '_> {
fn read_dir(
&self,
hg_path: &HgPath,
@@ -119,7 +121,7 @@
// Propagate here any error that would happen inside the comparison
// callback below
for dirstate_node in &dirstate_nodes {
- dirstate_node.base_name()?;
+ dirstate_node.base_name(self.dmap.on_disk)?;
}
itertools::merge_join_by(
dirstate_nodes,
@@ -127,7 +129,10 @@
|dirstate_node, fs_entry| {
// This `unwrap` never panics because we already propagated
// those errors above
- dirstate_node.base_name().unwrap().cmp(&fs_entry.base_name)
+ dirstate_node
+ .base_name(self.dmap.on_disk)
+ .unwrap()
+ .cmp(&fs_entry.base_name)
},
)
.par_bridge()
@@ -159,7 +164,7 @@
dirstate_node: NodeRef<'tree, '_>,
has_ignored_ancestor: bool,
) -> Result<(), DirstateV2ParseError> {
- let hg_path = dirstate_node.full_path()?;
+ let hg_path = dirstate_node.full_path(self.dmap.on_disk)?;
let file_type = fs_entry.metadata.file_type();
let file_or_symlink = file_type.is_file() || file_type.is_symlink();
if !file_or_symlink {
@@ -179,7 +184,7 @@
let is_at_repo_root = false;
self.traverse_fs_directory_and_dirstate(
is_ignored,
- dirstate_node.children()?,
+ dirstate_node.children(self.dmap.on_disk)?,
hg_path,
&fs_entry.full_path,
is_at_repo_root,
@@ -221,7 +226,8 @@
}
}
- for child_node in dirstate_node.children()?.iter() {
+ for child_node in dirstate_node.children(self.dmap.on_disk)?.iter()
+ {
self.traverse_dirstate_only(child_node)?
}
}
@@ -246,7 +252,7 @@
let entry = dirstate_node
.entry()?
.expect("handle_normal_file called with entry-less node");
- let full_path = Cow::from(dirstate_node.full_path()?);
+ let full_path = Cow::from(dirstate_node.full_path(self.dmap.on_disk)?);
let mode_changed = || {
self.options.check_exec && entry.mode_changed(&fs_entry.metadata)
};
@@ -282,11 +288,11 @@
dirstate_node: NodeRef<'tree, '_>,
) -> Result<(), DirstateV2ParseError> {
self.mark_removed_or_deleted_if_file(
- dirstate_node.full_path()?,
+ dirstate_node.full_path(self.dmap.on_disk)?,
dirstate_node.state()?,
);
dirstate_node
- .children()?
+ .children(self.dmap.on_disk)?
.par_iter()
.map(|child_node| self.traverse_dirstate_only(child_node))
.collect()