diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d78ff840e..53e9569c19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * A new config option `ui.always-allow-large-revsets` has been added to allow large revsets expressions in some commands, without the `all:` prefix. +* Conflict markers now include an explanation of what each part of the conflict + represents. + * New command `jj parallelize` that rebases a set of revisions into siblings. * `jj status` now supports filtering by paths. For example, `jj status .` will diff --git a/cli/tests/test_cat_command.rs b/cli/tests/test_cat_command.rs index 8c093bbb6c..ca97ce4d49 100644 --- a/cli/tests/test_cat_command.rs +++ b/cli/tests/test_cat_command.rs @@ -73,11 +73,11 @@ fn test_cat() { test_env.jj_cmd_ok(&repo_path, &["rebase", "-r", "@", "-d", "@--"]); let stdout = test_env.jj_cmd_success(&repo_path, &["cat", "file1"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -b +a - +++++++ + +++++++ Contents of side #2 c >>>>>>> "###); diff --git a/cli/tests/test_chmod_command.rs b/cli/tests/test_chmod_command.rs index a43fa15fc8..6c9f51528b 100644 --- a/cli/tests/test_chmod_command.rs +++ b/cli/tests/test_chmod_command.rs @@ -71,11 +71,11 @@ fn test_chmod_regular_conflict() { let stdout = test_env.jj_cmd_success(&repo_path, &["cat", "file"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +x - +++++++ + +++++++ Contents of side #2 n >>>>>>> "###); @@ -90,11 +90,11 @@ fn test_chmod_regular_conflict() { let stdout = test_env.jj_cmd_success(&repo_path, &["cat", "file"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +x - +++++++ + +++++++ Contents of side #2 n >>>>>>> "###); @@ -107,11 +107,11 @@ fn test_chmod_regular_conflict() { let stdout = test_env.jj_cmd_success(&repo_path, &["cat", "file"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +x - +++++++ + +++++++ Contents of side #2 n >>>>>>> "###); @@ -130,11 +130,11 @@ fn test_chmod_regular_conflict() { let stdout = test_env.jj_cmd_success(&repo_path, &["cat", "file"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +x - +++++++ + +++++++ Contents of side #2 n >>>>>>> "###); @@ -212,10 +212,10 @@ fn test_chmod_file_dir_deletion_conflicts() { let stdout = test_env.jj_cmd_success(&repo_path, &["cat", "-r=file_deletion", "file"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 1 + +++++++ Contents of side #1 a - %%%%%%% + %%%%%%% Changes from base to side #2 -base >>>>>>> "###); @@ -245,10 +245,10 @@ fn test_chmod_file_dir_deletion_conflicts() { let stdout = test_env.jj_cmd_success(&repo_path, &["cat", "-r=file_deletion", "file"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 1 + +++++++ Contents of side #1 a - %%%%%%% + %%%%%%% Changes from base to side #2 -base >>>>>>> "###); diff --git a/cli/tests/test_diffedit_command.rs b/cli/tests/test_diffedit_command.rs index b1ea6f1f97..ce7cf65351 100644 --- a/cli/tests/test_diffedit_command.rs +++ b/cli/tests/test_diffedit_command.rs @@ -395,11 +395,11 @@ fn test_diffedit_merge() { assert!(!repo_path.join("file1").exists()); let stdout = test_env.jj_cmd_success(&repo_path, &["print", "file2"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -a +c - +++++++ + +++++++ Contents of side #2 b >>>>>>> "###); diff --git a/cli/tests/test_interdiff_command.rs b/cli/tests/test_interdiff_command.rs index 67257be912..b3f8da715e 100644 --- a/cli/tests/test_interdiff_command.rs +++ b/cli/tests/test_interdiff_command.rs @@ -153,11 +153,11 @@ fn test_interdiff_conflicting() { --- a/file +++ b/file @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --foo -+abc - -+++++++ + -+++++++ Contents of side #2 -bar ->>>>>>> +def diff --git a/cli/tests/test_obslog_command.rs b/cli/tests/test_obslog_command.rs index 2d0cb29b33..99359658ae 100644 --- a/cli/tests/test_obslog_command.rs +++ b/cli/tests/test_obslog_command.rs @@ -59,10 +59,10 @@ fn test_obslog_with_or_without_diff() { @ rlvkpnrz test.user@example.com 2001-02-03 08:05:10 66b42ad3 │ my description │ Resolved conflict in file1: - │ 1 1: <<<<<<>>>>>> @@ -111,10 +111,10 @@ fn test_obslog_with_or_without_diff() { --- a/file1 +++ b/file1 @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --foo - -+++++++ + -+++++++ Contents of side #2 -foo -bar ->>>>>>> diff --git a/cli/tests/test_resolve_command.rs b/cli/tests/test_resolve_command.rs index ee97fed326..accd22089f 100644 --- a/cli/tests/test_resolve_command.rs +++ b/cli/tests/test_resolve_command.rs @@ -69,14 +69,14 @@ fn test_resolution() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("file")).unwrap() , @r###" - <<<<<<< - %%%%%%% - -base - +a - +++++++ - b - >>>>>>> - "###); + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 + -base + +a + +++++++ Contents of side #2 + b + >>>>>>> + "###); let editor_script = test_env.set_up_fake_editor(); // Check that output file starts out empty and resolve the conflict @@ -104,11 +104,11 @@ fn test_resolution() { --- a/file +++ b/file @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --base -+a - -+++++++ + -+++++++ Contents of side #2 -b ->>>>>>> +resolution @@ -144,11 +144,11 @@ fn test_resolution() { --- a/file +++ b/file @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --base -+a - -+++++++ + -+++++++ Contents of side #2 -b ->>>>>>> +resolution @@ -178,11 +178,11 @@ fn test_resolution() { ); insta::assert_snapshot!( std::fs::read_to_string(test_env.env_root().join("editor1")).unwrap(), @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +a - +++++++ + +++++++ Contents of side #2 b >>>>>>> "###); @@ -193,11 +193,11 @@ fn test_resolution() { --- a/file +++ b/file @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --base -+a - -+++++++ + -+++++++ Contents of side #2 -b ->>>>>>> +resolution @@ -253,11 +253,11 @@ fn test_resolution() { "###); insta::assert_snapshot!( std::fs::read_to_string(test_env.env_root().join("editor2")).unwrap(), @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +a - +++++++ + +++++++ Contents of side #2 b >>>>>>> "###); @@ -268,13 +268,13 @@ fn test_resolution() { --- a/file +++ b/file @@ -1,7 +1,7 @@ - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 --base -+a +-some ++fake - +++++++ + +++++++ Contents of side #2 -b +conflict >>>>>>> @@ -328,14 +328,17 @@ fn test_resolution() { --- a/file +++ b/file @@ -1,7 +1,7 @@ - <<<<<<< - %%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --base -+a + -+++++++ Contents of side #2 + -b + +<<<<<<< + +%%%%%%% +-some ++fake - +++++++ - -b + ++++++++ +conflict >>>>>>> "###); @@ -398,14 +401,14 @@ fn test_normal_conflict_input_files() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("file")).unwrap() , @r###" - <<<<<<< - %%%%%%% - -base - +a - +++++++ - b - >>>>>>> - "###); + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 + -base + +a + +++++++ Contents of side #2 + b + >>>>>>> + "###); check_resolve_produces_input_file(&mut test_env, &repo_path, "base", "base\n"); check_resolve_produces_input_file(&mut test_env, &repo_path, "left", "a\n"); @@ -439,10 +442,10 @@ fn test_baseless_conflict_input_files() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("file")).unwrap() , @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 +a - +++++++ + +++++++ Contents of side #2 b >>>>>>> "###); @@ -510,10 +513,10 @@ fn test_edit_delete_conflict_input_files() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("file")).unwrap() , @r###" - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 1 + +++++++ Contents of side #1 a - %%%%%%% + %%%%%%% Changes from base to side #2 -base >>>>>>> "###); @@ -682,22 +685,22 @@ fn test_multiple_conflicts() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("this_file_has_a_very_long_name_to_test_padding")).unwrap() , @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -first base +first a - +++++++ + +++++++ Contents of side #2 first b >>>>>>> "###); insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("another_file")).unwrap() , @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -second base +second a - +++++++ + +++++++ Contents of side #2 second b >>>>>>> "###); @@ -742,11 +745,11 @@ fn test_multiple_conflicts() { --- a/another_file +++ b/another_file @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --second base -+second a - -+++++++ + -+++++++ Contents of side #2 -second b ->>>>>>> +resolution another_file @@ -781,11 +784,11 @@ fn test_multiple_conflicts() { --- a/another_file +++ b/another_file @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --second base -+second a - -+++++++ + -+++++++ Contents of side #2 -second b ->>>>>>> +first resolution for auto-chosen file @@ -808,11 +811,11 @@ fn test_multiple_conflicts() { --- a/another_file +++ b/another_file @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --second base -+second a - -+++++++ + -+++++++ Contents of side #2 -second b ->>>>>>> +first resolution for auto-chosen file @@ -821,11 +824,11 @@ fn test_multiple_conflicts() { --- a/this_file_has_a_very_long_name_to_test_padding +++ b/this_file_has_a_very_long_name_to_test_padding @@ -1,7 +1,1 @@ - -<<<<<<< - -%%%%%%% + -<<<<<<< Conflict 1 of 1 + -%%%%%%% Changes from base to side #1 --first base -+first a - -+++++++ + -+++++++ Contents of side #2 -first b ->>>>>>> +second resolution for auto-chosen file diff --git a/cli/tests/test_restore_command.rs b/cli/tests/test_restore_command.rs index 6bc86a5b62..d1860564ea 100644 --- a/cli/tests/test_restore_command.rs +++ b/cli/tests/test_restore_command.rs @@ -171,25 +171,25 @@ fn test_restore_conflicted_merge() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("file")).unwrap() , @r###" - <<<<<<< - %%%%%%% - -base - +a - +++++++ - b - >>>>>>> - "###); + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 + -base + +a + +++++++ Contents of side #2 + b + >>>>>>> + "###); // Overwrite the file... std::fs::write(repo_path.join("file"), "resolution").unwrap(); insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["diff"]), @r###" Resolved conflict in file: - 1 : <<<<<<< - 2 : %%%%%%% + 1 : <<<<<<< Conflict 1 of 1 + 2 : %%%%%%% Changes from base to side #1 3 : -base 4 : +a - 5 : +++++++ + 5 : +++++++ Contents of side #2 6 : b 7 : >>>>>>> 1: resolution @@ -210,11 +210,11 @@ fn test_restore_conflicted_merge() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("file")).unwrap() , @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +a - +++++++ + +++++++ Contents of side #2 b >>>>>>> "###); @@ -226,11 +226,11 @@ fn test_restore_conflicted_merge() { insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["diff"]), @r###" Resolved conflict in file: - 1 : <<<<<<< - 2 : %%%%%%% + 1 : <<<<<<< Conflict 1 of 1 + 2 : %%%%%%% Changes from base to side #1 3 : -base 4 : +a - 5 : +++++++ + 5 : +++++++ Contents of side #2 6 : b 7 : >>>>>>> 1: resolution @@ -251,11 +251,11 @@ fn test_restore_conflicted_merge() { insta::assert_snapshot!( std::fs::read_to_string(repo_path.join("file")).unwrap() , @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -base +a - +++++++ + +++++++ Contents of side #2 b >>>>>>> "###); diff --git a/cli/tests/test_squash_command.rs b/cli/tests/test_squash_command.rs index 9161ca9bec..2bad4113f9 100644 --- a/cli/tests/test_squash_command.rs +++ b/cli/tests/test_squash_command.rs @@ -656,14 +656,14 @@ fn test_squash_from_multiple() { // The changes from the sources have been applied let stdout = test_env.jj_cmd_success(&repo_path, &["print", "-r=d", "file"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base #1 to side #1 -a +d - %%%%%%% + %%%%%%% Changes from base #2 to side #2 -a +b - +++++++ + +++++++ Contents of side #3 c >>>>>>> "###); @@ -794,14 +794,14 @@ fn test_squash_from_multiple_partial() { // The selected changes from the sources have been applied let stdout = test_env.jj_cmd_success(&repo_path, &["print", "-r=d", "file1"]); insta::assert_snapshot!(stdout, @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base #1 to side #1 -a +d - %%%%%%% + %%%%%%% Changes from base #2 to side #2 -a +b - +++++++ + +++++++ Contents of side #3 c >>>>>>> "###); diff --git a/lib/src/conflicts.rs b/lib/src/conflicts.rs index d985814412..6ca456c481 100644 --- a/lib/src/conflicts.rs +++ b/lib/src/conflicts.rs @@ -29,11 +29,11 @@ use crate::merge::{Merge, MergeBuilder, MergedTreeValue}; use crate::repo_path::RepoPath; use crate::store::Store; -const CONFLICT_START_LINE: &[u8] = b"<<<<<<<\n"; -const CONFLICT_END_LINE: &[u8] = b">>>>>>>\n"; -const CONFLICT_DIFF_LINE: &[u8] = b"%%%%%%%\n"; -const CONFLICT_MINUS_LINE: &[u8] = b"-------\n"; -const CONFLICT_PLUS_LINE: &[u8] = b"+++++++\n"; +const CONFLICT_START_LINE: &[u8] = b"<<<<<<<"; +const CONFLICT_END_LINE: &[u8] = b">>>>>>>"; +const CONFLICT_DIFF_LINE: &[u8] = b"%%%%%%%"; +const CONFLICT_MINUS_LINE: &[u8] = b"-------"; +const CONFLICT_PLUS_LINE: &[u8] = b"+++++++"; const CONFLICT_START_LINE_CHAR: u8 = CONFLICT_START_LINE[0]; const CONFLICT_END_LINE_CHAR: u8 = CONFLICT_END_LINE[0]; const CONFLICT_DIFF_LINE_CHAR: u8 = CONFLICT_DIFF_LINE[0]; @@ -199,19 +199,37 @@ pub fn materialize_merge_result( output.write_all(&content.0)?; } MergeResult::Conflict(hunks) => { + let num_conflicts = hunks + .iter() + .filter(|hunk| hunk.as_resolved().is_none()) + .count(); + let mut conflict_index = 0; for hunk in hunks { if let Some(content) = hunk.as_resolved() { output.write_all(&content.0)?; } else { + conflict_index += 1; output.write_all(CONFLICT_START_LINE)?; + output.write_all( + format!(" Conflict {conflict_index} of {num_conflicts}\n").as_bytes(), + )?; let mut add_index = 0; - for left in hunk.removes() { + for (base_index, left) in hunk.removes().enumerate() { + // The vast majority of conflicts one actually tries to + // resolve manually have 1 base. + let base_str = if hunk.removes().len() == 1 { + "base".to_string() + } else { + format!("base #{}", base_index + 1) + }; + let right1 = if let Some(right1) = hunk.get_add(add_index) { right1 } else { // If we have no more positive terms, emit the remaining negative // terms as snapshots. output.write_all(CONFLICT_MINUS_LINE)?; + output.write_all(format!(" Contents of {base_str}\n").as_bytes())?; output.write_all(&left.0)?; continue; }; @@ -231,8 +249,18 @@ pub fn materialize_merge_result( // the current positive term as a snapshot and the next // positive term as a diff. output.write_all(CONFLICT_PLUS_LINE)?; + output.write_all( + format!(" Contents of side #{}\n", add_index + 1).as_bytes(), + )?; output.write_all(&right1.0)?; output.write_all(CONFLICT_DIFF_LINE)?; + output.write_all( + format!( + " Changes from {base_str} to side #{}\n", + add_index + 2 + ) + .as_bytes(), + )?; write_diff_hunks(&diff2, output)?; add_index += 2; continue; @@ -240,16 +268,24 @@ pub fn materialize_merge_result( } output.write_all(CONFLICT_DIFF_LINE)?; + output.write_all( + format!(" Changes from {base_str} to side #{}\n", add_index + 1) + .as_bytes(), + )?; write_diff_hunks(&diff1, output)?; add_index += 1; } // Emit the remaining positive terms as snapshots. - for slice in hunk.adds().skip(add_index) { + for (add_index, slice) in hunk.adds().enumerate().skip(add_index) { output.write_all(CONFLICT_PLUS_LINE)?; + output.write_all( + format!(" Contents of side #{}\n", add_index + 1).as_bytes(), + )?; output.write_all(&slice.0)?; } output.write_all(CONFLICT_END_LINE)?; + output.write_all(b"\n")?; } } } diff --git a/lib/tests/test_conflicts.rs b/lib/tests/test_conflicts.rs index 69bad65947..52638d584b 100644 --- a/lib/tests/test_conflicts.rs +++ b/lib/tests/test_conflicts.rs @@ -77,12 +77,12 @@ fn test_materialize_conflict_basic() { @r###" line 1 line 2 - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 1 + +++++++ Contents of side #1 left 3.1 left 3.2 left 3.3 - %%%%%%% + %%%%%%% Changes from base to side #2 -line 3 +right 3.1 >>>>>>> @@ -101,11 +101,11 @@ fn test_materialize_conflict_basic() { @r###" line 1 line 2 - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -line 3 +right 3.1 - +++++++ + +++++++ Contents of side #2 left 3.1 left 3.2 left 3.3 @@ -173,16 +173,16 @@ fn test_materialize_conflict_multi_rebase_conflicts() { &materialize_conflict_string(store, path, &conflict), @r###" line 1 - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 1 + +++++++ Contents of side #1 line 2 a.1 line 2 a.2 line 2 a.3 - %%%%%%% + %%%%%%% Changes from base #1 to side #2 -line 2 base +line 2 b.1 +line 2 b.2 - %%%%%%% + %%%%%%% Changes from base #2 to side #3 -line 2 base +line 2 c.1 >>>>>>> @@ -197,15 +197,15 @@ fn test_materialize_conflict_multi_rebase_conflicts() { &materialize_conflict_string(store, path, &conflict), @r###" line 1 - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base #1 to side #1 -line 2 base +line 2 c.1 - %%%%%%% + %%%%%%% Changes from base #2 to side #2 -line 2 base +line 2 b.1 +line 2 b.2 - +++++++ + +++++++ Contents of side #3 line 2 a.1 line 2 a.2 line 2 a.3 @@ -221,15 +221,15 @@ fn test_materialize_conflict_multi_rebase_conflicts() { &materialize_conflict_string(store, path, &conflict), @r###" line 1 - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base #1 to side #1 -line 2 base +line 2 c.1 - +++++++ + +++++++ Contents of side #2 line 2 a.1 line 2 a.2 line 2 a.3 - %%%%%%% + %%%%%%% Changes from base #2 to side #3 -line 2 base +line 2 b.1 +line 2 b.2 @@ -288,22 +288,22 @@ fn test_materialize_parse_roundtrip() { insta::assert_snapshot!( materialized, @r###" - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 2 + +++++++ Contents of side #1 line 1 left line 2 left - %%%%%%% + %%%%%%% Changes from base to side #2 -line 1 +line 1 right line 2 >>>>>>> line 3 - <<<<<<< - %%%%%%% + <<<<<<< Conflict 2 of 2 + %%%%%%% Changes from base to side #1 line 4 -line 5 +line 5 left - +++++++ + +++++++ Contents of side #2 line 4 right line 5 right >>>>>>> @@ -385,10 +385,10 @@ fn test_materialize_conflict_modify_delete() { insta::assert_snapshot!(&materialize_conflict_string(store, path, &conflict), @r###" line 1 line 2 - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 1 + +++++++ Contents of side #1 modified - %%%%%%% + %%%%%%% Changes from base to side #2 -line 3 >>>>>>> line 4 @@ -404,10 +404,10 @@ fn test_materialize_conflict_modify_delete() { insta::assert_snapshot!(&materialize_conflict_string(store, path, &conflict), @r###" line 1 line 2 - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 -line 3 - +++++++ + +++++++ Contents of side #2 modified >>>>>>> line 4 @@ -421,15 +421,15 @@ fn test_materialize_conflict_modify_delete() { vec![Some(modified_id.clone()), None], ); insta::assert_snapshot!(&materialize_conflict_string(store, path, &conflict), @r###" - <<<<<<< - %%%%%%% + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base to side #1 line 1 line 2 -line 3 +modified line 4 line 5 - +++++++ + +++++++ Contents of side #2 >>>>>>> "### ); @@ -474,16 +474,16 @@ fn test_materialize_conflict_two_forward_diffs() { insta::assert_snapshot!( &materialize_conflict_string(store, path, &conflict), @r###" - <<<<<<< - +++++++ + <<<<<<< Conflict 1 of 1 + +++++++ Contents of side #1 A - %%%%%%% + %%%%%%% Changes from base #1 to side #2 B - +++++++ + +++++++ Contents of side #3 D - %%%%%%% + %%%%%%% Changes from base #2 to side #4 C - ------- + ------- Contents of base #3 E >>>>>>> "###