##// END OF EJS Templates
dirstate-tree: Add tree traversal/iteration...
dirstate-tree: Add tree traversal/iteration Like Python’s, Rust’s iterators are "external" in that they are driven by a caller who calls a `next` method. This is as opposed to "internal" iterators who drive themselves and call a callback for each item. Writing an internal iterator traversing a tree is easy with recursion, but internal iterators cannot rely on the call stack in that way, they must save in an explicit object all state that they need to be preserved across two `next` calls. This algorithm uses a `Vec` as a stack that contains what would be local variables on the call stack if we could use recursion. Differential Revision: https://phab.mercurial-scm.org/D10370

File last commit:

r47172:43d63979 default
r47870:caa3031c default
Show More
list_tracked_files.rs
67 lines | 2.0 KiB | application/rls-services+xml | RustLexer
// 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::errors::HgError;
use crate::repo::Repo;
use crate::revlog::changelog::Changelog;
use crate::revlog::manifest::{Manifest, ManifestEntry};
use crate::revlog::node::Node;
use crate::revlog::revlog::RevlogError;
use crate::utils::hg_path::HgPath;
use crate::EntryState;
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>,
}
impl Dirstate {
pub fn new(repo: &Repo) -> Result<Self, HgError> {
let content = repo.hg_vfs().read("dirstate")?;
Ok(Self { content })
}
pub fn tracked_files(&self) -> Result<Vec<&HgPath>, HgError> {
let (_, entries, _) = parse_dirstate(&self.content)?;
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)
}
}
/// List files under Mercurial control at a given revision.
pub fn list_rev_tracked_files(
repo: &Repo,
revset: &str,
) -> Result<FilesForRev, RevlogError> {
let rev = crate::revset::resolve_single(revset, repo)?;
let changelog = Changelog::open(repo)?;
let manifest = Manifest::open(repo)?;
let changelog_entry = changelog.get_rev(rev)?;
let manifest_node =
Node::from_hex_for_repo(&changelog_entry.manifest_node()?)?;
let manifest_entry = manifest.get_node(manifest_node.into())?;
Ok(FilesForRev(manifest_entry))
}
pub struct FilesForRev(ManifestEntry);
impl FilesForRev {
pub fn iter(&self) -> impl Iterator<Item = &HgPath> {
self.0.files()
}
}