From 145f942d993a4b8753ab09f018c29f441719888b Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Mon, 12 Aug 2024 12:51:41 +0900 Subject: [PATCH] merged_tree: add function that resolves file conflicts non-recursively Conflict resolution is expensive, so I'm going to make file()/diff_contains() revsets not resolve the whole parent trees. --- lib/src/merged_tree.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/src/merged_tree.rs b/lib/src/merged_tree.rs index 8ba5d687e..4f97fda51 100644 --- a/lib/src/merged_tree.rs +++ b/lib/src/merged_tree.rs @@ -14,6 +14,7 @@ //! A lazily merged view of a set of trees. +use std::borrow::Borrow; use std::cmp::{max, Ordering}; use std::collections::{BTreeMap, VecDeque}; use std::iter::zip; @@ -499,15 +500,31 @@ fn merge_tree_values( } /// Tries to resolve file conflicts by merging the file contents. Treats missing -/// files as empty. -fn try_resolve_file_values( +/// files as empty. If the file conflict cannot be resolved, returns the passed +/// `values` unmodified. +pub fn resolve_file_values( store: &Arc, path: &RepoPath, - values: &MergedTreeVal, + values: MergedTreeValue, +) -> BackendResult { + if let Some(resolved) = values.resolve_trivial() { + return Ok(Merge::resolved(resolved.clone())); + } + + let maybe_resolved = try_resolve_file_values(store, path, &values)?; + Ok(maybe_resolved.unwrap_or(values)) +} + +fn try_resolve_file_values>( + store: &Arc, + path: &RepoPath, + values: &Merge>, ) -> BackendResult> { // The values may contain trees canceling each other (notably padded absent // trees), so we need to simplify them first. - let simplified = values.clone().simplify(); + let simplified = values + .map(|value| value.as_ref().map(Borrow::borrow)) + .simplify(); // No fast path for simplified.is_resolved(). If it could be resolved, it would // have been caught by values.resolve_trivial() above. if let Some(resolved) = try_resolve_file_conflict(store, path, &simplified)? {