diff --git a/CHANGELOG.md b/CHANGELOG.md index 610d20ab3..f5aad64ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### New features * The following diff formats now include information about copies and moves: - `--color-words`, `--stat`, `--summary` + `--color-words`, `--stat`, `--summary`, `--types` * A tilde (`~`) at the start of the path will now be expanded to the user's home directory when configuring a `signing.key` for SSH commit signing. diff --git a/cli/src/diff_util.rs b/cli/src/diff_util.rs index 0dc1bd63b..a7b552144 100644 --- a/cli/src/diff_util.rs +++ b/cli/src/diff_util.rs @@ -294,9 +294,14 @@ impl<'a> DiffRenderer<'a> { show_diff_stat(formatter, store, tree_diff, path_converter, width)?; } DiffFormat::Types => { - let no_copy_tracking = Default::default(); - let tree_diff = from_tree.diff_stream(to_tree, matcher, &no_copy_tracking); - show_types(formatter, tree_diff, path_converter)?; + show_types( + formatter, + path_converter, + from_tree, + to_tree, + matcher, + copy_records, + )?; } DiffFormat::NameOnly => { let tree_diff = from_tree.diff_stream(to_tree, matcher, copy_records); @@ -368,6 +373,22 @@ impl<'a> DiffRenderer<'a> { } } +fn collect_copied_sources<'a>( + copy_records: &'a CopyRecords, + matcher: &dyn Matcher, +) -> HashSet<&'a RepoPath> { + copy_records + .iter() + .filter_map(|record| { + if matcher.matches(&record.target) { + Some(record.source.as_ref()) + } else { + None + } + }) + .collect() +} + fn show_color_words_diff_hunks( left: &[u8], right: &[u8], @@ -1168,17 +1189,7 @@ pub fn show_diff_summary( copy_records: &CopyRecords, ) -> io::Result<()> { let mut tree_diff = from_tree.diff_stream(to_tree, matcher, copy_records); - - let copied_sources: HashSet<&RepoPath> = copy_records - .iter() - .filter_map(|record| { - if matcher.matches(&record.target) { - Some(record.source.as_ref()) - } else { - None - } - }) - .collect(); + let copied_sources = collect_copied_sources(copy_records, matcher); async { while let Some(TreeDiffEntry { @@ -1345,23 +1356,32 @@ pub fn show_diff_stat( pub fn show_types( formatter: &mut dyn Formatter, - mut tree_diff: TreeDiffStream, path_converter: &RepoPathUiConverter, + from_tree: &MergedTree, + to_tree: &MergedTree, + matcher: &dyn Matcher, + copy_records: &CopyRecords, ) -> io::Result<()> { + let mut tree_diff = from_tree.diff_stream(to_tree, matcher, copy_records); + let copied_sources = collect_copied_sources(copy_records, matcher); + async { while let Some(TreeDiffEntry { - source: _, // TODO handle copy tracking - target: repo_path, + source, + target, value: diff, }) = tree_diff.next().await { let (before, after) = diff.unwrap(); + if after.is_absent() && copied_sources.contains(source.as_ref()) { + continue; + } writeln!( formatter.labeled("modified"), "{}{} {}", diff_summary_char(&before), diff_summary_char(&after), - path_converter.format_file_path(&repo_path) + path_converter.format_copied_path(&source, &target) )?; } Ok(()) diff --git a/cli/tests/test_diff_command.rs b/cli/tests/test_diff_command.rs index aba7cb7d6..5489a7b17 100644 --- a/cli/tests/test_diff_command.rs +++ b/cli/tests/test_diff_command.rs @@ -70,9 +70,14 @@ fn test_diff_basic() { let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--types"]); insta::assert_snapshot!(stdout, @r###" + FF file2 + FF {file1 => file3} + "###); + + let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--types", "glob:file[12]"]); + insta::assert_snapshot!(stdout, @r###" F- file1 FF file2 - -F file3 "###); let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git"]); diff --git a/cli/tests/test_show_command.rs b/cli/tests/test_show_command.rs index 3c1576cc5..4a1d9cdbc 100644 --- a/cli/tests/test_show_command.rs +++ b/cli/tests/test_show_command.rs @@ -123,9 +123,8 @@ fn test_show_basic() { (no description set) - F- file1 FF file2 - -F file3 + FF {file1 => file3} "###); let stdout = test_env.jj_cmd_success(&repo_path, &["show", "--git"]);