list_tracked_files.rs
94 lines
| 2.8 KiB
| application/rls-services+xml
|
RustLexer
Antoine Cezar
|
r45918 | // 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 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; | ||||
Raphaël Gomès
|
r46007 | use std::path::{Path, PathBuf}; | ||
Antoine Cezar
|
r45918 | |||
/// 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 }) | ||||
} | ||||
Raphaël Gomès
|
r46007 | |||
/// Returns the repository root directory | ||||
/// TODO I think this is a crutch that creates a dependency that should not | ||||
/// be there. Operations that need the root of the repository should get | ||||
/// it themselves, probably in a lazy fashion. But this would make the | ||||
/// current series even larger, so this is simplified for now. | ||||
pub fn get_root(&self) -> &Path { | ||||
&self.root | ||||
} | ||||
Antoine Cezar
|
r45918 | } | ||
/// 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) | ||||
} | ||||
} | ||||