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.
--- 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))
}
}