fix: retain repository status between picker openings
This commit is contained in:
+87
-28
@@ -376,7 +376,7 @@ pub struct EditorSession {
|
||||
gutter_request_id: u64,
|
||||
gutter_pending: bool,
|
||||
last_gutter_refresh: Option<Instant>,
|
||||
picker_source: Option<(usize, PathBuf)>,
|
||||
picker_source: Option<PathBuf>,
|
||||
battery: Option<crate::battery::Battery>,
|
||||
battery_enabled: bool,
|
||||
last_file_refresh: Instant,
|
||||
@@ -1275,15 +1275,8 @@ impl EditorSession {
|
||||
|
||||
fn poll_gutter_at(&mut self, now: Instant) -> bool {
|
||||
let line_gutter = self.editor.gutter_style() != crate::gutter::GutterStyle::None;
|
||||
let picker_changed = match (self.editor.normal_file_picker(), &self.picker_source) {
|
||||
(Some(picker), Some((tab, root))) => {
|
||||
*tab != self.editor.tab_id() || *root != picker.root
|
||||
}
|
||||
(None, None) => false,
|
||||
_ => true,
|
||||
};
|
||||
if self.editor.should_quit() || (!line_gutter && self.editor.normal_file_picker().is_none())
|
||||
{
|
||||
let picker_changed = self.picker_source.as_deref() != Some(self.editor.project_root());
|
||||
if self.editor.should_quit() {
|
||||
self.gutter_worker = None;
|
||||
self.gutter_sources.clear();
|
||||
self.gutter_pending = false;
|
||||
@@ -1320,10 +1313,7 @@ impl EditorSession {
|
||||
.is_none_or(|last| now.saturating_duration_since(last) >= Duration::from_secs(1));
|
||||
if sources_changed || picker_changed || refresh_due {
|
||||
if picker_changed {
|
||||
self.picker_source = self
|
||||
.editor
|
||||
.normal_file_picker()
|
||||
.map(|picker| (self.editor.tab_id(), picker.root.clone()));
|
||||
self.picker_source = Some(self.editor.project_root().to_owned());
|
||||
}
|
||||
if sources_changed {
|
||||
self.gutter_sources = self
|
||||
@@ -1357,11 +1347,6 @@ impl EditorSession {
|
||||
}
|
||||
self.gutter_request_id = self.gutter_request_id.wrapping_add(1);
|
||||
self.last_gutter_refresh = Some(now);
|
||||
if self.gutter_sources.is_empty() && self.picker_source.is_none() {
|
||||
self.gutter_worker = None;
|
||||
self.gutter_pending = false;
|
||||
return false;
|
||||
}
|
||||
if self.gutter_worker.is_none() {
|
||||
match crate::gutter::Worker::start() {
|
||||
Ok(worker) => self.gutter_worker = Some(worker),
|
||||
@@ -1383,7 +1368,7 @@ impl EditorSession {
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let picker = self.picker_source.as_ref().map(|(_, root)| {
|
||||
let picker = self.picker_source.as_ref().map(|root| {
|
||||
let buffers = self
|
||||
.gutter_sources
|
||||
.iter()
|
||||
@@ -1451,20 +1436,15 @@ impl EditorSession {
|
||||
}
|
||||
|
||||
fn apply_picker_result(&mut self, id: u64, reply: crate::gutter::PickerChanges) -> bool {
|
||||
let Some((tab, root)) = &self.picker_source else {
|
||||
let Some(root) = &self.picker_source else {
|
||||
return false;
|
||||
};
|
||||
if id != self.gutter_request_id
|
||||
|| *tab != self.editor.tab_id()
|
||||
|| *root != reply.root
|
||||
|| self
|
||||
.editor
|
||||
.normal_file_picker()
|
||||
.is_none_or(|picker| picker.root != *root)
|
||||
|| *root != self.editor.project_root()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let tab = *tab;
|
||||
let mut changed = false;
|
||||
let changes = match reply.result {
|
||||
Ok(changes) => changes,
|
||||
@@ -1477,7 +1457,7 @@ impl EditorSession {
|
||||
changed
|
||||
| self
|
||||
.editor
|
||||
.set_picker_repository_changes(tab, &reply.root, changes)
|
||||
.set_picker_repository_changes(&reply.root, changes)
|
||||
}
|
||||
|
||||
pub(crate) fn refresh_gutter(&mut self) -> bool {
|
||||
@@ -1816,6 +1796,16 @@ mod tests {
|
||||
session.handle(Input::Char(' '));
|
||||
session.handle(Input::Char('o'));
|
||||
};
|
||||
let status = |session: &EditorSession| {
|
||||
session
|
||||
.editor
|
||||
.normal_file_picker()
|
||||
.unwrap()
|
||||
.entries()
|
||||
.find(|row| row.path == Path::new("buffer.txt"))
|
||||
.unwrap()
|
||||
.status
|
||||
};
|
||||
let ready = |session: &mut EditorSession, clock: Instant, expected| {
|
||||
let deadline = Instant::now() + Duration::from_secs(10);
|
||||
loop {
|
||||
@@ -1845,16 +1835,56 @@ mod tests {
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
};
|
||||
let settle = |session: &mut EditorSession| {
|
||||
let deadline = Instant::now() + Duration::from_secs(10);
|
||||
loop {
|
||||
session.poll_gutter_at(now);
|
||||
if !session.gutter_pending {
|
||||
break;
|
||||
}
|
||||
assert!(
|
||||
Instant::now() < deadline,
|
||||
"background file status did not settle"
|
||||
);
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
};
|
||||
settle(&mut session);
|
||||
open(&mut session);
|
||||
assert_eq!(
|
||||
status(&session),
|
||||
Some(FileStatus::Modified),
|
||||
"first open must reuse status loaded while the picker was closed",
|
||||
);
|
||||
ready(&mut session, now, Some(FileStatus::Modified));
|
||||
session.handle(Input::Ctrl('w'));
|
||||
settle(&mut session);
|
||||
open(&mut session);
|
||||
assert_eq!(
|
||||
status(&session),
|
||||
Some(FileStatus::Modified),
|
||||
"reopening must retain completed status",
|
||||
);
|
||||
let request = session.gutter_request_id;
|
||||
session.poll_gutter_at(now);
|
||||
assert_eq!(
|
||||
session.gutter_request_id, request,
|
||||
"opening must not restart status work"
|
||||
);
|
||||
session.handle(Input::Ctrl('w'));
|
||||
session.poll_gutter_at(now);
|
||||
session
|
||||
.editor
|
||||
.apply(vec![Effect::Replace("base\n".into())])
|
||||
.unwrap();
|
||||
assert!(session.editor.dirty());
|
||||
settle(&mut session);
|
||||
open(&mut session);
|
||||
assert_eq!(
|
||||
status(&session),
|
||||
None,
|
||||
"closed-picker edits must refresh the cache"
|
||||
);
|
||||
ready(&mut session, now, None);
|
||||
assert_eq!(
|
||||
fs::read_to_string(fixture.0.join("buffer.txt")).unwrap(),
|
||||
@@ -1863,11 +1893,40 @@ mod tests {
|
||||
session.handle(Input::Ctrl('w'));
|
||||
session.poll_gutter_at(now);
|
||||
session.handle(Input::Char('u'));
|
||||
settle(&mut session);
|
||||
open(&mut session);
|
||||
assert_eq!(status(&session), Some(FileStatus::Modified));
|
||||
ready(&mut session, now, Some(FileStatus::Modified));
|
||||
git(&["add", "buffer.txt"]);
|
||||
git(&["commit", "-qm", "new baseline"]);
|
||||
ready(&mut session, now + Duration::from_secs(1), None);
|
||||
assert!(!session.apply_picker_result(
|
||||
session.gutter_request_id.wrapping_sub(1),
|
||||
crate::gutter::PickerChanges {
|
||||
root: fixture.0.clone(),
|
||||
result: Ok(Vec::new()),
|
||||
},
|
||||
));
|
||||
assert!(!session.apply_picker_result(
|
||||
session.gutter_request_id,
|
||||
crate::gutter::PickerChanges {
|
||||
root: fixture.0.join("elsewhere"),
|
||||
result: Ok(Vec::new()),
|
||||
},
|
||||
));
|
||||
session.handle(Input::Ctrl('w'));
|
||||
session.execute("tab.new");
|
||||
open(&mut session);
|
||||
assert_eq!(status(&session), None);
|
||||
assert!(
|
||||
session
|
||||
.editor
|
||||
.normal_file_picker()
|
||||
.unwrap()
|
||||
.entries()
|
||||
.any(|row| row.path == Path::new("added.txt")
|
||||
&& row.status == Some(FileStatus::Added))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user