diff --git a/lib/tests/test_local_working_copy.rs b/lib/tests/test_local_working_copy.rs index ae4620dc57..2a29760a1f 100644 --- a/lib/tests/test_local_working_copy.rs +++ b/lib/tests/test_local_working_copy.rs @@ -35,7 +35,8 @@ use jj_lib::working_copy::{CheckoutStats, SnapshotError, SnapshotOptions}; use jj_lib::workspace::LockedWorkspace; use test_case::test_case; use testutils::{ - commit_with_tree, create_tree, write_random_commit, TestRepoBackend, TestWorkspace, + commit_with_tree, create_nonlegacy_tree, create_tree, write_random_commit, TestRepoBackend, + TestWorkspace, }; fn to_owned_path_vec(paths: &[&RepoPath]) -> Vec { @@ -329,6 +330,158 @@ fn test_conflict_subdirectory() { .unwrap(); } +#[test] +fn test_conflict_per_file_issue_2795() { + let settings = testutils::user_settings(); + let mut test_workspace = TestWorkspace::init(&settings); + let repo = &test_workspace.repo; + + let path1 = RepoPath::from_internal_string("dir/file1"); + let path2 = RepoPath::from_internal_string("dir/file2"); + let side1 = create_nonlegacy_tree(repo, &[(path1, "A\n"), (path2, "X\n")]); + let base1 = create_nonlegacy_tree(repo, &[(path1, "B\n"), (path2, "X\n")]); + let side2 = create_nonlegacy_tree(repo, &[(path1, "C\n"), (path2, "X\n")]); + let base2 = create_nonlegacy_tree(repo, &[(path1, "C\n"), (path2, "Y\n")]); + let side3 = create_nonlegacy_tree(repo, &[(path1, "C\n"), (path2, "Z\n")]); + let merged_tree = side1 + .merge(&base1, &side2) + .unwrap() + .merge(&base2, &side3) + .unwrap(); + assert_debug_snapshot!(tree_entries(&merged_tree), @r###" + [ + ( + "dir/file1", + Some( + Conflicted( + [ + Some( + File { + id: FileId( + "1c5c06be70ae033fe5fb", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "54b59f5ab966db7bcaf6", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "cf47364a5a9580666247", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "cf47364a5a9580666247", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "cf47364a5a9580666247", + ), + executable: false, + }, + ), + ], + ), + ), + ), + ( + "dir/file2", + Some( + Conflicted( + [ + Some( + File { + id: FileId( + "1f1bfb848adce5ec09e9", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "1f1bfb848adce5ec09e9", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "1f1bfb848adce5ec09e9", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "d93bab6433193bd3bb24", + ), + executable: false, + }, + ), + Some( + File { + id: FileId( + "bc0f2e7ac9ee0da40dc2", + ), + executable: false, + }, + ), + ], + ), + ), + ), + ] + "###); + let merged_commit = commit_with_tree(repo.store(), merged_tree.id()); + let repo = &test_workspace.repo; + let ws = &mut test_workspace.workspace; + ws.check_out(repo.op_id().clone(), None, &merged_commit) + .unwrap(); + // TODO: was #2795 fixed or are these not tree-level conflicts? + let file1_contents = std::fs::read_to_string(path1.to_fs_path(ws.workspace_root())).unwrap(); + assert_snapshot!(file1_contents, @r###" + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base #1 to side #1 + -B + +A + %%%%%%% Changes from base #2 to side #2 + C + +++++++ Contents of side #3 + C + >>>>>>> + "###); + let file2_contents = std::fs::read_to_string(path2.to_fs_path(ws.workspace_root())).unwrap(); + assert_snapshot!(file2_contents, @r###" + <<<<<<< Conflict 1 of 1 + %%%%%%% Changes from base #1 to side #1 + X + %%%%%%% Changes from base #2 to side #2 + -Y + +X + +++++++ Contents of side #3 + Z + >>>>>>> + "###); +} + #[test] fn test_conflict_empty_vs_nonempty_issue_3223() { let settings = testutils::user_settings(); diff --git a/lib/testutils/src/lib.rs b/lib/testutils/src/lib.rs index fa416dc53f..af790e1154 100644 --- a/lib/testutils/src/lib.rs +++ b/lib/testutils/src/lib.rs @@ -329,6 +329,13 @@ pub fn create_tree(repo: &Arc, path_contents: &[(&RepoPath, &str)] MergedTree::resolved(create_single_tree(repo, path_contents)) } +pub fn create_nonlegacy_tree( + repo: &Arc, + path_contents: &[(&RepoPath, &str)], +) -> MergedTree { + MergedTree::resolved(create_single_tree(repo, path_contents)) +} + #[must_use] pub fn create_random_tree(repo: &Arc) -> MergedTreeId { let number = rand::random::();