]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix undo of changes in cloned indirect buffers
authorEli Zaretskii <eliz@gnu.org>
Thu, 7 Jul 2022 08:56:31 +0000 (11:56 +0300)
committerEli Zaretskii <eliz@gnu.org>
Thu, 7 Jul 2022 08:56:31 +0000 (11:56 +0300)
* lisp/simple.el (primitive-undo): If the visited-modtime of the
indirect buffer's file is bogus, use the modtime of the file
visited by its base buffer.

* src/undo.c (record_first_change): Call
'buffer_visited_file_modtime' with the correct buffer, instead of
always calling 'Fvisited_file_modtime', which returns possibly
bogus values for indirect buffers.
* src/fileio.c (Fset_visited_file_modtime): Signal a meaningful
error for indirect buffers.
(buffer_visited_file_modtime): New function, with implementation
taken from 'Fvisited_file_modtime'.
(Fvisited_file_modtime): Call 'buffer_visited_file_modtime'.
* src/lisp.h: Add prototype for 'buffer_visited_file_modtime'.
(Bug#56397)

lisp/simple.el
src/fileio.c
src/lisp.h
src/undo.c

index 6313ce81ef916baae025d71e9b525582fc6307a8..66640916a252314c25905acd49b1d555021cf0de 100644 (file)
@@ -3525,12 +3525,22 @@ Return what remains of the list."
            ;; If this records an obsolete save
            ;; (not matching the actual disk file)
            ;; then don't mark unmodified.
-           (when (or (equal time (visited-file-modtime))
-                     (and (consp time)
-                          (equal (list (car time) (cdr time))
-                                 (visited-file-modtime))))
-             (unlock-buffer)
-             (set-buffer-modified-p nil)))
+           (let ((visited-file-time (visited-file-modtime)))
+             ;; Indirect buffers don't have a visited file, so their
+             ;; file-modtime can be bogus.  In that case, use the
+             ;; modtime of the base buffer instead.
+             (if (and (numberp visited-file-time)
+                      (= visited-file-time 0)
+                      (buffer-base-buffer))
+                 (setq visited-file-time
+                      (with-current-buffer (buffer-base-buffer)
+                        (visited-file-modtime))))
+             (when (or (equal time visited-file-time)
+                       (and (consp time)
+                            (equal (list (car time) (cdr time))
+                                   visited-file-time)))
+               (unlock-buffer)
+               (set-buffer-modified-p nil))))
           ;; Element (nil PROP VAL BEG . END) is property change.
           (`(nil . ,(or `(,prop ,val ,beg . ,end) pcase--dontcare))
            (when (or (> (point-min) beg) (< (point-max) end))
index 10d4b8bc15ed38e9607c0ec3e0ff5b803dbf0d65..d07e62a12125277cc54bc6db78474dd5dfebfa6e 100644 (file)
@@ -5832,6 +5832,15 @@ See Info node `(elisp)Modification Time' for more details.  */)
   return Qnil;
 }
 
+Lisp_Object
+buffer_visited_file_modtime (struct buffer *buf)
+{
+  int ns = buf->modtime.tv_nsec;
+  if (ns < 0)
+    return make_fixnum (UNKNOWN_MODTIME_NSECS - ns);
+  return make_lisp_time (buf->modtime);
+}
+
 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
        Svisited_file_modtime, 0, 0, 0,
        doc: /* Return the current buffer's recorded visited file modification time.
@@ -5841,10 +5850,7 @@ visited file doesn't exist.
 See Info node `(elisp)Modification Time' for more details.  */)
   (void)
 {
-  int ns = current_buffer->modtime.tv_nsec;
-  if (ns < 0)
-    return make_fixnum (UNKNOWN_MODTIME_NSECS - ns);
-  return make_lisp_time (current_buffer->modtime);
+  return buffer_visited_file_modtime (current_buffer);
 }
 
 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
@@ -5871,6 +5877,8 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'.  */)
       current_buffer->modtime = mtime;
       current_buffer->modtime_size = -1;
     }
+  else if (current_buffer->base_buffer)
+    error ("An indirect buffer does not have a visited file");
   else
     {
       register Lisp_Object filename;
index e4a49b8ef945983a160440fee1f7545c70ebe214..35cc7f5a0985d0b67f9ad178e45e53d52541c045 100644 (file)
@@ -4733,6 +4733,7 @@ extern bool internal_delete_file (Lisp_Object);
 extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *);
 extern bool file_directory_p (Lisp_Object);
 extern bool file_accessible_directory_p (Lisp_Object);
+extern Lisp_Object buffer_visited_file_modtime (struct buffer *);
 extern void init_fileio (void);
 extern void syms_of_fileio (void);
 
index 36664d16424c6036b86969327b5b66bd5c8c883f..f76977dbe5038fc9ad7ff69a437dac07b95d7c8d 100644 (file)
@@ -218,7 +218,7 @@ record_first_change (void)
     base_buffer = base_buffer->base_buffer;
 
   bset_undo_list (current_buffer,
-                 Fcons (Fcons (Qt, Fvisited_file_modtime ()),
+                 Fcons (Fcons (Qt, buffer_visited_file_modtime (base_buffer)),
                         BVAR (current_buffer, undo_list)));
 }