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,85 @@ +// list_tracked_files.rs +// +// Copyright 2020 Antoine Cezar +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +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 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 { + let root = find_root::FindRoot::new().run()?; + Ok(ListTrackedFiles { root }) + } + + /// Load the tracked files data from disk + pub fn load(&self) -> Result { + 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, +} + +impl ListDirstateTrackedFiles { + pub fn run(&self) -> Result, 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) + } +} 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