aboutsummaryrefslogtreecommitdiff
path: root/working/org-element-cache-persist-bug/upstream-repro.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-30 17:48:06 -0500
committerCraig Jennings <c@cjennings.net>2026-07-30 17:48:06 -0500
commit00f44f46f65a96bb84271faa7f4ed7965fc44d5e (patch)
treea61cc9cbaabb03400cf64e1787e98fb226e3f3a9 /working/org-element-cache-persist-bug/upstream-repro.el
parentce223dc63c4901603e66aab0ebc8934791260c89 (diff)
downloaddotemacs-main.tar.gz
dotemacs-main.zip
docs: keep the org-element cache reproduction evidenceHEADmain
Twelve scripts plus a README covering the persist-write cache corruption: the no-dirvish root cause, the buffer-list ordering dependency, a faithful replay of the file-manager preview path, and the two fixes I tried and reverted. The README says which scripts are weak evidence and why, so the next reader doesn't rebuild an argument on the one whose control varied three things at once. Also holds the upstream bug report and its reproduction, verified to run standalone under emacs -Q.
Diffstat (limited to 'working/org-element-cache-persist-bug/upstream-repro.el')
-rw-r--r--working/org-element-cache-persist-bug/upstream-repro.el70
1 files changed, 70 insertions, 0 deletions
diff --git a/working/org-element-cache-persist-bug/upstream-repro.el b/working/org-element-cache-persist-bug/upstream-repro.el
new file mode 100644
index 00000000..d0a96774
--- /dev/null
+++ b/working/org-element-cache-persist-bug/upstream-repro.el
@@ -0,0 +1,70 @@
+;;; upstream-repro.el --- minimal reproduction for the org list -*- lexical-binding: t -*-
+
+;; Run with: emacs -Q --batch -l upstream-repro.el
+;;
+;; Writing the element cache to disk while the buffer is still live strips the
+;; :buffer property from every cached element and never restores it. The next
+;; access to a cached headline signals (wrong-type-argument stringp nil).
+
+(require 'org)
+(require 'org-element)
+(require 'org-persist)
+
+(let* ((dir (make-temp-file "org-persist-repro-" t))
+ (org-persist-directory (expand-file-name "persist" dir))
+ (file (expand-file-name "notes.org" dir))
+ (org-element-use-cache t)
+ (org-element-cache-persistent t)
+ (org-log-done nil))
+
+ (with-temp-file file
+ (dotimes (i 20)
+ (insert (format "* TODO task %d\nbody %d\n" i i))))
+
+ (let ((buffer (find-file-noselect file)))
+ (with-current-buffer buffer
+ ;; Populate the cache with parsed headlines.
+ (org-element-cache-reset)
+ (org-element-cache-map #'ignore :granularity 'headline)
+ (goto-char (point-min))
+ (re-search-forward "^\\* TODO task 0")
+ (beginning-of-line)
+ (org-todo "DONE"))
+
+ (message "cached :buffer values before write: %S"
+ (with-current-buffer buffer
+ (let (values)
+ (avl-tree-mapc (lambda (element)
+ (push (org-element-property :buffer element) values))
+ org-element--cache)
+ (delete-dups values))))
+
+ ;; Persist while the buffer is still alive. In a real session this is
+ ;; reached by any in-session write, e.g. `org-persist-write-all-buffer' from
+ ;; `kill-buffer-hook' in a *second* buffer visiting the same file.
+ (org-persist-write `((elisp org-element--cache)
+ (version ,org-element-cache-version))
+ buffer t)
+
+ (message "cached :buffer values after write: %S"
+ (with-current-buffer buffer
+ (let (values)
+ (avl-tree-mapc (lambda (element)
+ (push (org-element-property :buffer element) values))
+ org-element--cache)
+ (delete-dups values))))
+
+ (with-current-buffer buffer
+ (message "reading a cached headline: %s"
+ (condition-case err
+ (progn (org-element-cache-map
+ (lambda (element) (org-element-property :raw-value element))
+ :granularity 'headline)
+ "ok")
+ (error (format "%S" err)))))
+
+ (set-buffer-modified-p nil)
+ (kill-buffer buffer))
+ (delete-directory dir t))
+
+;;; upstream-repro.el ends here