copy-tracking: implement copy-tracking for --types

This commit is contained in:
Matt Kulukundis 2024-08-14 09:30:31 -04:00 committed by Matt Fowles Kulukundis
parent eccc3e235d
commit 0b179dcbde
4 changed files with 46 additions and 22 deletions

View File

@ -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.

View File

@ -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(())

View File

@ -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"]);

View File

@ -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"]);