ok/jj
1
0
Fork 0
forked from mirrors/jj

copies: provide source path mapping by CopyRecords

All for/has_source/target() combinations are added for API consistency.
This commit is contained in:
Yuya Nishihara 2024-08-20 21:31:06 +09:00
parent 5e356ffd24
commit 2cffcc9323
2 changed files with 31 additions and 25 deletions

View file

@ -396,13 +396,6 @@ pub fn get_copy_records<'a>(
Ok(block_on_stream(stream).filter_ok(|record| matcher.matches(&record.target))) Ok(block_on_stream(stream).filter_ok(|record| matcher.matches(&record.target)))
} }
fn collect_copied_sources(copy_records: &CopyRecords) -> HashSet<&RepoPath> {
copy_records
.iter()
.map(|record| record.source.as_ref())
.collect()
}
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct ColorWordsOptions { pub struct ColorWordsOptions {
/// Number of context lines to show. /// Number of context lines to show.
@ -919,7 +912,6 @@ pub fn show_file_by_file_diff(
std::fs::write(&fs_path, content.contents)?; std::fs::write(&fs_path, content.contents)?;
Ok(fs_path) Ok(fs_path)
} }
let copied_sources = collect_copied_sources(copy_records);
let temp_dir = new_utf8_temp_dir("jj-diff-")?; let temp_dir = new_utf8_temp_dir("jj-diff-")?;
let left_wc_dir = temp_dir.path().join("left"); let left_wc_dir = temp_dir.path().join("left");
@ -933,7 +925,7 @@ pub fn show_file_by_file_diff(
}) = diff_stream.next().await }) = diff_stream.next().await
{ {
let (left_value, right_value) = diff?; let (left_value, right_value) = diff?;
if right_value.is_absent() && copied_sources.contains(left_path.as_ref()) { if right_value.is_absent() && copy_records.has_source(&left_path) {
continue; continue;
} }
@ -1272,7 +1264,6 @@ pub fn show_git_diff(
) -> Result<(), DiffRenderError> { ) -> Result<(), DiffRenderError> {
let tree_diff = from_tree.diff_stream_with_copies(to_tree, matcher, copy_records); let tree_diff = from_tree.diff_stream_with_copies(to_tree, matcher, copy_records);
let mut diff_stream = materialized_diff_stream(store, tree_diff); let mut diff_stream = materialized_diff_stream(store, tree_diff);
let copied_sources = collect_copied_sources(copy_records);
async { async {
while let Some(MaterializedTreeDiffEntry { while let Some(MaterializedTreeDiffEntry {
@ -1289,7 +1280,7 @@ pub fn show_git_diff(
let right_part = git_diff_part(&right_path, right_value)?; let right_part = git_diff_part(&right_path, right_value)?;
// Skip the "delete" entry when there is a rename. // Skip the "delete" entry when there is a rename.
if right_part.mode.is_none() && copied_sources.contains(left_path.as_ref()) { if right_part.mode.is_none() && copy_records.has_source(&left_path) {
continue; continue;
} }
@ -1382,7 +1373,6 @@ pub fn show_diff_summary(
copy_records: &CopyRecords, copy_records: &CopyRecords,
) -> Result<(), DiffRenderError> { ) -> Result<(), DiffRenderError> {
let mut tree_diff = from_tree.diff_stream_with_copies(to_tree, matcher, copy_records); let mut tree_diff = from_tree.diff_stream_with_copies(to_tree, matcher, copy_records);
let copied_sources = collect_copied_sources(copy_records);
async { async {
while let Some(CopiesTreeDiffEntry { while let Some(CopiesTreeDiffEntry {
@ -1405,7 +1395,7 @@ pub fn show_diff_summary(
(true, true) => writeln!(formatter.labeled("modified"), "M {path}")?, (true, true) => writeln!(formatter.labeled("modified"), "M {path}")?,
(false, true) => writeln!(formatter.labeled("added"), "A {path}")?, (false, true) => writeln!(formatter.labeled("added"), "A {path}")?,
(true, false) => { (true, false) => {
if !copied_sources.contains(before_path.as_ref()) { if !copy_records.has_source(&before_path) {
writeln!(formatter.labeled("removed"), "D {path}")?; writeln!(formatter.labeled("removed"), "D {path}")?;
} }
} }
@ -1555,7 +1545,6 @@ pub fn show_types(
copy_records: &CopyRecords, copy_records: &CopyRecords,
) -> Result<(), DiffRenderError> { ) -> Result<(), DiffRenderError> {
let mut tree_diff = from_tree.diff_stream_with_copies(to_tree, matcher, copy_records); let mut tree_diff = from_tree.diff_stream_with_copies(to_tree, matcher, copy_records);
let copied_sources = collect_copied_sources(copy_records);
async { async {
while let Some(CopiesTreeDiffEntry { while let Some(CopiesTreeDiffEntry {
@ -1565,7 +1554,7 @@ pub fn show_types(
}) = tree_diff.next().await }) = tree_diff.next().await
{ {
let (before, after) = diff?; let (before, after) = diff?;
if after.is_absent() && copied_sources.contains(source.as_ref()) { if after.is_absent() && copy_records.has_source(&source) {
continue; continue;
} }
writeln!( writeln!(

View file

@ -29,8 +29,9 @@ use crate::repo_path::{RepoPath, RepoPathBuf};
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct CopyRecords { pub struct CopyRecords {
records: Vec<CopyRecord>, records: Vec<CopyRecord>,
// Maps from `target` to the index of the target in `records`. Conflicts // Maps from `source` or `target` to the index of the entry in `records`.
// are excluded by keeping an out of range value. // Conflicts are excluded by keeping an out of range value.
sources: HashMap<RepoPathBuf, usize>,
targets: HashMap<RepoPathBuf, usize>, targets: HashMap<RepoPathBuf, usize>,
} }
@ -43,20 +44,36 @@ impl CopyRecords {
) -> BackendResult<()> { ) -> BackendResult<()> {
for record in copy_records { for record in copy_records {
let r = record?; let r = record?;
let value = self self.sources
.targets .entry(r.source.clone())
.entry(r.target.clone())
.or_insert(self.records.len());
if *value != self.records.len() {
// TODO: handle conflicts instead of ignoring both sides. // TODO: handle conflicts instead of ignoring both sides.
*value = usize::MAX; .and_modify(|value| *value = usize::MAX)
} .or_insert(self.records.len());
self.targets
.entry(r.target.clone())
// TODO: handle conflicts instead of ignoring both sides.
.and_modify(|value| *value = usize::MAX)
.or_insert(self.records.len());
self.records.push(r); self.records.push(r);
} }
Ok(()) Ok(())
} }
/// Returns true if there are copy records associated with a source path.
pub fn has_source(&self, source: &RepoPath) -> bool {
self.sources.contains_key(source)
}
/// Gets any copy record associated with a source path.
pub fn for_source(&self, source: &RepoPath) -> Option<&CopyRecord> {
self.sources.get(source).and_then(|&i| self.records.get(i))
}
/// Returns true if there are copy records associated with a target path.
pub fn has_target(&self, target: &RepoPath) -> bool {
self.targets.contains_key(target)
}
/// Gets any copy record associated with a target path. /// Gets any copy record associated with a target path.
pub fn for_target(&self, target: &RepoPath) -> Option<&CopyRecord> { pub fn for_target(&self, target: &RepoPath) -> Option<&CopyRecord> {
self.targets.get(target).and_then(|&i| self.records.get(i)) self.targets.get(target).and_then(|&i| self.records.get(i))