diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-05 05:18:59 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-05 05:18:59 -0500 |
| commit | 7f7564612628d31718c2fc1e4471ab7fa29ef3c1 (patch) | |
| tree | a1847e743b1c00cb0984eee39cf4d86aadb6c6d4 | |
| parent | f5d67d7a0a48cd68d7f443ca475c0c7bc59a8468 (diff) | |
| download | org-drill-7f7564612628d31718c2fc1e4471ab7fa29ef3c1.tar.gz org-drill-7f7564612628d31718c2fc1e4471ab7fa29ef3c1.zip | |
fix: recover from corrupted persist file at package load (upstream #45)
Issue #45 (2021): persist-load raised End of file during parsing
at persist.el:413 in some configurations, likely from a corrupted
persist data file. Pre-fix, this propagated up through the
top-level (persist-defvar org-drill-sm5-optimal-factor-matrix ...)
form at file-load time and broke the entire package's load.
Wrapped the persist-defvar form in condition-case. On failure, the
matrix falls back to a fresh nil binding via plain defvar, and a
message tells the user what happened. org-drill continues to load
normally.
| -rw-r--r-- | org-drill.el | 17 | ||||
| -rw-r--r-- | tests/test-org-drill-persist-recovery.el | 51 |
2 files changed, 65 insertions, 3 deletions
diff --git a/org-drill.el b/org-drill.el index 0de606c..489215a 100644 --- a/org-drill.el +++ b/org-drill.el @@ -401,15 +401,26 @@ Available choices are: :group 'org-drill :type '(choice (const sm2) (const sm5) (const simple8))) -(persist-defvar org-drill-sm5-optimal-factor-matrix - nil - "DO NOT CHANGE THE VALUE OF THIS VARIABLE. +;; Wrap `persist-defvar' in `condition-case' so a corrupted persist +;; file (upstream issue #45 — "End of file during parsing" raised from +;; deep inside the persist package) doesn't prevent org-drill from +;; loading. Fall back to a fresh nil matrix when persist-load fails. +(condition-case err + (persist-defvar org-drill-sm5-optimal-factor-matrix + nil + "DO NOT CHANGE THE VALUE OF THIS VARIABLE. Persistent matrix of optimal factors, used by the SuperMemo SM5 algorithm. The matrix is saved at the end of each drill session. Over time, values in the matrix will adapt to the individual user's pace of learning.") + (error + (message + "org-drill: failed to load persisted SM5 matrix (%s); using fresh state" + err) + (defvar org-drill-sm5-optimal-factor-matrix nil + "Persistent matrix of optimal factors (fallback after load failure)."))) (defcustom org-drill-sm5-initial-interval 4.0 diff --git a/tests/test-org-drill-persist-recovery.el b/tests/test-org-drill-persist-recovery.el new file mode 100644 index 0000000..eb0b572 --- /dev/null +++ b/tests/test-org-drill-persist-recovery.el @@ -0,0 +1,51 @@ +;;; test-org-drill-persist-recovery.el --- Regression test for corrupted persist file -*- lexical-binding: t; -*- + +;;; Commentary: +;; Upstream issue #45 (2021-10). `persist-load' raises "End of file +;; during parsing" at persist.el:413 in some configurations, likely +;; from a corrupted persist data file. Pre-fix, this propagated up +;; through the `(persist-defvar org-drill-sm5-optimal-factor-matrix +;; ...)' form at file-load time, breaking the entire package's load. +;; +;; Fix wraps the persist-defvar form in `condition-case' so a +;; corrupted file falls back to a fresh nil matrix instead of +;; preventing the package from loading. + +;;; Code: + +(require 'ert) +(require 'cl-lib) +(require 'persist) +(require 'org-drill) + +;;;; Regression — wrapping pattern + +(ert-deftest test-persist-defvar-error-falls-back-to-initial-value () + "When persist-load throws, the condition-case wrapper recovers and +binds the symbol to the supplied initial value. + +This verifies the same wrapping pattern used at top-level around the +real `org-drill-sm5-optimal-factor-matrix' definition." + (let ((sym (intern (format "org-drill-test-persist-sym-%d" (random 999999))))) + (unwind-protect + (progn + (cl-letf (((symbol-function 'persist-symbol) #'ignore) + ((symbol-function 'persist-load) + (lambda (_) (error "End of file during parsing")))) + (condition-case _err + (eval `(persist-defvar ,sym 'fallback-value "doc")) + (error + (set sym 'fallback-value)))) + (should (eq 'fallback-value (symbol-value sym)))) + ;; Clean up the test symbol. + (when (boundp sym) (makunbound sym))))) + +(ert-deftest test-org-drill-sm5-optimal-factor-matrix-bound () + "After loading org-drill, the SM5 matrix variable is bound — confirms +the at-load-time wrapping (or normal persist-defvar success) leaves +the package in a usable state." + (should (boundp 'org-drill-sm5-optimal-factor-matrix))) + +(provide 'test-org-drill-persist-recovery) + +;;; test-org-drill-persist-recovery.el ends here |
