merged_tree: micro-optimize Merge<Tree> entries iterator to return &TreeValue

try_resolve_file_conflict() is also updated. It could be a generic function,
but there are only two callers, and the legacy tree one is used only in tests.
This commit is contained in:
Yuya Nishihara 2024-08-11 13:06:15 +09:00
parent 6d6f5990de
commit 88018e84fc
2 changed files with 10 additions and 9 deletions

View file

@ -389,7 +389,7 @@ fn all_tree_entries(
/// than `tree.entries_non_recursive()`. /// than `tree.entries_non_recursive()`.
fn all_merged_tree_entries( fn all_merged_tree_entries(
trees: &Merge<Tree>, trees: &Merge<Tree>,
) -> impl Iterator<Item = (&RepoPathComponent, MergedTreeValue)> { ) -> impl Iterator<Item = (&RepoPathComponent, Merge<Option<&TreeValue>>)> {
let mut entries_iters = trees let mut entries_iters = trees
.iter() .iter()
.map(|tree| tree.entries_non_recursive().peekable()) .map(|tree| tree.entries_non_recursive().peekable())
@ -404,7 +404,7 @@ fn all_merged_tree_entries(
.iter_mut() .iter_mut()
.map(|iter| { .map(|iter| {
let entry = iter.next_if(|entry| entry.name() == next_name)?; let entry = iter.next_if(|entry| entry.name() == next_name)?;
Some(entry.value().clone()) Some(entry.value())
}) })
.collect(); .collect();
Some((next_name, values.build())) Some((next_name, values.build()))
@ -456,7 +456,7 @@ fn merge_trees(merge: &Merge<Tree>) -> BackendResult<Merge<Tree>> {
let mut conflicts = vec![]; let mut conflicts = vec![];
for (basename, path_merge) in all_merged_tree_entries(merge) { for (basename, path_merge) in all_merged_tree_entries(merge) {
let path = dir.join(basename); let path = dir.join(basename);
let path_merge = merge_tree_values(store, &path, path_merge)?; let path_merge = merge_tree_values(store, &path, &path_merge)?;
match path_merge.into_resolved() { match path_merge.into_resolved() {
Ok(value) => { Ok(value) => {
new_tree.set_or_remove(basename, value); new_tree.set_or_remove(basename, value);
@ -493,10 +493,10 @@ fn merge_trees(merge: &Merge<Tree>) -> BackendResult<Merge<Tree>> {
fn merge_tree_values( fn merge_tree_values(
store: &Arc<Store>, store: &Arc<Store>,
path: &RepoPath, path: &RepoPath,
values: MergedTreeValue, values: &Merge<Option<&TreeValue>>,
) -> BackendResult<MergedTreeValue> { ) -> BackendResult<MergedTreeValue> {
if let Some(resolved) = values.resolve_trivial() { if let Some(resolved) = values.resolve_trivial() {
return Ok(Merge::resolved(resolved.clone())); return Ok(Merge::resolved(resolved.cloned()));
} }
if let Some(trees) = values.to_tree_merge(store, path)? { if let Some(trees) = values.to_tree_merge(store, path)? {
@ -517,7 +517,7 @@ fn merge_tree_values(
Ok(Merge::normal(resolved)) Ok(Merge::normal(resolved))
} else { } else {
// Failed to merge the files, or the paths are not files // Failed to merge the files, or the paths are not files
Ok(values) Ok(values.map(|value| value.cloned()))
} }
} }
} }

View file

@ -28,7 +28,7 @@ use crate::backend::{
}; };
use crate::files::MergeResult; use crate::files::MergeResult;
use crate::matchers::{EverythingMatcher, Matcher}; use crate::matchers::{EverythingMatcher, Matcher};
use crate::merge::{trivial_merge, Merge, MergedTreeValue}; use crate::merge::{trivial_merge, Merge};
use crate::object_id::ObjectId; use crate::object_id::ObjectId;
use crate::repo_path::{RepoPath, RepoPathBuf, RepoPathComponent}; use crate::repo_path::{RepoPath, RepoPathBuf, RepoPathComponent};
use crate::store::Store; use crate::store::Store;
@ -382,8 +382,9 @@ fn merge_tree_value(
match merge.into_resolved() { match merge.into_resolved() {
Ok(value) => value, Ok(value) => value,
Err(conflict) => { Err(conflict) => {
let conflict_borrowed = conflict.map(|value| value.as_ref());
if let Some(tree_value) = if let Some(tree_value) =
try_resolve_file_conflict(store, &filename, &conflict)? try_resolve_file_conflict(store, &filename, &conflict_borrowed)?
{ {
Some(tree_value) Some(tree_value)
} else { } else {
@ -403,7 +404,7 @@ fn merge_tree_value(
pub fn try_resolve_file_conflict( pub fn try_resolve_file_conflict(
store: &Store, store: &Store,
filename: &RepoPath, filename: &RepoPath,
conflict: &MergedTreeValue, conflict: &Merge<Option<&TreeValue>>,
) -> BackendResult<Option<TreeValue>> { ) -> BackendResult<Option<TreeValue>> {
// If there are any non-file or any missing parts in the conflict, we can't // If there are any non-file or any missing parts in the conflict, we can't
// merge it. We check early so we don't waste time reading file contents if // merge it. We check early so we don't waste time reading file contents if