[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