From 58b963f7f3d9d8e869408666608c05f3c69a5cb5 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Mon, 12 Apr 2010 21:47:40 -0400 Subject: [PATCH] Try to detect file modification within the same second. * buffer.h (struct buffer): New field modtime_size. * buffer.c (reset_buffer): Initialize it. * fileio.c (Finsert_file_contents, Fwrite_region): Set it. (Fverify_visited_file_modtime): Check it. (Fclear_visited_file_modtime, Fset_visited_file_modtime): Clear it. (Fset_visited_file_modtime): Set (or clear) it. --- src/ChangeLog | 10 ++++++++++ src/buffer.c | 1 + src/buffer.h | 6 ++++++ src/fileio.c | 29 +++++++++++++++++++++-------- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 2c768be4821..ad88dc8311b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2010-04-13 Stefan Monnier + + Try to detect file modification within the same second. + * buffer.h (struct buffer): New field modtime_size. + * buffer.c (reset_buffer): Initialize it. + * fileio.c (Finsert_file_contents, Fwrite_region): Set it. + (Fverify_visited_file_modtime): Check it. + (Fclear_visited_file_modtime, Fset_visited_file_modtime): Clear it. + (Fset_visited_file_modtime): Set (or clear) it. + 2010-04-12 Stefan Monnier * process.c (status_notify): Remove unused var `ro'. diff --git a/src/buffer.c b/src/buffer.c index 9035a986b4c..0759ce1c43c 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -693,6 +693,7 @@ reset_buffer (b) b->file_truename = Qnil; b->directory = (current_buffer) ? current_buffer->directory : Qnil; b->modtime = 0; + b->modtime_size = -1; XSETFASTINT (b->save_length, 0); b->last_window_start = 1; /* It is more conservative to start out "changed" than "unchanged". */ diff --git a/src/buffer.h b/src/buffer.h index 40f03daca90..fa3fc6dafb8 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -513,6 +513,12 @@ struct buffer 0 means visited file modtime unknown; in no case complain about any mismatch on next save attempt. */ int modtime; + /* Size of the file when modtime was set. This is used to detect the + case where the file grew while we were reading it, so the modtime + is still the same (since it's rounded up to seconds) but we're actually + not up-to-date. -1 means the size is unknown. Only meaningful if + modtime is actually set. */ + EMACS_INT modtime_size; /* The value of text->modiff at the last auto-save. */ int auto_save_modified; /* The value of text->modiff at the last display error. diff --git a/src/fileio.c b/src/fileio.c index c62d5724eff..e9440adabe0 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -4092,6 +4092,7 @@ variable `last-coding-system-used' to the coding system actually used. */) if (NILP (handler)) { current_buffer->modtime = st.st_mtime; + current_buffer->modtime_size = st.st_size; current_buffer->filename = orig_filename; } @@ -4695,7 +4696,10 @@ This calls `write-region-annotate-functions' at the start, and to avoid a "file has changed on disk" warning on next attempt to save. */ if (visiting) - current_buffer->modtime = st.st_mtime; + { + current_buffer->modtime = st.st_mtime; + current_buffer->modtime_size = st.st_size; + } if (failure) error ("IO error writing %s: %s", SDATA (filename), @@ -5004,11 +5008,13 @@ See Info node `(elisp)Modification Time' for more details. */) else st.st_mtime = 0; } - if (st.st_mtime == b->modtime - /* If both are positive, accept them if they are off by one second. */ - || (st.st_mtime > 0 && b->modtime > 0 - && (st.st_mtime == b->modtime + 1 - || st.st_mtime == b->modtime - 1))) + if ((st.st_mtime == b->modtime + /* If both are positive, accept them if they are off by one second. */ + || (st.st_mtime > 0 && b->modtime > 0 + && (st.st_mtime == b->modtime + 1 + || st.st_mtime == b->modtime - 1))) + && (st.st_size == b->modtime_size + || b->modtime_size < 0)) return Qt; return Qnil; } @@ -5020,6 +5026,7 @@ Next attempt to save will certainly not complain of a discrepancy. */) () { current_buffer->modtime = 0; + current_buffer->modtime_size = -1; return Qnil; } @@ -5049,7 +5056,10 @@ An argument specifies the modification time value to use Lisp_Object time_list; { if (!NILP (time_list)) - current_buffer->modtime = cons_to_long (time_list); + { + current_buffer->modtime = cons_to_long (time_list); + current_buffer->modtime_size = -1; + } else { register Lisp_Object filename; @@ -5068,7 +5078,10 @@ An argument specifies the modification time value to use filename = ENCODE_FILE (filename); if (stat (SDATA (filename), &st) >= 0) - current_buffer->modtime = st.st_mtime; + { + current_buffer->modtime = st.st_mtime; + current_buffer->modtime_size = st.st_size; + } } return Qnil; -- 2.39.5