##// END OF EJS Templates
dirstate-tree: Skip readdir() in `hg status -mard`...
dirstate-tree: Skip readdir() in `hg status -mard` When running the status algorithm in a mode where we don’t list unknown or ignored files, all we care about are files that are listed in the dirstate. We can there for skip making expensive calls to readdir() to list the contents of filesystem directories, and instead only run stat() to get the filesystem state of files listed in the dirstate. (This state may be an error for files that don’t exist anymore on the filesystem.) On 16 CPU threads, this reduces the time spent in the `status()` function for `hg status -mard` on an old snapshot of mozilla-central from ~70ms to ~50ms. Differential Revision: https://phab.mercurial-scm.org/D10752

File last commit:

r47478:b1f2c2b3 default
r48129:f27f2afb default
Show More
cat.rs
105 lines | 3.7 KiB | application/rls-services+xml | RustLexer
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112 // 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.
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 use std::path::PathBuf;
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 use crate::repo::Repo;
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112 use crate::revlog::changelog::Changelog;
Simon Sapin
rust: replace most "operation" structs with functions...
r46751 use crate::revlog::manifest::Manifest;
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112 use crate::revlog::path_encode::path_encode;
use crate::revlog::revlog::Revlog;
use crate::revlog::revlog::RevlogError;
Simon Sapin
rust: use NodePrefix::from_hex instead of hex::decode directly...
r46647 use crate::revlog::Node;
Antoine cezar
hg-core: fix path encoding usage...
r46408 use crate::utils::files::get_path_from_bytes;
use crate::utils::hg_path::{HgPath, HgPathBuf};
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 pub struct CatOutput {
/// Whether any file in the manifest matched the paths given as CLI
/// arguments
pub found_any: bool,
/// The contents of matching files, in manifest order
pub concatenated: Vec<u8>,
/// Which of the CLI arguments did not match any manifest file
pub missing: Vec<HgPathBuf>,
/// The node ID that the given revset was resolved to
pub node: Node,
}
Antoine cezar
rhg: strip copied files metadata from `cat` output...
r46406 const METADATA_DELIMITER: [u8; 2] = [b'\x01', b'\n'];
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 /// Output the given revision of files
Simon Sapin
rust: replace most "operation" structs with functions...
r46751 ///
/// * `root`: Repository root
/// * `rev`: The revision to cat the files from.
/// * `files`: The files to output.
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 pub fn cat<'a>(
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 repo: &Repo,
Simon Sapin
rhg: centralize parsing of `--rev` CLI arguments...
r47162 revset: &str,
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 files: &'a [HgPathBuf],
) -> Result<CatOutput, RevlogError> {
Simon Sapin
rhg: centralize parsing of `--rev` CLI arguments...
r47162 let rev = crate::revset::resolve_single(revset, repo)?;
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 let changelog = Changelog::open(repo)?;
let manifest = Manifest::open(repo)?;
Simon Sapin
rhg: centralize parsing of `--rev` CLI arguments...
r47162 let changelog_entry = changelog.get_rev(rev)?;
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 let node = *changelog
.node_from_rev(rev)
.expect("should succeed when changelog.get_rev did");
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 let manifest_node =
Node::from_hex_for_repo(&changelog_entry.manifest_node()?)?;
Simon Sapin
rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef...
r47160 let manifest_entry = manifest.get_node(manifest_node.into())?;
Simon Sapin
rust: replace most "operation" structs with functions...
r46751 let mut bytes = vec![];
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 let mut matched = vec![false; files.len()];
let mut found_any = false;
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112
Simon Sapin
rust: replace most "operation" structs with functions...
r46751 for (manifest_file, node_bytes) in manifest_entry.files_with_nodes() {
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 for (cat_file, is_matched) in files.iter().zip(&mut matched) {
Simon Sapin
rust: replace most "operation" structs with functions...
r46751 if cat_file.as_bytes() == manifest_file.as_bytes() {
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 *is_matched = true;
found_any = true;
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 let index_path = store_path(manifest_file, b".i");
let data_path = store_path(manifest_file, b".d");
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 let file_log =
Revlog::open(repo, &index_path, Some(&data_path))?;
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 let file_node = Node::from_hex_for_repo(node_bytes)?;
Simon Sapin
rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef...
r47160 let file_rev = file_log.get_node_rev(file_node.into())?;
Simon Sapin
rust: replace most "operation" structs with functions...
r46751 let data = file_log.get_rev_data(file_rev)?;
if data.starts_with(&METADATA_DELIMITER) {
let end_delimiter_position = data
[METADATA_DELIMITER.len()..]
.windows(METADATA_DELIMITER.len())
.position(|bytes| bytes == METADATA_DELIMITER);
if let Some(position) = end_delimiter_position {
let offset = METADATA_DELIMITER.len() * 2;
bytes.extend(data[position + offset..].iter());
}
} else {
bytes.extend(data);
}
}
}
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112 }
Simon Sapin
rhg: `cat` command: print error messages for missing files...
r47478 let missing: Vec<_> = files
.iter()
.zip(&matched)
.filter(|pair| !*pair.1)
.map(|pair| pair.0.clone())
.collect();
Ok(CatOutput {
found_any,
concatenated: bytes,
missing,
node,
})
Antoine Cezar
hg-core: add a `CatRev` operation...
r46112 }
Antoine cezar
hg-core: fix path encoding usage...
r46408
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 fn store_path(hg_path: &HgPath, suffix: &[u8]) -> PathBuf {
Antoine cezar
hg-core: fix path encoding usage...
r46408 let encoded_bytes =
path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat());
Simon Sapin
rust: introduce Repo and Vfs types for filesystem abstraction...
r46782 get_path_from_bytes(&encoded_bytes).into()
Antoine cezar
hg-core: fix path encoding usage...
r46408 }