##// END OF EJS Templates
dirstate-v2: Move fixed-size tree metadata into the docket file...
dirstate-v2: Move fixed-size tree metadata into the docket file Before this changeset, the dirstate-v2 data file contained not only nodes and paths that may be reused when appending to an existing file, but also some fixed-size metadata that applies to the entire tree and was added at the end of the data file for every append. This moves that metadata into the docket file, so that repeated "append" operations without meaningful changes don’t actually need to grow any file. Differential Revision: https://phab.mercurial-scm.org/D11098

File last commit:

r48482:78f7f0d4 default
r48482:78f7f0d4 default
Show More
list_tracked_files.rs
90 lines | 2.8 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_entries;
use crate::dirstate_tree::on_disk::{for_each_tracked_path, read_docket};
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::DirstateError;
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>,
v2_metadata: Option<Vec<u8>>,
}
impl Dirstate {
pub fn new(repo: &Repo) -> Result<Self, HgError> {
let mut content = repo.hg_vfs().read("dirstate")?;
let v2_metadata = if repo.has_dirstate_v2() {
let docket = read_docket(&content)?;
let meta = docket.tree_metadata().to_vec();
content = repo.hg_vfs().read(docket.data_filename())?;
Some(meta)
} else {
None
};
Ok(Self {
content,
v2_metadata,
})
}
pub fn tracked_files(&self) -> Result<Vec<&HgPath>, DirstateError> {
let mut files = Vec::new();
if !self.content.is_empty() {
if let Some(meta) = &self.v2_metadata {
for_each_tracked_path(&self.content, meta, |path| {
files.push(path)
})?
} else {
let _parents = parse_dirstate_entries(
&self.content,
|path, entry, _copy_source| {
if entry.state.is_tracked() {
files.push(path)
}
Ok(())
},
)?;
}
}
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()
}
}