rhg-files: reuse centralized dirstate logic
authorRaphaël Gomès <rgomes@octobus.net>
Wed, 11 Jan 2023 16:29:29 +0100
changeset 49980 95ffa065204e
parent 49979 f5b168979626
child 49981 364e78389653
rhg-files: reuse centralized dirstate logic The `files` logic predates the centralized dirstate logic. It was duplicated, an didn't receive bugfixes along the way.
rust/hg-core/src/dirstate_tree/on_disk.rs
rust/hg-core/src/operations/list_tracked_files.rs
rust/hg-core/src/operations/mod.rs
rust/rhg/src/commands/files.rs
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs	Wed Jan 11 17:27:19 2023 +0100
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs	Wed Jan 11 16:29:29 2023 +0100
@@ -599,32 +599,6 @@
         .map(|(slice, _rest)| slice)
 }
 
-pub(crate) fn for_each_tracked_path<'on_disk>(
-    on_disk: &'on_disk [u8],
-    metadata: &[u8],
-    mut f: impl FnMut(&'on_disk HgPath),
-) -> Result<(), DirstateV2ParseError> {
-    let (meta, _) = TreeMetadata::from_bytes(metadata).map_err(|e| {
-        DirstateV2ParseError::new(format!("when parsing tree metadata, {}", e))
-    })?;
-    fn recur<'on_disk>(
-        on_disk: &'on_disk [u8],
-        nodes: ChildNodes,
-        f: &mut impl FnMut(&'on_disk HgPath),
-    ) -> Result<(), DirstateV2ParseError> {
-        for node in read_nodes(on_disk, nodes)? {
-            if let Some(entry) = node.entry()? {
-                if entry.tracked() {
-                    f(node.full_path(on_disk)?)
-                }
-            }
-            recur(on_disk, node.children, f)?
-        }
-        Ok(())
-    }
-    recur(on_disk, meta.root_nodes, &mut f)
-}
-
 /// Returns new data and metadata, together with whether that data should be
 /// appended to the existing data file whose content is at
 /// `dirstate_map.on_disk` (true), instead of written to a new data file
--- a/rust/hg-core/src/operations/list_tracked_files.rs	Wed Jan 11 17:27:19 2023 +0100
+++ b/rust/hg-core/src/operations/list_tracked_files.rs	Wed Jan 11 16:29:29 2023 +0100
@@ -5,64 +5,11 @@
 // 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::parsers::parse_dirstate_entries;
-use crate::dirstate_tree::on_disk::{for_each_tracked_path, read_docket};
 use crate::errors::HgError;
 use crate::repo::Repo;
 use crate::revlog::manifest::Manifest;
 use crate::revlog::RevlogError;
 use crate::utils::hg_path::HgPath;
-use crate::DirstateError;
-use rayon::prelude::*;
-
-/// List files under Mercurial control in the working directory
-/// by reading the dirstate
-pub struct Dirstate {
-    /// The `dirstate` content.
-    content: Vec<u8>,
-    v2_metadata: Option<Vec<u8>>,
-}
-
-impl Dirstate {
-    pub fn new(repo: &Repo) -> Result<Self, HgError> {
-        let mut content = repo.hg_vfs().read("dirstate")?;
-        let v2_metadata = if repo.has_dirstate_v2() {
-            let docket = read_docket(&content)?;
-            let meta = docket.tree_metadata().to_vec();
-            content = repo.hg_vfs().read(docket.data_filename())?;
-            Some(meta)
-        } else {
-            None
-        };
-        Ok(Self {
-            content,
-            v2_metadata,
-        })
-    }
-
-    pub fn tracked_files(&self) -> Result<Vec<&HgPath>, DirstateError> {
-        let mut files = Vec::new();
-        if !self.content.is_empty() {
-            if let Some(meta) = &self.v2_metadata {
-                for_each_tracked_path(&self.content, meta, |path| {
-                    files.push(path)
-                })?
-            } else {
-                let _parents = parse_dirstate_entries(
-                    &self.content,
-                    |path, entry, _copy_source| {
-                        if entry.tracked() {
-                            files.push(path)
-                        }
-                        Ok(())
-                    },
-                )?;
-            }
-        }
-        files.par_sort_unstable();
-        Ok(files)
-    }
-}
 
 /// List files under Mercurial control at a given revision.
 pub fn list_rev_tracked_files(
--- a/rust/hg-core/src/operations/mod.rs	Wed Jan 11 17:27:19 2023 +0100
+++ b/rust/hg-core/src/operations/mod.rs	Wed Jan 11 16:29:29 2023 +0100
@@ -7,5 +7,4 @@
 mod list_tracked_files;
 pub use cat::{cat, CatOutput};
 pub use debugdata::{debug_data, DebugDataKind};
-pub use list_tracked_files::Dirstate;
 pub use list_tracked_files::{list_rev_tracked_files, FilesForRev};
--- a/rust/rhg/src/commands/files.rs	Wed Jan 11 17:27:19 2023 +0100
+++ b/rust/rhg/src/commands/files.rs	Wed Jan 11 16:29:29 2023 +0100
@@ -4,9 +4,10 @@
 use clap::Arg;
 use hg::errors::HgError;
 use hg::operations::list_rev_tracked_files;
-use hg::operations::Dirstate;
 use hg::repo::Repo;
+use hg::utils::filter_map_results;
 use hg::utils::hg_path::HgPath;
+use rayon::prelude::*;
 
 pub const HELP_TEXT: &str = "
 List tracked files.
@@ -70,8 +71,16 @@
                 "rhg files is not supported in narrow clones",
             ));
         }
-        let dirstate = Dirstate::new(repo)?;
-        let files = dirstate.tracked_files()?;
+        let dirstate = repo.dirstate_map()?;
+        let files_res: Result<Vec<_>, _> =
+            filter_map_results(dirstate.iter(), |(path, entry)| {
+                Ok(if entry.tracked() { Some(path) } else { None })
+            })
+            .collect();
+
+        let mut files = files_res?;
+        files.par_sort_unstable();
+
         display_files(invocation.ui, repo, files.into_iter().map(Ok))
     }
 }