fix: show revision-aware blame in diff buffers

Diff and snapshot sources were excluded before scheduling, and the separate diff renderer never painted attribution. Capture per-side Git provenance, preserve private object stores for historical tabs, and reuse the current-line worker and cache.
This commit is contained in:
Valdemar Lorenzen
2026-10-20 11:47:49 +02:00
parent 8f8d96ead9
commit 4fb1be7972
16 changed files with 819 additions and 91 deletions
+15 -4
View File
@@ -1952,6 +1952,7 @@ struct Buffer {
resolver_readonly: bool,
snapshot_document_path: Option<PathBuf>,
snapshot_root: Option<PathBuf>,
snapshot_blame: Option<Arc<crate::blame::RevisionSource>>,
lines: Vec<String>,
saved_lines: Vec<String>,
// Invalidate whenever text or the saved baseline changes, including temporary swaps.
@@ -2012,6 +2013,7 @@ impl Buffer {
resolver_readonly: false,
snapshot_document_path: None,
snapshot_root: None,
snapshot_blame: None,
saved_lines: lines.clone(),
dirty_cache: Cell::new(Some(false)),
disk_stamp,
@@ -2175,6 +2177,7 @@ pub(crate) struct BlameSource {
buffer: usize,
revision: u64,
pub(crate) path: Arc<Path>,
pub(crate) snapshot: Option<Arc<crate::blame::RevisionSource>>,
pub(crate) row: usize,
save_revision: u64,
disk_stamp: Option<FileStamp>,
@@ -5116,6 +5119,14 @@ impl Editor {
};
let source = comparison.root.join(relative);
let root = comparison.root.clone();
let blame = comparison.blame[side].as_ref().map(|baseline| {
Arc::new(crate::blame::RevisionSource {
store: baseline.store.clone(),
commit: baseline.commit.clone(),
keepalive: baseline.keepalive.clone(),
path: relative.clone(),
})
});
let lines = diff.snapshot_lines_at(file_index, focus);
let key = (
diff.comparison_id.expect("snapshot comparison"),
@@ -5155,6 +5166,7 @@ impl Editor {
buffer.path = Some(source);
buffer.snapshot_document_path = Some(document_path);
buffer.snapshot_root = Some(root);
buffer.snapshot_blame = blame;
buffer.lines = lines;
buffer.dirty_cache.set(None);
buffer
@@ -7156,8 +7168,7 @@ impl Editor {
pub(crate) fn blame_source(&self) -> Option<BlameSource> {
if !self.git_blame
|| self.should_quit()
|| self.diff.is_some()
|| self.active.diff_snapshot.is_some()
|| (self.active.diff_snapshot.is_some() && self.active.snapshot_blame.is_none())
|| self.active.reload_error.is_some()
{
return None;
@@ -7166,6 +7177,7 @@ impl Editor {
buffer: self.buffer_id(),
revision: self.text_revision(),
path: Arc::from(self.path()?),
snapshot: self.active.snapshot_blame.clone(),
row: self.cursor().row,
save_revision: self.active.save_revision,
disk_stamp: self.active.disk_stamp,
@@ -7177,13 +7189,12 @@ impl Editor {
pub(crate) fn blame_file_source_is_current(&self, source: &BlameSource) -> bool {
self.git_blame
&& !self.should_quit()
&& self.diff.is_none()
&& self.active.diff_snapshot.is_none()
&& self.active.reload_error.is_none()
&& source.buffer == self.buffer_id()
&& source.revision == self.text_revision()
&& source.save_revision == self.active.save_revision
&& source.disk_stamp == self.active.disk_stamp
&& source.snapshot == self.active.snapshot_blame
&& Some(source.path.as_ref()) == self.path()
}