ok/jj
1
0
Fork 0
forked from mirrors/jj

merged_tree: make resolve() also simplify the result

This changes the documented behavior of `resolve()` since it was
previously documented to not change the arity unless all conflicts
were resolved.

I plan to use `resolve()` from `MergedTreeBuilder::write_tree()`.
This commit is contained in:
Martin von Zweigbergk 2024-06-07 14:16:46 -07:00 committed by Martin von Zweigbergk
parent 776b2d981f
commit 2e6a0f9e96

View file

@ -182,15 +182,25 @@ impl MergedTree {
}
/// Tries to resolve any conflicts, resolving any conflicts that can be
/// automatically resolved and leaving the rest unresolved. The returned
/// conflict will either be resolved or have the same number of sides as
/// the input.
/// automatically resolved and leaving the rest unresolved.
pub fn resolve(&self) -> BackendResult<MergedTree> {
match self {
MergedTree::Legacy(_) => panic!("Cannot resolve conflicts in legacy tree"),
MergedTree::Merge(trees) => {
let merged = merge_trees(trees)?;
Ok(MergedTree::Merge(merged))
// If the result can be resolved, then `merge_trees()` above would have returned
// a resolved merge. However, that function will always preserve the arity of
// conflicts it cannot resolve. So we simplify the conflict again
// here to possibly reduce a complex conflict to a simpler one.
let simplified = merged.simplify();
// If debug assertions are enabled, check that the merge was idempotent. In
// particular, that this last simplification doesn't enable further automatic
// resolutions
if cfg!(debug_assertions) {
let re_merged = merge_trees(&simplified).unwrap();
debug_assert_eq!(re_merged, simplified);
}
Ok(MergedTree::Merge(simplified))
}
}
}
@ -389,20 +399,8 @@ impl MergedTree {
}
};
let nested = Merge::from_vec(vec![to_merge(self)?, to_merge(base)?, to_merge(other)?]);
let tree = merge_trees(&nested.flatten().simplify())?;
// If the result can be resolved, then `merge_trees()` above would have returned
// a resolved merge. However, that function will always preserve the arity of
// conflicts it cannot resolve. So we simplify the conflict again
// here to possibly reduce a complex conflict to a simpler one.
let tree = tree.simplify();
// If debug assertions are enabled, check that the merge was idempotent. In
// particular, that this last simplification doesn't enable further automatic
// resolutions
if cfg!(debug_assertions) {
let re_merged = merge_trees(&tree).unwrap();
debug_assert_eq!(re_merged, tree);
}
Ok(MergedTree::Merge(tree))
let flattened = MergedTree::Merge(nested.flatten().simplify());
flattened.resolve()
}
}
@ -476,6 +474,8 @@ fn trees_value<'a>(trees: &'a Merge<Tree>, basename: &RepoPathComponent) -> Merg
MergedTreeVal::Conflict(value.map(|x| x.cloned()))
}
/// The returned conflict will either be resolved or have the same number of
/// sides as the input.
fn merge_trees(merge: &Merge<Tree>) -> BackendResult<Merge<Tree>> {
if let Some(tree) = merge.resolve_trivial() {
return Ok(Merge::resolved(tree.clone()));