perf: cache file attribution for instant blame navigation
This commit is contained in:
+51
-11
@@ -1561,13 +1561,19 @@ impl Buffer {
|
||||
}
|
||||
|
||||
fn refresh_file(&mut self) -> io::Result<bool> {
|
||||
if self.diff_snapshot.is_some() || self.dirty() {
|
||||
if self.diff_snapshot.is_some() {
|
||||
return Ok(false);
|
||||
}
|
||||
let Some(path) = &self.path else {
|
||||
return Ok(false);
|
||||
};
|
||||
let stamp = FileStamp::read(path)?;
|
||||
if self.dirty() {
|
||||
if stamp.is_none() && self.disk_stamp.is_some() {
|
||||
return Err(io::Error::new(io::ErrorKind::NotFound, "File was removed"));
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
if stamp == self.disk_stamp {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -1670,8 +1676,10 @@ struct PendingLspNavigation {
|
||||
pub(crate) struct BlameSource {
|
||||
buffer: usize,
|
||||
revision: u64,
|
||||
pub(crate) path: PathBuf,
|
||||
pub(crate) path: Arc<Path>,
|
||||
pub(crate) row: usize,
|
||||
save_revision: u64,
|
||||
disk_stamp: Option<FileStamp>,
|
||||
pane: usize,
|
||||
tab: usize,
|
||||
}
|
||||
@@ -1712,7 +1720,7 @@ pub struct Editor {
|
||||
battery_charge: Option<u8>,
|
||||
battery_label: String,
|
||||
git_blame: bool,
|
||||
line_blame: Option<(BlameSource, String)>,
|
||||
line_blame: Option<(BlameSource, Arc<crate::blame::LineBlame>, String)>,
|
||||
lsp_names: Vec<String>,
|
||||
lsp_label: String,
|
||||
quit: bool,
|
||||
@@ -4682,27 +4690,37 @@ impl Editor {
|
||||
|| self.should_quit()
|
||||
|| self.diff.is_some()
|
||||
|| self.active.diff_snapshot.is_some()
|
||||
|| self.active.reload_error.is_some()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
Some(BlameSource {
|
||||
buffer: self.buffer_id(),
|
||||
revision: self.text_revision(),
|
||||
path: self.path()?.to_owned(),
|
||||
path: Arc::from(self.path()?),
|
||||
row: self.cursor().row,
|
||||
save_revision: self.active.save_revision,
|
||||
disk_stamp: self.active.disk_stamp,
|
||||
pane: self.pane_id(),
|
||||
tab: self.tab_id(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn blame_source_is_current(&self, source: &BlameSource) -> bool {
|
||||
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()
|
||||
&& Some(source.path.as_path()) == self.path()
|
||||
&& source.save_revision == self.active.save_revision
|
||||
&& source.disk_stamp == self.active.disk_stamp
|
||||
&& Some(source.path.as_ref()) == self.path()
|
||||
}
|
||||
|
||||
pub(crate) fn blame_source_is_current(&self, source: &BlameSource) -> bool {
|
||||
self.blame_file_source_is_current(source)
|
||||
&& source.row == self.cursor().row
|
||||
&& source.pane == self.pane_id()
|
||||
&& source.tab == self.tab_id()
|
||||
@@ -4712,14 +4730,32 @@ impl Editor {
|
||||
self.line_blame.take().is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn set_cached_line_blame(
|
||||
&mut self,
|
||||
source: &BlameSource,
|
||||
blame: Arc<crate::blame::LineBlame>,
|
||||
) -> bool {
|
||||
let mut source = source.clone();
|
||||
source.row = self.cursor().row;
|
||||
source.pane = self.pane_id();
|
||||
source.tab = self.tab_id();
|
||||
self.set_line_blame(source, blame)
|
||||
}
|
||||
|
||||
pub(crate) fn set_line_blame(
|
||||
&mut self,
|
||||
source: BlameSource,
|
||||
blame: crate::blame::LineBlame,
|
||||
blame: Arc<crate::blame::LineBlame>,
|
||||
) -> bool {
|
||||
if !self.blame_source_is_current(&source) {
|
||||
return false;
|
||||
}
|
||||
if let Some((previous, metadata, _)) = &mut self.line_blame
|
||||
&& Arc::ptr_eq(metadata, &blame)
|
||||
{
|
||||
*previous = source;
|
||||
return false;
|
||||
}
|
||||
let label = if blame.uncommitted {
|
||||
"Uncommitted".to_owned()
|
||||
} else {
|
||||
@@ -4728,15 +4764,19 @@ impl Editor {
|
||||
blame.author, blame.summary, blame.commit
|
||||
))
|
||||
};
|
||||
self.line_blame = Some((source, label));
|
||||
true
|
||||
let changed = self
|
||||
.line_blame
|
||||
.as_ref()
|
||||
.is_none_or(|(_, _, previous)| previous != &label);
|
||||
self.line_blame = Some((source, blame, label));
|
||||
changed
|
||||
}
|
||||
|
||||
pub(crate) fn line_blame(&self) -> Option<&str> {
|
||||
self.line_blame
|
||||
.as_ref()
|
||||
.filter(|(source, _)| self.blame_source_is_current(source))
|
||||
.map(|(_, label)| label.as_str())
|
||||
.filter(|(source, _, _)| self.blame_source_is_current(source))
|
||||
.map(|(_, _, label)| label.as_str())
|
||||
}
|
||||
pub fn lsp_names(&self) -> &[String] {
|
||||
&self.lsp_names
|
||||
|
||||
Reference in New Issue
Block a user