Subject: [PATCH] Make persist-defvar work with records and hash tables

From: Joseph Turner <[email-masked]>
Date: Sun, 14 May 2023 22:56:20 -0700

Hello!

persist-defvar does not persist records or hash tables correctly.

Here's a minimal example with a hash table:

(progn
  (persist-defvar foo (make-hash-table :test #'equal) "docstring")
  (puthash 'bar t foo)
  (persist-save 'foo)
  (gethash 'bar (persist-default 'foo))) ;; Expected nil, got t

This patch fixes persisting records by using copy-tree. Currently,
copy-tree does not work with records (see
<https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-05/msg00875.html>).
The following snippet will return the expected value only when both this
patch and the above-linked patch are applied:

(progn
  (cl-defstruct baz a)
  (persist-defvar quux (make-baz :a nil) "docstring")
  (setf (baz-a quux) t)
  (persist-save 'quux)
  (baz-a (persist-default 'quux))) ;; Expected nil, got t

Before applying this patch, the updated values in both cases are not
persisted to disk. With the patch, the updated values are persisted as
expected.

Best,

Joseph

>From b1512983fb82b9800ab6d0d1c9ca359e1251e94a Mon Sep 17 00:00:00 2001
From: Joseph Turner <[email-masked]>
Date: Sun, 14 May 2023 22:32:16 -0700
Subject: [PATCH] Make persist-defvar work with records and hash tables

Previously, when persist-defvar received a record or hash table for an
initial value, updated values were not persisted. This was because the
value and default value shared the same structure.
---
 persist.el | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/persist.el b/persist.el
index d80943d19e..a40fc2b297 100644
--- a/persist.el
+++ b/persist.el
@@ -118,7 +118,9 @@ (defun persist-symbol (symbol &optional initvalue)
   (let ((initvalue (or initvalue (symbol-value symbol))))
     (add-to-list 'persist--symbols symbol)
     (put symbol 'persist t)
-    (put symbol 'persist-default initvalue)))
+    (if (eq 'hash-table (type-of initvalue))
+        (put symbol 'persist-default (copy-hash-table initvalue))
+      (put symbol 'persist-default (copy-tree initvalue t)))))
 
 (defun persist--persistant-p (symbol)
   "Return non-nil if SYMBOL is a persistant variable."
-- 
2.40.1