rust/hg-core/src/dirstate_tree/on_disk.rs
changeset 47374 bd88b6bfd8da
parent 47351 3b9914b28133
child 47409 0ef8231e413f
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs	Wed May 26 11:53:37 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs	Tue May 25 09:20:30 2021 +0200
@@ -167,6 +167,16 @@
     }
 }
 
+fn read_header(on_disk: &[u8]) -> Result<&Header, DirstateV2ParseError> {
+    let (header, _) =
+        Header::from_bytes(on_disk).map_err(|_| DirstateV2ParseError)?;
+    if header.marker == *V2_FORMAT_MARKER {
+        Ok(header)
+    } else {
+        Err(DirstateV2ParseError)
+    }
+}
+
 pub(super) fn read<'on_disk>(
     on_disk: &'on_disk [u8],
 ) -> Result<
@@ -176,27 +186,19 @@
     if on_disk.is_empty() {
         return Ok((DirstateMap::empty(on_disk), None));
     }
-    let (header, _) =
-        Header::from_bytes(on_disk).map_err(|_| DirstateV2ParseError)?;
-    let Header {
-        marker,
-        parents,
-        root,
-        nodes_with_entry_count,
-        nodes_with_copy_source_count,
-    } = header;
-    if marker != V2_FORMAT_MARKER {
-        return Err(DirstateV2ParseError);
-    }
+    let header = read_header(on_disk)?;
     let dirstate_map = DirstateMap {
         on_disk,
         root: dirstate_map::ChildNodes::OnDisk(read_slice::<Node>(
-            on_disk, *root,
+            on_disk,
+            header.root,
         )?),
-        nodes_with_entry_count: nodes_with_entry_count.get(),
-        nodes_with_copy_source_count: nodes_with_copy_source_count.get(),
+        nodes_with_entry_count: header.nodes_with_entry_count.get(),
+        nodes_with_copy_source_count: header
+            .nodes_with_copy_source_count
+            .get(),
     };
-    let parents = Some(parents.clone());
+    let parents = Some(header.parents.clone());
     Ok((dirstate_map, parents))
 }
 
@@ -414,6 +416,35 @@
         .ok_or_else(|| DirstateV2ParseError)
 }
 
+pub(crate) fn parse_dirstate_parents(
+    on_disk: &[u8],
+) -> Result<&DirstateParents, HgError> {
+    Ok(&read_header(on_disk)?.parents)
+}
+
+pub(crate) fn for_each_tracked_path<'on_disk>(
+    on_disk: &'on_disk [u8],
+    mut f: impl FnMut(&'on_disk HgPath),
+) -> Result<(), DirstateV2ParseError> {
+    let header = read_header(on_disk)?;
+    fn recur<'on_disk>(
+        on_disk: &'on_disk [u8],
+        nodes: Slice,
+        f: &mut impl FnMut(&'on_disk HgPath),
+    ) -> Result<(), DirstateV2ParseError> {
+        for node in read_slice::<Node>(on_disk, nodes)? {
+            if let Some(state) = node.state()? {
+                if state.is_tracked() {
+                    f(node.full_path(on_disk)?)
+                }
+            }
+            recur(on_disk, node.children, f)?
+        }
+        Ok(())
+    }
+    recur(on_disk, header.root, &mut f)
+}
+
 pub(super) fn write(
     dirstate_map: &mut DirstateMap,
     parents: DirstateParents,