on master help sign in
fix: buffer-close ensuring writes

Make sure buffer-close waits for the document to finish its writes.

commita5a93182cd5ccf88bc95b68044aa05d746ded35e authorSkyler Hawthorne <skyler@dead10ck.com> dateSat 23 Apr 2022, 18:38 (5 years ago) parentd706194
5 files changed+63−12
helix-term/src/application.rs+2 helix-term/src/commands/typed.rs+1 helix-term/tests/test/commands.rs−1 helix-view/src/document.rs+55−11 helix-view/src/editor.rs+5
helix-term/src/application.rs+2
@@ -310,6 +310,8 @@ impl Application {
310310 self.render();
311311 }
312312 event = self.editor.wait_event() => {
313+ log::debug!("received editor event: {:?}", event);
314+
313315 match event {
314316 EditorEvent::DocumentSave(event) => {
315317 self.handle_document_write(event);
helix-term/src/commands/typed.rs+1
@@ -151,6 +151,7 @@ fn buffer_close(
151151 }
152152
153153 let document_ids = buffer_gather_paths_impl(cx.editor, args);
154+ log::debug!("closing buffers: {:?}", document_ids);
154155 buffer_close_by_ids_impl(cx.editor, &document_ids, false)
155156}
156157
helix-term/tests/test/commands.rs−1
@@ -26,7 +26,6 @@ async fn test_write_quit_fail() -> anyhow::Result<()> {
2626}
2727
2828#[tokio::test]
29−#[ignore]
3029async fn test_buffer_close_concurrent() -> anyhow::Result<()> {
3130 test_key_sequences(
3231 &mut Application::new(Args::default(), Config::default())?,
helix-view/src/document.rs+55−11
@@ -616,6 +616,10 @@ impl Document {
616616 }
617617
618618 pub async fn await_save(&mut self) -> Option<DocumentSaveEventResult> {
619+ self.await_save_impl(true).await
620+ }
621+
622+ async fn await_save_impl(&mut self, block: bool) -> Option<DocumentSaveEventResult> {
619623 let mut current_save = self.current_save.lock().await;
620624 if let Some(ref mut save) = *current_save {
621625 let result = save.await;
@@ -627,7 +631,15 @@ impl Document {
627631 // return early if the receiver is closed
628632 self.save_receiver.as_ref()?;
629633
630− let save = match self.save_receiver.as_mut().unwrap().recv().await {
634+ let rx = self.save_receiver.as_mut().unwrap();
635+
636+ let save_req = if block {
637+ rx.recv().await
638+ } else {
639+ rx.try_recv().ok()
640+ };
641+
642+ let save = match save_req {
631643 Some(save) => save,
632644 None => {
633645 self.save_receiver = None;
@@ -648,19 +660,24 @@ impl Document {
648660 Some(result)
649661 }
650662
651− /// Prepares the Document for being closed by stopping any new writes
652− /// and flushing through the queue of pending writes. If any fail,
653− /// it stops early before emptying the rest of the queue. Callers
654− /// should keep calling until it returns None.
655− pub async fn close(&mut self) -> Option<DocumentSaveEventResult> {
656− if self.save_sender.is_some() {
657− self.save_sender = None;
658− }
663+ /// Flushes the queue of pending writes. If any fail,
664+ /// it stops early before emptying the rest of the queue.
665+ pub async fn try_flush_saves(&mut self) -> Option<DocumentSaveEventResult> {
666+ self.flush_saves_impl(false).await
667+ }
659668
669+ async fn flush_saves_impl(&mut self, block: bool) -> Option<DocumentSaveEventResult> {
660670 let mut final_result = None;
661671
662− while let Some(save_event) = self.await_save().await {
663− let is_err = save_event.is_err();
672+ while let Some(save_event) = self.await_save_impl(block).await {
673+ let is_err = match &save_event {
674+ Ok(event) => {
675+ self.set_last_saved_revision(event.revision);
676+ false
677+ }
678+ Err(_) => true,
679+ };
680+
664681 final_result = Some(save_event);
665682
666683 if is_err {
@@ -671,6 +688,17 @@ impl Document {
671688 final_result
672689 }
673690
691+ /// Prepares the Document for being closed by stopping any new writes
692+ /// and flushing through the queue of pending writes. If any fail,
693+ /// it stops early before emptying the rest of the queue.
694+ pub async fn close(&mut self) -> Option<DocumentSaveEventResult> {
695+ if self.save_sender.is_some() {
696+ self.save_sender = None;
697+ }
698+
699+ self.flush_saves_impl(true).await
700+ }
701+
674702 /// Detect the programming language based on the file type.
675703 pub fn detect_language(&mut self, config_loader: Arc<syntax::Loader>) {
676704 if let Some(path) = &self.path {
@@ -1023,6 +1051,11 @@ impl Document {
10231051 let history = self.history.take();
10241052 let current_revision = history.current_revision();
10251053 self.history.set(history);
1054+ log::debug!(
1055+ "modified - last saved: {}, current: {}",
1056+ self.last_saved_revision,
1057+ current_revision
1058+ );
10261059 current_revision != self.last_saved_revision || !self.changes.is_empty()
10271060 }
10281061
@@ -1036,9 +1069,20 @@ impl Document {
10361069
10371070 /// Set the document's latest saved revision to the given one.
10381071 pub fn set_last_saved_revision(&mut self, rev: usize) {
1072+ log::debug!(
1073+ "doc {} revision updated {} -> {}",
1074+ self.id,
1075+ self.last_saved_revision,
1076+ rev
1077+ );
10391078 self.last_saved_revision = rev;
10401079 }
10411080
1081+ /// Get the document's latest saved revision.
1082+ pub fn get_last_saved_revision(&mut self) -> usize {
1083+ self.last_saved_revision
1084+ }
1085+
10421086 /// Get the current revision number
10431087 pub fn get_current_revision(&mut self) -> usize {
10441088 let history = self.history.take();
helix-view/src/editor.rs+5
@@ -1101,6 +1101,11 @@ impl Editor {
11011101 None => return Err(CloseError::DoesNotExist),
11021102 };
11031103
1104+ // flush out any pending writes first to clear the modified status
1105+ if let Some(save_result) = doc.try_flush_saves().await {
1106+ save_result?;
1107+ }
1108+
11041109 if !force && doc.is_modified() {
11051110 return Err(CloseError::BufferModified(doc.display_name().into_owned()));
11061111 }