|
|
// 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::manifest::Manifest;
|
|
|
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 = repo.changelog()?;
|
|
|
let manifest = repo.manifestlog()?;
|
|
|
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(Manifest);
|
|
|
|
|
|
impl FilesForRev {
|
|
|
pub fn iter(&self) -> impl Iterator<Item = &HgPath> {
|
|
|
self.0.files()
|
|
|
}
|
|
|
}
|
|
|
|