Patchwork D8863: hg-core: define a `ListTrackedFiles` `Operation`

login
register
mail settings
Submitter phabricator
Date Aug. 3, 2020, 2:27 p.m.
Message ID <differential-rev-PHID-DREV-tepymmmwoqzsjkjvwgys-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/46960/
State Superseded
Headers show

Comments

phabricator - Aug. 3, 2020, 2:27 p.m.
acezar created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  List files under Mercurial control in the working directory.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D8863

AFFECTED FILES
  rust/hg-core/src/operations/list_tracked_files.rs
  rust/hg-core/src/operations/mod.rs

CHANGE DETAILS




To: acezar, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

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
@@ -4,7 +4,11 @@ 
 
 mod dirstate_status;
 mod find_root;
+mod list_tracked_files;
 pub use find_root::{FindRoot, FindRootError, FindRootErrorKind};
+pub use list_tracked_files::{
+    ListTrackedFiles, ListTrackedFilesError, ListTrackedFilesErrorKind,
+};
 
 // TODO add an `Operation` trait when GAT have landed (rust #44265):
 // there is no way to currently define a trait which can both return
diff --git a/rust/hg-core/src/operations/list_tracked_files.rs b/rust/hg-core/src/operations/list_tracked_files.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/operations/list_tracked_files.rs
@@ -0,0 +1,78 @@ 
+use super::find_root;
+use crate::dirstate::parsers::parse_dirstate;
+use crate::utils::hg_path::HgPath;
+use crate::{DirstateParseError, EntryState};
+use rayon::prelude::*;
+use std::convert::From;
+use std::fmt;
+use std::fs;
+use std::io;
+use std::path::PathBuf;
+
+/// Kind of error encoutered by ListTrackedFiles
+#[derive(Debug)]
+pub enum ListTrackedFilesErrorKind {
+    ParseError(DirstateParseError),
+}
+
+/// A ListTrackedFiles error
+#[derive(Debug)]
+pub struct ListTrackedFilesError {
+    /// Kind of error encoutered by ListTrackedFiles
+    pub kind: ListTrackedFilesErrorKind,
+}
+
+impl std::error::Error for ListTrackedFilesError {}
+
+impl fmt::Display for ListTrackedFilesError {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
+impl From<ListTrackedFilesErrorKind> for ListTrackedFilesError {
+    fn from(kind: ListTrackedFilesErrorKind) -> Self {
+        ListTrackedFilesError { kind }
+    }
+}
+
+/// List files under Mercurial control in the working directory
+pub struct ListTrackedFiles {
+    root: PathBuf,
+}
+
+impl ListTrackedFiles {
+    pub fn new() -> Result<Self, find_root::FindRootError> {
+        let root = find_root::FindRoot::new().run()?;
+        Ok(ListTrackedFiles { root })
+    }
+
+    /// Load the tracked files data from disk
+    pub fn load(&self) -> Result<ListDirstateTrackedFiles, io::Error> {
+        let dirstate = &self.root.join(".hg/dirstate");
+        let content = fs::read(&dirstate)?;
+        Ok(ListDirstateTrackedFiles { content })
+    }
+}
+
+/// List files under Mercurial control in the working directory
+/// by reading the dirstate
+pub struct ListDirstateTrackedFiles {
+    content: Vec<u8>,
+}
+
+impl ListDirstateTrackedFiles {
+    pub fn run(&self) -> Result<Vec<&HgPath>, ListTrackedFilesError> {
+        let (_, entries, _) = parse_dirstate(&self.content)
+            .map_err(ListTrackedFilesErrorKind::ParseError)?;
+        let mut files: Vec<&HgPath> = entries
+            .into_iter()
+            .filter_map(|(path, entry)| match entry.state {
+                EntryState::Removed => None,
+                _ => Some(path),
+            })
+            .collect();
+        files.par_sort_unstable();
+        Ok(files)
+    }
+}