forked from mirrors/jj
conflicts: fix off-by-one error in materialize_merge_result()
This should fix #1304. I think the added test simulates the behavior of multiple rebase conflicts, but I don't have expertise around this. add_index could be replaced with a peekable iterator, but the iterator version wouldn't be as readable as the current implementation.
This commit is contained in:
parent
0224b52ffc
commit
da16bf340c
2 changed files with 136 additions and 7 deletions
|
@ -210,11 +210,9 @@ pub fn materialize_merge_result(
|
||||||
// Check if the diff against the next positive term is better. Since
|
// Check if the diff against the next positive term is better. Since
|
||||||
// we want to preserve the order of the terms, we don't match against
|
// we want to preserve the order of the terms, we don't match against
|
||||||
// any later positive terms.
|
// any later positive terms.
|
||||||
if add_index < adds.len() {
|
if let Some(right2) = adds.get(add_index + 1) {
|
||||||
let diff2 = Diff::for_tokenizer(
|
let diff2 =
|
||||||
&[&left, &adds[add_index + 1]],
|
Diff::for_tokenizer(&[&left, right2], &find_line_ranges)
|
||||||
&find_line_ranges,
|
|
||||||
)
|
|
||||||
.hunks()
|
.hunks()
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
if diff_size(&diff2) < diff_size(&diff1) {
|
if diff_size(&diff2) < diff_size(&diff1) {
|
||||||
|
|
|
@ -114,6 +114,137 @@ line 5
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_materialize_conflict_multi_rebase_conflicts() {
|
||||||
|
let test_repo = TestRepo::init(false);
|
||||||
|
let store = test_repo.repo.store();
|
||||||
|
|
||||||
|
// Create changes (a, b, c) on top of the base, and linearize them.
|
||||||
|
let path = RepoPath::from_internal_string("file");
|
||||||
|
let base_id = testutils::write_file(
|
||||||
|
store,
|
||||||
|
&path,
|
||||||
|
"line 1
|
||||||
|
line 2 base
|
||||||
|
line 3
|
||||||
|
",
|
||||||
|
);
|
||||||
|
let a_id = testutils::write_file(
|
||||||
|
store,
|
||||||
|
&path,
|
||||||
|
"line 1
|
||||||
|
line 2 a.1
|
||||||
|
line 2 a.2
|
||||||
|
line 2 a.3
|
||||||
|
line 3
|
||||||
|
",
|
||||||
|
);
|
||||||
|
let b_id = testutils::write_file(
|
||||||
|
store,
|
||||||
|
&path,
|
||||||
|
"line 1
|
||||||
|
line 2 b.1
|
||||||
|
line 2 b.2
|
||||||
|
line 3
|
||||||
|
",
|
||||||
|
);
|
||||||
|
let c_id = testutils::write_file(
|
||||||
|
store,
|
||||||
|
&path,
|
||||||
|
"line 1
|
||||||
|
line 2 c.1
|
||||||
|
line 3
|
||||||
|
",
|
||||||
|
);
|
||||||
|
|
||||||
|
// The order of (a, b, c) should be preserved. For all cases, the "a" side
|
||||||
|
// should be a snapshot.
|
||||||
|
let conflict = Conflict {
|
||||||
|
removes: vec![file_conflict_term(&base_id), file_conflict_term(&base_id)],
|
||||||
|
adds: vec![
|
||||||
|
file_conflict_term(&a_id),
|
||||||
|
file_conflict_term(&b_id),
|
||||||
|
file_conflict_term(&c_id),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
insta::assert_snapshot!(
|
||||||
|
&materialize_conflict_string(store, &path, &conflict),
|
||||||
|
@r###"
|
||||||
|
line 1
|
||||||
|
<<<<<<<
|
||||||
|
+++++++
|
||||||
|
line 2 a.1
|
||||||
|
line 2 a.2
|
||||||
|
line 2 a.3
|
||||||
|
%%%%%%%
|
||||||
|
-line 2 base
|
||||||
|
+line 2 b.1
|
||||||
|
+line 2 b.2
|
||||||
|
%%%%%%%
|
||||||
|
-line 2 base
|
||||||
|
+line 2 c.1
|
||||||
|
>>>>>>>
|
||||||
|
line 3
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
let conflict = Conflict {
|
||||||
|
removes: vec![file_conflict_term(&base_id), file_conflict_term(&base_id)],
|
||||||
|
adds: vec![
|
||||||
|
file_conflict_term(&c_id),
|
||||||
|
file_conflict_term(&b_id),
|
||||||
|
file_conflict_term(&a_id),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
insta::assert_snapshot!(
|
||||||
|
&materialize_conflict_string(store, &path, &conflict),
|
||||||
|
@r###"
|
||||||
|
line 1
|
||||||
|
<<<<<<<
|
||||||
|
%%%%%%%
|
||||||
|
-line 2 base
|
||||||
|
+line 2 c.1
|
||||||
|
%%%%%%%
|
||||||
|
-line 2 base
|
||||||
|
+line 2 b.1
|
||||||
|
+line 2 b.2
|
||||||
|
+++++++
|
||||||
|
line 2 a.1
|
||||||
|
line 2 a.2
|
||||||
|
line 2 a.3
|
||||||
|
>>>>>>>
|
||||||
|
line 3
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
let conflict = Conflict {
|
||||||
|
removes: vec![file_conflict_term(&base_id), file_conflict_term(&base_id)],
|
||||||
|
adds: vec![
|
||||||
|
file_conflict_term(&c_id),
|
||||||
|
file_conflict_term(&a_id),
|
||||||
|
file_conflict_term(&b_id),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
insta::assert_snapshot!(
|
||||||
|
&materialize_conflict_string(store, &path, &conflict),
|
||||||
|
@r###"
|
||||||
|
line 1
|
||||||
|
<<<<<<<
|
||||||
|
%%%%%%%
|
||||||
|
-line 2 base
|
||||||
|
+line 2 c.1
|
||||||
|
+++++++
|
||||||
|
line 2 a.1
|
||||||
|
line 2 a.2
|
||||||
|
line 2 a.3
|
||||||
|
%%%%%%%
|
||||||
|
-line 2 base
|
||||||
|
+line 2 b.1
|
||||||
|
+line 2 b.2
|
||||||
|
>>>>>>>
|
||||||
|
line 3
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_materialize_parse_roundtrip() {
|
fn test_materialize_parse_roundtrip() {
|
||||||
let test_repo = TestRepo::init(false);
|
let test_repo = TestRepo::init(false);
|
||||||
|
|
Loading…
Reference in a new issue