diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs b/rust/hg-core/src/dirstate_tree/on_disk.rs --- a/rust/hg-core/src/dirstate_tree/on_disk.rs +++ b/rust/hg-core/src/dirstate_tree/on_disk.rs @@ -599,32 +599,6 @@ where .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 diff --git a/rust/hg-core/src/operations/list_tracked_files.rs b/rust/hg-core/src/operations/list_tracked_files.rs --- a/rust/hg-core/src/operations/list_tracked_files.rs +++ b/rust/hg-core/src/operations/list_tracked_files.rs @@ -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, - v2_metadata: Option>, -} - -impl Dirstate { - pub fn new(repo: &Repo) -> Result { - 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, 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( diff --git a/rust/hg-core/src/operations/mod.rs b/rust/hg-core/src/operations/mod.rs --- a/rust/hg-core/src/operations/mod.rs +++ b/rust/hg-core/src/operations/mod.rs @@ -7,5 +7,4 @@ mod debugdata; 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}; diff --git a/rust/rhg/src/commands/files.rs b/rust/rhg/src/commands/files.rs --- a/rust/rhg/src/commands/files.rs +++ b/rust/rhg/src/commands/files.rs @@ -4,9 +4,10 @@ use crate::utils::path_utils::Relativize 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 @@ pub fn run(invocation: &crate::CliInvoca "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, _> = + 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)) } }