@@ -19,6 +19,7 @@ use std::future::Future;
1919use std::path::{Path, PathBuf};
2020use std::str::FromStr;
2121use std::sync::Arc;
22+use std::time::SystemTime;
2223
2324use helix_core::{
2425 encoding,
@@ -135,6 +136,10 @@ pub struct Document {
135136
136137 pub savepoint: Option<Transaction>,
137138
139+ // Last time we wrote to the file. This will carry the time the file was last opened if there
140+ // were no saves.
141+ last_saved_time: SystemTime,
142+
138143 last_saved_revision: usize,
139144 version: i32, // should be usize?
140145 pub(crate) modified_since_accessed: bool,
@@ -160,6 +165,7 @@ impl fmt::Debug for Document {
160165 .field("changes", &self.changes)
161166 .field("old_state", &self.old_state)
162167 // .field("history", &self.history)
168+ .field("last_saved_time", &self.last_saved_time)
163169 .field("last_saved_revision", &self.last_saved_revision)
164170 .field("version", &self.version)
165171 .field("modified_since_accessed", &self.modified_since_accessed)
@@ -382,6 +388,7 @@ impl Document {
382388 version: 0,
383389 history: Cell::new(History::default()),
384390 savepoint: None,
391+ last_saved_time: SystemTime::now(),
385392 last_saved_revision: 0,
386393 modified_since_accessed: false,
387394 language_server: None,
@@ -577,9 +584,11 @@ impl Document {
577584
578585 let encoding = self.encoding;
579586
587+ let last_saved_time = self.last_saved_time;
588+
580589 // We encode the file according to the `Document`'s encoding.
581590 let future = async move {
582− use tokio::fs::File;
591+ use tokio::{fs, fs::File};
583592 if let Some(parent) = path.parent() {
584593 // TODO: display a prompt asking the user if the directories should be created
585594 if !parent.exists() {
@@ -591,6 +600,17 @@ impl Document {
591600 }
592601 }
593602
603+ // Protect against overwriting changes made externally
604+ if !force {
605+ if let Ok(metadata) = fs::metadata(&path).await {
606+ if let Ok(mtime) = metadata.modified() {
607+ if last_saved_time < mtime {
608+ bail!("file modified by an external process, use :w! to overwrite");
609+ }
610+ }
611+ }
612+ }
613+
594614 let mut file = File::create(&path).await?;
595615 to_writer(&mut file, encoding, &text).await?;
596616
@@ -668,6 +688,8 @@ impl Document {
668688 self.append_changes_to_history(view);
669689 self.reset_modified();
670690
691+ self.last_saved_time = SystemTime::now();
692+
671693 self.detect_indent_and_line_ending();
672694
673695 match provider_registry.get_diff_base(&path) {
@@ -1016,6 +1038,7 @@ impl Document {
10161038 rev
10171039 );
10181040 self.last_saved_revision = rev;
1041+ self.last_saved_time = SystemTime::now();
10191042 }
10201043
10211044 /// Get the document's latest saved revision.