aboutsummaryrefslogtreecommitdiff
path: root/helix-view/src
diff options
context:
space:
mode:
authorClément Delafargue2023-02-08 16:09:19 +0000
committerGitHub2023-02-08 16:09:19 +0000
commitf386ff795d4833cce02d57de921999284aadded3 (patch)
tree363078f7197e71ffc1aeedc27919e1076957a4f1 /helix-view/src
parent00ecc556a8d3f7efe115f3d826c916ffacf6ab2e (diff)
Check for external file modifications when writing (#5805)
`:write` and other file-saving commands now check the file modification time before writing to protect against overwriting external changes. Co-authored-by: Gustavo Noronha Silva <gustavo@noronha.dev.br> Co-authored-by: LeoniePhiline <22329650+LeoniePhiline@users.noreply.github.com> Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
Diffstat (limited to 'helix-view/src')
-rw-r--r--helix-view/src/document.rs25
1 files changed, 24 insertions, 1 deletions
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index 798b5400..d308d013 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -19,6 +19,7 @@ use std::future::Future;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::Arc;
+use std::time::SystemTime;
use helix_core::{
encoding,
@@ -135,6 +136,10 @@ pub struct Document {
pub savepoint: Option<Transaction>,
+ // Last time we wrote to the file. This will carry the time the file was last opened if there
+ // were no saves.
+ last_saved_time: SystemTime,
+
last_saved_revision: usize,
version: i32, // should be usize?
pub(crate) modified_since_accessed: bool,
@@ -160,6 +165,7 @@ impl fmt::Debug for Document {
.field("changes", &self.changes)
.field("old_state", &self.old_state)
// .field("history", &self.history)
+ .field("last_saved_time", &self.last_saved_time)
.field("last_saved_revision", &self.last_saved_revision)
.field("version", &self.version)
.field("modified_since_accessed", &self.modified_since_accessed)
@@ -382,6 +388,7 @@ impl Document {
version: 0,
history: Cell::new(History::default()),
savepoint: None,
+ last_saved_time: SystemTime::now(),
last_saved_revision: 0,
modified_since_accessed: false,
language_server: None,
@@ -577,9 +584,11 @@ impl Document {
let encoding = self.encoding;
+ let last_saved_time = self.last_saved_time;
+
// We encode the file according to the `Document`'s encoding.
let future = async move {
- use tokio::fs::File;
+ use tokio::{fs, fs::File};
if let Some(parent) = path.parent() {
// TODO: display a prompt asking the user if the directories should be created
if !parent.exists() {
@@ -591,6 +600,17 @@ impl Document {
}
}
+ // Protect against overwriting changes made externally
+ if !force {
+ if let Ok(metadata) = fs::metadata(&path).await {
+ if let Ok(mtime) = metadata.modified() {
+ if last_saved_time < mtime {
+ bail!("file modified by an external process, use :w! to overwrite");
+ }
+ }
+ }
+ }
+
let mut file = File::create(&path).await?;
to_writer(&mut file, encoding, &text).await?;
@@ -668,6 +688,8 @@ impl Document {
self.append_changes_to_history(view);
self.reset_modified();
+ self.last_saved_time = SystemTime::now();
+
self.detect_indent_and_line_ending();
match provider_registry.get_diff_base(&path) {
@@ -1016,6 +1038,7 @@ impl Document {
rev
);
self.last_saved_revision = rev;
+ self.last_saved_time = SystemTime::now();
}
/// Get the document's latest saved revision.