copies: ignore existing tree when testing copy/rename operation type

In this context, a tree value should be considered absent.
This commit is contained in:
Yuya Nishihara 2025-04-21 17:00:33 +09:00
parent b6a861b529
commit 0e17c0e17d
3 changed files with 83 additions and 4 deletions

View File

@ -550,7 +550,7 @@ fn test_diff_renamed_file_and_dir() {
let output = work_dir.run_jj(["diff", "--summary"]); let output = work_dir.run_jj(["diff", "--summary"]);
insta::assert_snapshot!(output.normalize_backslash(), @r" insta::assert_snapshot!(output.normalize_backslash(), @r"
R {y => x}/file R {y => x}/file
C {x => y} R {x => y}
[EOF] [EOF]
"); ");
@ -560,8 +560,8 @@ fn test_diff_renamed_file_and_dir() {
rename from y/file rename from y/file
rename to x/file rename to x/file
diff --git a/x b/y diff --git a/x b/y
copy from x rename from x
copy to y rename to y
[EOF] [EOF]
"); ");
} }

View File

@ -166,7 +166,8 @@ impl<'a> CopiesTreeDiffStream<'a> {
let (_, target_value) = values?; let (_, target_value) = values?;
let source_value = self.source_tree.path_value(source)?; let source_value = self.source_tree.path_value(source)?;
// If the source path is deleted in the target tree, it's a rename. // If the source path is deleted in the target tree, it's a rename.
let copy_op = if self.target_tree.path_value(source)?.is_absent() { let source_value_at_target = self.target_tree.path_value(source)?;
let copy_op = if source_value_at_target.is_absent() || source_value_at_target.is_tree() {
CopyOperation::Rename CopyOperation::Rename
} else { } else {
CopyOperation::Copy CopyOperation::Copy

View File

@ -43,6 +43,7 @@ use pretty_assertions::assert_eq;
use testutils::create_single_tree; use testutils::create_single_tree;
use testutils::create_tree; use testutils::create_tree;
use testutils::repo_path; use testutils::repo_path;
use testutils::repo_path_buf;
use testutils::repo_path_component; use testutils::repo_path_component;
use testutils::write_file; use testutils::write_file;
use testutils::TestRepo; use testutils::TestRepo;
@ -921,6 +922,83 @@ fn test_diff_copy_tracing() {
diff_stream_equals_iter(&before_merged, &after_merged, &EverythingMatcher); diff_stream_equals_iter(&before_merged, &after_merged, &EverythingMatcher);
} }
#[test]
fn test_diff_copy_tracing_file_and_dir() {
let test_repo = TestRepo::init();
let repo = &test_repo.repo;
// a -> b (file)
// b -> a (dir)
// c -> c/file (file)
let before = create_tree(
repo,
&[
(repo_path("a"), "content1"),
(repo_path("b/file"), "content2"),
(repo_path("c"), "content3"),
],
);
let after = create_tree(
repo,
&[
(repo_path("a/file"), "content2"),
(repo_path("b"), "content1"),
(repo_path("c/file"), "content3"),
],
);
let copy_records = create_copy_records(&[
(repo_path("a"), repo_path("b")),
(repo_path("b/file"), repo_path("a/file")),
(repo_path("c"), repo_path("c/file")),
]);
let diff: Vec<_> = before
.diff_stream_with_copies(&after, &EverythingMatcher, &copy_records)
.map(|diff| (diff.path, diff.values.unwrap()))
.collect()
.block_on();
assert_eq!(diff.len(), 3);
assert_eq!(
diff[0],
(
CopiesTreeDiffEntryPath {
source: Some((repo_path_buf("b/file"), CopyOperation::Rename)),
target: repo_path_buf("a/file"),
},
(
before.path_value(repo_path("b/file")).unwrap(),
after.path_value(repo_path("a/file")).unwrap(),
),
)
);
assert_eq!(
diff[1],
(
CopiesTreeDiffEntryPath {
source: Some((repo_path_buf("a"), CopyOperation::Rename)),
target: repo_path_buf("b"),
},
(
before.path_value(repo_path("a")).unwrap(),
after.path_value(repo_path("b")).unwrap(),
),
)
);
assert_eq!(
diff[2],
(
CopiesTreeDiffEntryPath {
source: Some((repo_path_buf("c"), CopyOperation::Rename)),
target: repo_path_buf("c/file"),
},
(
before.path_value(repo_path("c")).unwrap(),
after.path_value(repo_path("c/file")).unwrap(),
),
)
);
diff_stream_equals_iter(&before, &after, &EverythingMatcher);
}
/// Diff two conflicted trees /// Diff two conflicted trees
#[test] #[test]
fn test_diff_conflicted() { fn test_diff_conflicted() {