emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 9df72ec 1/2: Preserve more markers when reverting .


From: Lars Ingebrigtsen
Subject: [Emacs-diffs] master 9df72ec 1/2: Preserve more markers when reverting .gpg files
Date: Wed, 4 Sep 2019 09:20:11 -0400 (EDT)

branch: master
commit 9df72ecb6339110a0380c6faf75e7e93025bb26a
Author: Lars Ingebrigtsen <address@hidden>
Commit: Lars Ingebrigtsen <address@hidden>

    Preserve more markers when reverting .gpg files
    
    * lisp/epa-file.el (epa-file--replace-text): Gingerly replace the
    text in the buffer to preserve as many markers as possible
    (bug#34720).  This emulates the behaviour of Finsert_file_contents
    more accurately.
    (epa-file-decode-and-insert): Remove compat code.
    (epa-file-insert-file-contents): Use the new function.
    
    * lisp/emacs-lisp/cl-lib.el (cl-incf): Add autoload cookie.
---
 lisp/emacs-lisp/cl-lib.el |  1 +
 lisp/epa-file.el          | 64 ++++++++++++++++++++++++++++++++++-------------
 2 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index c09fcf5..ff09691 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -110,6 +110,7 @@ a future Emacs interpreter will be able to use it.")
 ;; These macros are defined here so that they
 ;; can safely be used in init files.
 
+;;;###autoload
 (defmacro cl-incf (place &optional x)
   "Increment PLACE by X (1 by default).
 PLACE may be a symbol, or any generalized variable allowed by `setf'.
diff --git a/lisp/epa-file.el b/lisp/epa-file.el
index d9886d3..c43641a 100644
--- a/lisp/epa-file.el
+++ b/lisp/epa-file.el
@@ -102,16 +102,15 @@ encryption is used."
     (apply operation args)))
 
 (defun epa-file-decode-and-insert (string file visit beg end replace)
-  (if (fboundp 'decode-coding-inserted-region)
-      (save-restriction
-       (narrow-to-region (point) (point))
-       (insert string)
-       (decode-coding-inserted-region
-        (point-min) (point-max)
-        (substring file 0 (string-match epa-file-name-regexp file))
-        visit beg end replace))
-    (insert (epa-file--decode-coding-string string (or coding-system-for-read
-                                                      'undecided)))))
+  (save-restriction
+    (narrow-to-region (point) (point))
+    (insert string)
+    (decode-coding-inserted-region
+     (point-min) (point-max)
+     (substring file 0 (string-match epa-file-name-regexp file))
+     visit beg end replace)
+    (goto-char (point-max))
+    (- (point-max) (point-min))))
 
 (defvar epa-file-error nil)
 (defun epa-file--find-file-not-found-function ()
@@ -147,8 +146,6 @@ encryption is used."
           (format "Decrypting %s" file)))
     (unwind-protect
        (progn
-         (if replace
-             (goto-char (point-min)))
          (condition-case error
              (setq string (epg-decrypt-file context local-file nil))
            (error
@@ -187,12 +184,11 @@ encryption is used."
            ;; really edit the buffer.
            (let ((buffer-file-name
                   (if visit nil buffer-file-name)))
-             (save-restriction
-               (narrow-to-region (point) (point))
-               (epa-file-decode-and-insert string file visit beg end replace)
-               (setq length (- (point-max) (point-min))))
-             (if replace
-                 (delete-region (point) (point-max))))
+              (setq length
+                    (if replace
+                        (epa-file--replace-text string file visit beg end)
+                     (epa-file-decode-and-insert
+                       string file visit beg end replace))))
            (if visit
                (set-visited-file-modtime))))
       (if (and local-copy
@@ -201,6 +197,38 @@ encryption is used."
     (list file length)))
 (put 'insert-file-contents 'epa-file 'epa-file-insert-file-contents)
 
+(defun epa-file--replace-text (string file visit beg end)
+  ;; The idea here is that we want to replace the text in the buffer
+  ;; (for instance, for a `revert-buffer'), but we want to touch as
+  ;; little of the text as possible.  So we compare the new and the
+  ;; old text and only starts replacing when the text changes.
+  (let ((orig-point (point))
+        new-start length)
+    (goto-char (point-max))
+    (setq new-start (point))
+    (setq length
+         (epa-file-decode-and-insert
+           string file visit beg end t))
+    (if (equal (buffer-substring (point-min) new-start)
+               (buffer-substring new-start (point-max)))
+        ;; The new text is equal to the old, so just keep the old.
+        (delete-region new-start (point-max))
+      ;; Compute the region the hard way.
+      (let ((p1 (point-min))
+            (p2 new-start))
+        (while (and (< p1 new-start)
+                    (< p2 (point-max))
+                    (eql (char-after p1) (char-after p2)))
+          (cl-incf p1)
+          (cl-incf p2))
+        (delete-region new-start p2)
+        (delete-region p1 new-start)))
+    ;; Restore point, if possible.
+    (if (< orig-point (point-max))
+        (goto-char orig-point)
+      (goto-char (point-max)))
+    length))
+
 (defun epa-file-write-region (start end file &optional append visit lockname
                                    mustbenew)
   (if append



reply via email to

[Prev in Thread] Current Thread [Next in Thread]