From eb9d7c8660d8ee110f8574d07dea870e0bfa453e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 21 Oct 2021 12:05:44 +0200 Subject: [PATCH] Update buffer's saved mtime when file is reloaded after on-disk change Co-Authored-By: Antonio Scandurra Co-Authored-By: Nathan Sobo --- crates/language/src/lib.rs | 71 +++++++++++----------------------- crates/project/src/worktree.rs | 36 ++++++----------- 2 files changed, 35 insertions(+), 72 deletions(-) diff --git a/crates/language/src/lib.rs b/crates/language/src/lib.rs index d364513084674de71d29036351aa7d0a5a8ecfe3..090ea8d9c8c7840e53815f0a991b93d28e990a39 100644 --- a/crates/language/src/lib.rs +++ b/crates/language/src/lib.rs @@ -300,45 +300,34 @@ impl Buffer { cx.emit(Event::Saved); } + pub fn file_renamed(&self, cx: &mut ModelContext) { + cx.emit(Event::FileHandleChanged); + } + pub fn file_updated( &mut self, - path: Arc, - mtime: SystemTime, - new_text: Option, + new_text: String, cx: &mut ModelContext, - ) { - let file = self.file.as_mut().unwrap(); - let mut changed = false; - if path != *file.path() { - file.set_path(path); - changed = true; - } - - if mtime != file.mtime() { - file.set_mtime(mtime); - changed = true; - if let Some(new_text) = new_text { - if self.version == self.saved_version { - cx.spawn(|this, mut cx| async move { - let diff = this - .read_with(&cx, |this, cx| this.diff(new_text.into(), cx)) - .await; - this.update(&mut cx, |this, cx| { - if this.apply_diff(diff, cx) { - this.saved_version = this.version.clone(); - this.saved_mtime = mtime; - cx.emit(Event::Reloaded); - } - }); - }) - .detach(); - } - } - } - - if changed { + ) -> Option> { + if let Some(file) = self.file.as_ref() { cx.emit(Event::FileHandleChanged); + let mtime = file.mtime(); + if self.version == self.saved_version { + return Some(cx.spawn(|this, mut cx| async move { + let diff = this + .read_with(&cx, |this, cx| this.diff(new_text.into(), cx)) + .await; + this.update(&mut cx, |this, cx| { + if this.apply_diff(diff, cx) { + this.saved_version = this.version.clone(); + this.saved_mtime = mtime; + cx.emit(Event::Reloaded); + } + }); + })); + } } + None } pub fn file_deleted(&mut self, cx: &mut ModelContext) { @@ -740,20 +729,6 @@ impl Buffer { }) } - pub fn set_text_from_disk(&self, new_text: Arc, cx: &mut ModelContext) -> Task<()> { - cx.spawn(|this, mut cx| async move { - let diff = this - .read_with(&cx, |this, cx| this.diff(new_text, cx)) - .await; - - this.update(&mut cx, |this, cx| { - if this.apply_diff(diff, cx) { - this.saved_version = this.version.clone(); - } - }); - }) - } - fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext) -> bool { if self.version == diff.base_version { self.start_transaction(None).unwrap(); diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 6912f66120c57fbd503d8af59fbf2b6bdf7d2ba5..72bb9c405b1940c1c539cf69ea7ecb1644925fed 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -594,20 +594,12 @@ impl Worktree { let buffer_is_clean = !buffer.is_dirty(); if let Some(file) = buffer.file_mut() { - let mut file_changed = false; - if let Some(entry) = file .entry_id() .and_then(|entry_id| self.entry_for_id(entry_id)) { - if entry.path != *file.path() { - file.set_path(entry.path.clone()); - file_changed = true; - } - if entry.mtime != file.mtime() { file.set_mtime(entry.mtime); - file_changed = true; if let Some(worktree) = self.as_local() { if buffer_is_clean { let abs_path = worktree.absolutize(file.path().as_ref()); @@ -615,6 +607,11 @@ impl Worktree { } } } + + if entry.path != *file.path() { + file.set_path(entry.path.clone()); + buffer.file_renamed(cx); + } } else if let Some(entry) = self.entry_for_path(file.path().as_ref()) { file.set_entry_id(Some(entry.id)); file.set_mtime(entry.mtime); @@ -624,17 +621,9 @@ impl Worktree { refresh_buffer(abs_path, &worktree.fs, cx); } } - file_changed = true; } else if !file.is_deleted() { - if buffer_is_clean { - cx.emit(language::Event::Dirtied); - } file.set_entry_id(None); - file_changed = true; - } - - if file_changed { - cx.emit(language::Event::FileHandleChanged); + buffer.file_deleted(cx); } } }); @@ -1186,15 +1175,14 @@ fn build_gitignore(abs_path: &Path, fs: &dyn Fs) -> Result { pub fn refresh_buffer(abs_path: PathBuf, fs: &Arc, cx: &mut ModelContext) { let fs = fs.clone(); cx.spawn(|buffer, mut cx| async move { - let new_text = fs.load(&abs_path).await; - match new_text { + match fs.load(&abs_path).await { Err(error) => log::error!("error refreshing buffer after file changed: {}", error), Ok(new_text) => { - buffer - .update(&mut cx, |buffer, cx| { - buffer.set_text_from_disk(new_text.into(), cx) - }) - .await; + if let Some(task) = + buffer.update(&mut cx, |buffer, cx| buffer.file_updated(new_text, cx)) + { + task.await; + } } } })