From 721aa1238c5ceef7012082e80fe66b8bdc271ab2 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Sat, 17 Aug 2024 14:18:24 -0700 Subject: [PATCH] copies: add a separate diff stream item type with copy info The goal is to have the new item type know if it represent a copy, a rename, a deleted rename source, or a regular copy-unrelated item. --- cli/src/commit_templater.rs | 11 ++++++----- cli/src/diff_util.rs | 19 ++++++++++--------- lib/src/conflicts.rs | 7 ++++--- lib/src/copies.rs | 23 +++++++++++++++++++---- lib/src/merged_tree.rs | 4 ++-- 5 files changed, 41 insertions(+), 23 deletions(-) diff --git a/cli/src/commit_templater.rs b/cli/src/commit_templater.rs index 623ec26ff..6d968f438 100644 --- a/cli/src/commit_templater.rs +++ b/cli/src/commit_templater.rs @@ -18,17 +18,18 @@ use std::collections::HashMap; use std::io; use std::rc::Rc; +use futures::stream::BoxStream; use itertools::Itertools as _; use jj_lib::backend::{BackendResult, ChangeId, CommitId}; use jj_lib::commit::Commit; -use jj_lib::copies::CopyRecords; +use jj_lib::copies::{CopiesTreeDiffEntry, CopyRecords}; use jj_lib::extensions_map::ExtensionsMap; use jj_lib::fileset::{self, FilesetExpression}; use jj_lib::git; use jj_lib::hex_util::to_reverse_hex; use jj_lib::id_prefix::IdPrefixContext; use jj_lib::matchers::Matcher; -use jj_lib::merged_tree::{MergedTree, TreeDiffStream}; +use jj_lib::merged_tree::MergedTree; use jj_lib::object_id::ObjectId as _; use jj_lib::op_store::{RefTarget, RemoteRef, WorkspaceId}; use jj_lib::repo::Repo; @@ -1296,14 +1297,14 @@ impl TreeDiff { }) } - fn diff_stream(&self) -> TreeDiffStream<'_> { + fn diff_stream(&self) -> BoxStream<'_, CopiesTreeDiffEntry> { self.from_tree .diff_stream_with_copies(&self.to_tree, &*self.matcher, &self.copy_records) } fn into_formatted(self, show: F) -> TreeDiffFormatted where - F: Fn(&mut dyn Formatter, &Store, TreeDiffStream) -> Result<(), E>, + F: Fn(&mut dyn Formatter, &Store, BoxStream) -> Result<(), E>, E: Into, { TreeDiffFormatted { diff: self, show } @@ -1318,7 +1319,7 @@ struct TreeDiffFormatted { impl Template for TreeDiffFormatted where - F: Fn(&mut dyn Formatter, &Store, TreeDiffStream) -> Result<(), E>, + F: Fn(&mut dyn Formatter, &Store, BoxStream) -> Result<(), E>, E: Into, { fn format(&self, formatter: &mut TemplateFormatter) -> io::Result<()> { diff --git a/cli/src/diff_util.rs b/cli/src/diff_util.rs index 91757040b..3ebfc9a8d 100644 --- a/cli/src/diff_util.rs +++ b/cli/src/diff_util.rs @@ -18,6 +18,7 @@ use std::ops::Range; use std::path::{Path, PathBuf}; use std::{io, mem}; +use futures::stream::BoxStream; use futures::StreamExt; use itertools::Itertools; use jj_lib::backend::{BackendError, TreeValue}; @@ -25,12 +26,12 @@ use jj_lib::commit::Commit; use jj_lib::conflicts::{ materialized_diff_stream, MaterializedTreeDiffEntry, MaterializedTreeValue, }; -use jj_lib::copies::CopyRecords; +use jj_lib::copies::{CopiesTreeDiffEntry, CopyRecords}; use jj_lib::diff::{Diff, DiffHunk}; use jj_lib::files::{DiffLine, DiffLineHunkSide, DiffLineIterator, DiffLineNumber}; use jj_lib::matchers::Matcher; use jj_lib::merge::MergedTreeValue; -use jj_lib::merged_tree::{MergedTree, TreeDiffEntry, TreeDiffStream}; +use jj_lib::merged_tree::MergedTree; use jj_lib::object_id::ObjectId; use jj_lib::repo::Repo; use jj_lib::repo_path::{RepoPath, RepoPathUiConverter}; @@ -652,7 +653,7 @@ fn basic_diff_file_type(value: &MaterializedTreeValue) -> &'static str { pub fn show_color_words_diff( formatter: &mut dyn Formatter, store: &Store, - tree_diff: TreeDiffStream, + tree_diff: BoxStream, path_converter: &RepoPathUiConverter, num_context_lines: usize, ) -> Result<(), DiffRenderError> { @@ -808,7 +809,7 @@ pub fn show_file_by_file_diff( ui: &Ui, formatter: &mut dyn Formatter, store: &Store, - tree_diff: TreeDiffStream, + tree_diff: BoxStream, path_converter: &RepoPathUiConverter, matcher: &dyn Matcher, copy_records: &CopyRecords, @@ -1279,7 +1280,7 @@ pub fn show_diff_summary( let copied_sources = collect_copied_sources(copy_records, matcher); async { - while let Some(TreeDiffEntry { + while let Some(CopiesTreeDiffEntry { source: before_path, target: after_path, value: diff, @@ -1351,7 +1352,7 @@ fn get_diff_stat( pub fn show_diff_stat( formatter: &mut dyn Formatter, store: &Store, - tree_diff: TreeDiffStream, + tree_diff: BoxStream, path_converter: &RepoPathUiConverter, display_width: usize, ) -> Result<(), DiffRenderError> { @@ -1452,7 +1453,7 @@ pub fn show_types( let copied_sources = collect_copied_sources(copy_records, matcher); async { - while let Some(TreeDiffEntry { + while let Some(CopiesTreeDiffEntry { source, target, value: diff, @@ -1490,11 +1491,11 @@ fn diff_summary_char(value: &MergedTreeValue) -> char { pub fn show_names( formatter: &mut dyn Formatter, - mut tree_diff: TreeDiffStream, + mut tree_diff: BoxStream, path_converter: &RepoPathUiConverter, ) -> io::Result<()> { async { - while let Some(TreeDiffEntry { + while let Some(CopiesTreeDiffEntry { target: repo_path, .. }) = tree_diff.next().await { diff --git a/lib/src/conflicts.rs b/lib/src/conflicts.rs index 9cb50d678..2030f3fdd 100644 --- a/lib/src/conflicts.rs +++ b/lib/src/conflicts.rs @@ -17,16 +17,17 @@ use std::io::{Read, Write}; use std::iter::zip; +use futures::stream::BoxStream; use futures::{try_join, Stream, StreamExt, TryStreamExt}; use itertools::Itertools; use regex::bytes::{Regex, RegexBuilder}; use crate::backend::{BackendError, BackendResult, CommitId, FileId, SymlinkId, TreeId, TreeValue}; +use crate::copies::CopiesTreeDiffEntry; use crate::diff::{Diff, DiffHunk}; use crate::files; use crate::files::{ContentHunk, MergeResult}; use crate::merge::{Merge, MergeBuilder, MergedTreeValue}; -use crate::merged_tree::{TreeDiffEntry, TreeDiffStream}; use crate::repo_path::{RepoPath, RepoPathBuf}; use crate::store::Store; @@ -333,11 +334,11 @@ pub struct MaterializedTreeDiffEntry { pub fn materialized_diff_stream<'a>( store: &'a Store, - tree_diff: TreeDiffStream<'a>, + tree_diff: BoxStream<'a, CopiesTreeDiffEntry>, ) -> impl Stream + 'a { tree_diff .map( - |TreeDiffEntry { + |CopiesTreeDiffEntry { source, target, value, diff --git a/lib/src/copies.rs b/lib/src/copies.rs index b8521fac3..7c5b6d7e4 100644 --- a/lib/src/copies.rs +++ b/lib/src/copies.rs @@ -23,7 +23,8 @@ use futures::stream::BoxStream; use futures::Stream; use crate::backend::{BackendResult, CopyRecord}; -use crate::merged_tree::{MergedTree, TreeDiffEntry, TreeDiffStream}; +use crate::merge::MergedTreeValue; +use crate::merged_tree::{MergedTree, TreeDiffStream}; use crate::repo_path::{RepoPath, RepoPathBuf}; /// A collection of CopyRecords. @@ -91,8 +92,18 @@ impl<'a> CopiesTreeDiffStream<'a> { } } +/// A `TreeDiffEntry` with copy information. +pub struct CopiesTreeDiffEntry { + /// The source path. + pub source: RepoPathBuf, + /// The target path. + pub target: RepoPathBuf, + /// The resolved tree values if available. + pub value: BackendResult<(MergedTreeValue, MergedTreeValue)>, +} + impl Stream for CopiesTreeDiffStream<'_> { - type Item = TreeDiffEntry; + type Item = CopiesTreeDiffEntry; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.as_mut().poll_next(cx).map(|option| { @@ -100,10 +111,14 @@ impl Stream for CopiesTreeDiffStream<'_> { let Some(CopyRecord { source, .. }) = self.copy_records.for_target(&diff_entry.target) else { - return diff_entry; + return CopiesTreeDiffEntry { + source: diff_entry.source, + target: diff_entry.target, + value: diff_entry.value, + }; }; - TreeDiffEntry { + CopiesTreeDiffEntry { source: source.clone(), target: diff_entry.target, value: diff_entry.value.and_then(|(_, target_value)| { diff --git a/lib/src/merged_tree.rs b/lib/src/merged_tree.rs index c30b393f4..8e36752d8 100644 --- a/lib/src/merged_tree.rs +++ b/lib/src/merged_tree.rs @@ -31,7 +31,7 @@ use itertools::{EitherOrBoth, Itertools}; use crate::backend; use crate::backend::{BackendResult, MergedTreeId, TreeId, TreeValue}; -use crate::copies::{CopiesTreeDiffStream, CopyRecords}; +use crate::copies::{CopiesTreeDiffEntry, CopiesTreeDiffStream, CopyRecords}; use crate::matchers::{EverythingMatcher, Matcher}; use crate::merge::{Merge, MergeBuilder, MergedTreeVal, MergedTreeValue}; use crate::repo_path::{RepoPath, RepoPathBuf, RepoPathComponent}; @@ -289,7 +289,7 @@ impl MergedTree { other: &MergedTree, matcher: &'a dyn Matcher, copy_records: &'a CopyRecords, - ) -> TreeDiffStream<'a> { + ) -> BoxStream<'a, CopiesTreeDiffEntry> { let stream = self.diff_stream(other, matcher); Box::pin(CopiesTreeDiffStream::new( stream,