feat: track checkout identity for pinned diff editability

This commit is contained in:
2026-10-13 17:04:15 +02:00
parent e3e087f16f
commit 99fa5a2aff
14 changed files with 705 additions and 170 deletions
+27 -30
View File
@@ -84,12 +84,13 @@ impl DiffWorker {
} => repository
.compare(id, &before, &after, mode, &buffers)
.map(DiffOutcome::Comparison),
DiffOperation::RefreshWorking {
DiffOperation::RefreshCheckout {
comparison_id,
follow_working,
buffers,
} => repository
.refresh_working_after(comparison_id, id, &buffers)
.map(DiffOutcome::WorkingRefresh),
.refresh_checkout(comparison_id, id, follow_working, &buffers)
.map(DiffOutcome::CheckoutRefresh),
DiffOperation::LoadFile {
comparison_id,
file_index,
@@ -1151,14 +1152,13 @@ impl EditorSession {
self.editor.refresh_files()
}
fn refresh_working_diffs_at(&mut self, now: Instant) {
if !self.diff_follow_working_copy
|| now.saturating_duration_since(self.last_diff_refresh) < Duration::from_secs(1)
{
fn refresh_checkout_diffs_at(&mut self, now: Instant) {
if now.saturating_duration_since(self.last_diff_refresh) < Duration::from_secs(1) {
return;
}
self.last_diff_refresh = now;
self.editor.queue_working_refreshes();
self.editor
.queue_checkout_refreshes(self.diff_follow_working_copy);
}
/// Drains ready plugin work without waiting for command or server responses.
@@ -1170,7 +1170,7 @@ impl EditorSession {
let mut changed = self.refresh_files_at(now);
changed |= self.synchronize_documents();
changed |= self.poll_battery();
self.refresh_working_diffs_at(now);
self.refresh_checkout_diffs_at(now);
changed |= self.poll_diff();
for update in self.lsp.poll() {
match self.apply_update("core", update) {
@@ -1234,7 +1234,7 @@ mod tests {
};
#[test]
fn working_diff_polling_uses_injected_interval_and_never_queues_historical_or_disabled_views() {
fn checkout_diff_polling_uses_injected_interval_independently_of_endpoint_following() {
use crate::diff::{Catalog, Category, Comparison, RepoKind, Revision, RevisionTarget};
let fixture = Fixture::new();
fixture.file("buffer.txt", "base");
@@ -1279,27 +1279,24 @@ mod tests {
})),
);
let now = session.last_diff_refresh;
session.diff_follow_working_copy = false;
session.refresh_working_diffs_at(now + Duration::from_secs(1));
assert!(session.editor.take_next_diff_request().is_none());
session.diff_follow_working_copy = true;
session.refresh_working_diffs_at(now + Duration::from_millis(999));
assert!(session.editor.take_next_diff_request().is_none());
session.refresh_working_diffs_at(now + Duration::from_secs(1));
let request = session.editor.take_next_diff_request();
assert_eq!(request.is_some(), working);
if let Some((_, refresh, operation)) = request {
assert!(
matches!(operation, DiffOperation::RefreshWorking { comparison_id, .. }
if comparison_id == id)
);
session.refresh_working_diffs_at(now + Duration::from_secs(2));
for (tick, follow) in [(1, false), (2, true)] {
session.diff_follow_working_copy = follow;
session.refresh_checkout_diffs_at(now + Duration::from_millis(tick * 1000 - 1));
assert!(session.editor.take_next_diff_request().is_none());
assert!(
!session
.editor
.apply_diff_result(refresh, Ok(DiffOutcome::WorkingRefresh(None)))
);
session.refresh_checkout_diffs_at(now + Duration::from_secs(tick));
let request = session.editor.take_next_diff_request();
assert_eq!(request.is_some(), !working || follow);
if let Some((_, refresh, operation)) = request {
assert!(
matches!(operation, DiffOperation::RefreshCheckout { comparison_id, follow_working, .. }
if comparison_id == id && follow_working == follow)
);
assert!(
!session
.editor
.apply_diff_result(refresh, Ok(DiffOutcome::CheckoutRefresh(None)))
);
}
}
}
}