D11615: rhg: faster hg cat when many files are requested
aalekseyev (Arseniy Alekseyev)
phabricator at mercurial-scm.org
Tue Oct 5 14:16:22 UTC 2021
aalekseyev created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D11615
AFFECTED FILES
rust/hg-core/src/operations/cat.rs
rust/rhg/src/commands/cat.rs
CHANGE DETAILS
diff --git a/rust/rhg/src/commands/cat.rs b/rust/rhg/src/commands/cat.rs
--- a/rust/rhg/src/commands/cat.rs
+++ b/rust/rhg/src/commands/cat.rs
@@ -59,7 +59,7 @@
match rev {
Some(rev) => {
- let output = cat(&repo, rev, &files).map_err(|e| (e, rev))?;
+ let output = cat(&repo, rev, files).map_err(|e| (e, rev))?;
invocation.ui.write_stdout(&output.concatenated)?;
if !output.missing.is_empty() {
let short = format!("{:x}", output.node.short()).into_bytes();
diff --git a/rust/hg-core/src/operations/cat.rs b/rust/hg-core/src/operations/cat.rs
--- a/rust/hg-core/src/operations/cat.rs
+++ b/rust/hg-core/src/operations/cat.rs
@@ -11,6 +11,9 @@
use crate::utils::hg_path::HgPathBuf;
+use itertools::EitherOrBoth::{Both, Left, Right};
+use itertools::Itertools;
+
pub struct CatOutput {
/// Whether any file in the manifest matched the paths given as CLI
/// arguments
@@ -31,7 +34,7 @@
pub fn cat<'a>(
repo: &Repo,
revset: &str,
- files: &'a [HgPathBuf],
+ mut files: Vec<HgPathBuf>,
) -> Result<CatOutput, RevlogError> {
let rev = crate::revset::resolve_single(revset, repo)?;
let manifest = repo.manifest_for_rev(rev)?;
@@ -40,13 +43,21 @@
.node_from_rev(rev)
.expect("should succeed when repo.manifest did");
let mut bytes = vec![];
- let mut matched = vec![false; files.len()];
let mut found_any = false;
+ files.sort_unstable();
+
+ let mut missing = vec![];
- for (manifest_file, node_bytes) in manifest.files_with_nodes() {
- for (cat_file, is_matched) in files.iter().zip(&mut matched) {
- if cat_file.as_bytes() == manifest_file.as_bytes() {
- *is_matched = true;
+ for entry in manifest
+ .files_with_nodes()
+ .merge_join_by(files.iter(), |(manifest_file, _), file| {
+ manifest_file.cmp(&file.as_ref())
+ })
+ {
+ match entry {
+ Left(_) => (),
+ Right(path) => missing.push(path),
+ Both((manifest_file, node_bytes), _) => {
found_any = true;
let file_log = repo.filelog(manifest_file)?;
let file_node = Node::from_hex_for_repo(node_bytes)?;
@@ -56,11 +67,12 @@
}
}
+ // make the order of the [missing] files
+ // match the order they were specified on the command line
let missing: Vec<_> = files
.iter()
- .zip(&matched)
- .filter(|pair| !*pair.1)
- .map(|pair| pair.0.clone())
+ .filter(|file| missing.contains(file))
+ .map(|file| file.clone())
.collect();
Ok(CatOutput {
found_any,
To: aalekseyev, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
More information about the Mercurial-devel
mailing list