rust/hg-core/src/operations/list_tracked_files.rs
author Antoine Cezar <antoine.cezar@octobus.net>
Wed, 09 Sep 2020 12:12:11 +0200
changeset 45535 72b7d58d6e35
parent 45436 1b3197047f5c
child 45536 639f33f22faf
permissions -rw-r--r--
hg-core: simplify `list_tracked_files` operation Use directly `ListDirstateTrackedFiles` rather than having an operation builder. Differential Revision: https://phab.mercurial-scm.org/D9013

// list_tracked_files.rs
//
// Copyright 2020 Antoine Cezar <antoine.cezar@octobus.net>
//
// 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;
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::ops::Deref;
use std::path::{Path, PathBuf};

/// Kind of error encountered by `ListDirstateTrackedFiles`
#[derive(Debug)]
pub enum ListDirstateTrackedFilesErrorKind {
    /// Error when reading the `dirstate` file
    IoError(std::io::Error),
    /// Error when parsing the `dirstate` file
    ParseError(DirstateParseError),
}

/// A `ListDirstateTrackedFiles` error
#[derive(Debug)]
pub struct ListDirstateTrackedFilesError {
    /// Kind of error encountered by `ListDirstateTrackedFiles`
    pub kind: ListDirstateTrackedFilesErrorKind,
}

impl std::error::Error for ListDirstateTrackedFilesError {}

impl fmt::Display for ListDirstateTrackedFilesError {
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
        unimplemented!()
    }
}

impl From<ListDirstateTrackedFilesErrorKind>
    for ListDirstateTrackedFilesError
{
    fn from(kind: ListDirstateTrackedFilesErrorKind) -> Self {
        ListDirstateTrackedFilesError { kind }
    }
}

impl From<std::io::Error> for ListDirstateTrackedFilesError {
    fn from(err: std::io::Error) -> Self {
        let kind = ListDirstateTrackedFilesErrorKind::IoError(err);
        ListDirstateTrackedFilesError { kind }
    }
}

/// List files under Mercurial control in the working directory
/// by reading the dirstate
pub struct ListDirstateTrackedFiles {
    /// The `dirstate` content.
    content: Vec<u8>,
}

impl ListDirstateTrackedFiles {
    pub fn new(root: &PathBuf) -> Result<Self, ListDirstateTrackedFilesError> {
        let dirstate = root.join(".hg/dirstate");
        let content = fs::read(&dirstate)?;
        Ok(Self { content })
    }

    pub fn run(
        &mut self,
    ) -> Result<Vec<&HgPath>, ListDirstateTrackedFilesError> {
        let (_, entries, _) = parse_dirstate(&self.content)
            .map_err(ListDirstateTrackedFilesErrorKind::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)
    }
}