branch: externals/persist
commit dab814ab0ffab1c08f48cc088fb93476d6908152
Author: Joseph Turner <[email protected]>
Commit: Philip Kaludercic <[email protected]>

    Fix persist-default prop being set to current value
    
    Previously, if a persist-defvar form was evaluated after the variable
    was bound, the default value would be set to the whatever the current
    value was instead of INITVALUE.  This sometimes led to a data loss
    bug, since persist-save deletes when the current value is
    persist-equal to the default value.  Resolves bug#75779.
---
 persist.el            | 17 +++++++++++------
 test/persist-tests.el |  6 ++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/persist.el b/persist.el
index 3260df0964..c6c708efc6 100644
--- a/persist.el
+++ b/persist.el
@@ -66,18 +66,20 @@ variable is not set to the value.")
    (or (get symbol 'persist-location)
        persist--directory-location)))
 
-(defun persist--defvar-1 (symbol location)
+(defun persist--defvar-1 (symbol location initvalue)
   "Set symbol up for persistence."
   (when location
     (persist-location symbol location))
-  (persist-symbol symbol (symbol-value symbol))
+  (persist-symbol symbol initvalue)
   (persist-load symbol))
 
 (defmacro persist-defvar (symbol initvalue docstring &optional location)
   "Define SYMBOL as a persistent variable and return SYMBOL.
 
 This form is nearly equivalent to `defvar', except that the
-variable persists between Emacs sessions.
+variable persists between Emacs sessions.  When this form is
+evaluated, the variable's default value is always set to
+INITVALUE.
 
 It does not support the optional parameters.  Both INITVALUE and
 DOCSTRING need to be given."
@@ -95,9 +97,12 @@ DOCSTRING need to be given."
   ;; Define inside progn so the byte compiler sees defvar
   `(progn
      (defvar ,symbol ,initvalue ,docstring)
-     ;; Access initvalue through its symbol because the defvar form
-     ;; has to stay at first level within a progn
-     (persist--defvar-1 ',symbol ,location)
+     ;; `defvar' must stay at top level within `progn'.  Pass init
+     ;; value to `persist--defvar-1' since the `defvar' form may not
+     ;; set the symbol's value and we don't want to set the
+     ;; persist-default property to the current value of the symbol.
+     ;; See bug#75779 for details.
+     (persist--defvar-1 ',symbol ,location ,initvalue)
      ',symbol))
 
 (defun persist-location (symbol directory)
diff --git a/test/persist-tests.el b/test/persist-tests.el
index 6bf2ed3708..2c452b7d38 100644
--- a/test/persist-tests.el
+++ b/test/persist-tests.el
@@ -108,6 +108,12 @@
    (should (= 20
               (persist-default 'test-persist-variable)))))
 
+(ert-deftest test-persist-default-set-to-initvalue ()
+  (persist-defvar test-persist-variable-default 'INIT "Docstring.")
+  (setq test-persist-variable-default 'CHANGED)
+  (persist-defvar test-persist-variable-default 'INIT "Docstring.")
+  (should (equal 'INIT (persist-default 'test-persist-variable-default))))
+
 (ert-deftest test-persist-location ()
   (unwind-protect
       (let ((sym (cl-gensym)))

Reply via email to