Try to detect file modification within the same second.
authorStefan Monnier <monnier@iro.umontreal.ca>
Tue, 13 Apr 2010 01:47:40 +0000 (21:47 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Tue, 13 Apr 2010 01:47:40 +0000 (21:47 -0400)
* 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
src/buffer.c
src/buffer.h
src/fileio.c

index 2c768be..ad88dc8 100644 (file)
@@ -1,3 +1,13 @@
+2010-04-13  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       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  <monnier@iro.umontreal.ca>
 
        * process.c (status_notify): Remove unused var `ro'.
index 9035a98..0759ce1 100644 (file)
@@ -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".  */
index 40f03da..fa3fc6d 100644 (file)
@@ -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.
index c62d572..e9440ad 100644 (file)
@@ -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;