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

refs: retry trivial resolution after merging targets

This helps resolve diverged refs by abandoning both sides:

    D  ref = [D]
    |\
    | C       C  ref = [B - D + C]
    | |       |
    B |     B |     B  ref = [B - D + A]
    |/      |/      |
    A       A       A       A  ref = [A - D + A]
This commit is contained in:
Yuya Nishihara 2024-09-01 13:44:05 +09:00
parent 982ee63ba8
commit 11b9888cdf
2 changed files with 38 additions and 2 deletions

View file

@ -102,10 +102,16 @@ pub fn merge_ref_targets(
])
.flatten()
.simplify();
if !merge.is_resolved() {
// Suppose left = [A - C + B], base = [B], right = [A], the merge result is
// [A - C + A], which can now be trivially resolved.
if let Some(resolved) = merge.resolve_trivial() {
RefTarget::resolved(resolved.clone())
} else {
merge_ref_targets_non_trivial(index, &mut merge);
// TODO: Maybe better to try resolve_trivial() again, but the result is
// unreliable since merge_ref_targets_non_trivial() is order dependent.
RefTarget::from_merge(merge)
}
RefTarget::from_merge(merge)
}
pub fn merge_remote_refs(

View file

@ -363,6 +363,36 @@ fn test_merge_ref_targets() {
target4
);
// Existing conflict on left, right moves one side of conflict to the other
// side ("A - B + A" - type conflict)
assert_eq!(
merge_ref_targets(
index,
&RefTarget::from_legacy_form(
[commit5.id().clone()], // not an ancestor of commit3, 4
[commit3.id().clone(), commit4.id().clone()],
),
&target4,
&target3,
),
target3
);
// Existing conflict on right, left moves one side of conflict to the other
// side ("A - B + A" - type conflict)
assert_eq!(
merge_ref_targets(
index,
&target4,
&target3,
&RefTarget::from_legacy_form(
[commit5.id().clone()], // not an ancestor of commit3, 4
[commit3.id().clone(), commit4.id().clone()],
),
),
target4
);
// Existing conflict on left, right makes unrelated update
assert_eq!(
merge_ref_targets(