@ -19,6 +19,7 @@ use std::future::Future;
use std ::path ::{ Path , PathBuf } ;
use std ::path ::{ Path , PathBuf } ;
use std ::str ::FromStr ;
use std ::str ::FromStr ;
use std ::sync ::Arc ;
use std ::sync ::Arc ;
use std ::time ::SystemTime ;
use helix_core ::{
use helix_core ::{
encoding ,
encoding ,
@ -135,6 +136,10 @@ pub struct Document {
pub savepoint : Option < Transaction > ,
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 ,
last_saved_revision : usize ,
version : i32 , // should be usize?
version : i32 , // should be usize?
pub ( crate ) modified_since_accessed : bool ,
pub ( crate ) modified_since_accessed : bool ,
@ -160,6 +165,7 @@ impl fmt::Debug for Document {
. field ( "changes" , & self . changes )
. field ( "changes" , & self . changes )
. field ( "old_state" , & self . old_state )
. field ( "old_state" , & self . old_state )
// .field("history", &self.history)
// .field("history", &self.history)
. field ( "last_saved_time" , & self . last_saved_time )
. field ( "last_saved_revision" , & self . last_saved_revision )
. field ( "last_saved_revision" , & self . last_saved_revision )
. field ( "version" , & self . version )
. field ( "version" , & self . version )
. field ( "modified_since_accessed" , & self . modified_since_accessed )
. field ( "modified_since_accessed" , & self . modified_since_accessed )
@ -382,6 +388,7 @@ impl Document {
version : 0 ,
version : 0 ,
history : Cell ::new ( History ::default ( ) ) ,
history : Cell ::new ( History ::default ( ) ) ,
savepoint : None ,
savepoint : None ,
last_saved_time : SystemTime ::now ( ) ,
last_saved_revision : 0 ,
last_saved_revision : 0 ,
modified_since_accessed : false ,
modified_since_accessed : false ,
language_server : None ,
language_server : None ,
@ -577,9 +584,11 @@ impl Document {
let encoding = self . encoding ;
let encoding = self . encoding ;
let last_saved_time = self . last_saved_time ;
// We encode the file according to the `Document`'s encoding.
// We encode the file according to the `Document`'s encoding.
let future = async move {
let future = async move {
use tokio ::fs ::File ;
use tokio ::{ fs , fs ::File } ;
if let Some ( parent ) = path . parent ( ) {
if let Some ( parent ) = path . parent ( ) {
// TODO: display a prompt asking the user if the directories should be created
// TODO: display a prompt asking the user if the directories should be created
if ! parent . exists ( ) {
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 ? ;
let mut file = File ::create ( & path ) . await ? ;
to_writer ( & mut file , encoding , & text ) . await ? ;
to_writer ( & mut file , encoding , & text ) . await ? ;
@ -668,6 +688,8 @@ impl Document {
self . append_changes_to_history ( view ) ;
self . append_changes_to_history ( view ) ;
self . reset_modified ( ) ;
self . reset_modified ( ) ;
self . last_saved_time = SystemTime ::now ( ) ;
self . detect_indent_and_line_ending ( ) ;
self . detect_indent_and_line_ending ( ) ;
match provider_registry . get_diff_base ( & path ) {
match provider_registry . get_diff_base ( & path ) {
@ -1016,6 +1038,7 @@ impl Document {
rev
rev
) ;
) ;
self . last_saved_revision = rev ;
self . last_saved_revision = rev ;
self . last_saved_time = SystemTime ::now ( ) ;
}
}
/// Get the document's latest saved revision.
/// Get the document's latest saved revision.