Created
July 29, 2026 13:52
-
-
Save lewang/8b7ae8aafc54b7074df05510bb732ed4 to your computer and use it in GitHub Desktop.
Reproduce denote PR #715: denote: link previews abort org-mode startup inside a silo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # Reproduce the per-commit table in comment.md by running repro-715.sh against | |
| # four builds of denote: upstream, each commit of PR #715 alone, and both. | |
| # | |
| # sh matrix.sh /path/to/denote-repo | |
| # | |
| # Each build is a throwaway git worktree at the pre-PR upstream tip with the | |
| # relevant denote.el hunks applied. Only denote.el is applied, not the test | |
| # files, so the two commits can be taken in isolation without conflicting. | |
| # Every worktree is removed on exit, so nothing is left registered in the repo. | |
| set -eu | |
| REPO=$(cd "${1:?usage: matrix.sh /path/to/denote-repo}" && pwd) | |
| HERE=$(cd "$(dirname "$0")" && pwd) | |
| BASE=1004f73 # upstream tip immediately before the PR | |
| DIRLOCAL=2fe3bcd # Honor unapplied dir-local denote-directory | |
| NILGUARD=d9d1257 # Do not attempt a preview for unresolvable denote links | |
| W=$(mktemp -d "${TMPDIR:-/tmp}/denote-715-matrix.XXXXXX") | |
| # One init directory for all four runs, so Org is byte-compiled once. | |
| DENOTE_715_EMACSD="$W/emacs.d" | |
| export DENOTE_715_EMACSD | |
| cleanup() { | |
| for d in "$W"/*; do | |
| [ -d "$d" ] && git -C "$REPO" worktree remove --force "$d" 2>/dev/null || true | |
| done | |
| rm -rf "$W" | |
| git -C "$REPO" worktree prune | |
| } | |
| trap cleanup EXIT | |
| build() { | |
| name=$1; shift | |
| git -C "$REPO" worktree add --detach "$W/$name" "$BASE" >/dev/null 2>&1 | |
| for sha in "$@"; do | |
| git -C "$REPO" show "$sha" -- denote.el | git -C "$W/$name" apply - | |
| done | |
| } | |
| build base | |
| build nilguard "$NILGUARD" | |
| build dirlocal "$DIRLOCAL" | |
| build both "$NILGUARD" "$DIRLOCAL" | |
| for name in base nilguard dirlocal both; do | |
| echo "################ $name ################" | |
| sh "$HERE/repro-715.sh" "$W/$name" | sed -n '3,$p' | |
| echo | |
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # Reproduce the failure fixed by denote PR #715. | |
| # | |
| # sh repro-715.sh /path/to/denote-checkout | |
| # | |
| # Everything lives in a throwaway directory: a pristine init directory whose | |
| # only package is Org, and a two-file silo. Your own configuration, your own | |
| # package directory and your own notes are never read or written. | |
| # | |
| # Two preconditions are load-bearing, and either one alone hides the bug: | |
| # | |
| # 1. Org >= 9.8. The `:preview' link parameter that denote registers | |
| # `denote-link-preview-file' on first shipped in Org 9.8 (released | |
| # 2026-02-21). On the Org bundled with every released Emacs -- 9.7.x -- | |
| # denote's preview function is never called and there is nothing to see. | |
| # Stock package.el pulls a current Org from GNU ELPA below. | |
| # | |
| # 2. A graphical frame. `org-link-preview-file' opens with | |
| # (when (display-graphic-p) ...), so under --batch the preview is skipped | |
| # and the run looks perfectly clean. The probe therefore opens a real | |
| # frame and exits on its own. | |
| set -eu | |
| DENOTE=${1:?usage: repro-715.sh /path/to/denote-checkout} | |
| DENOTE=$(cd "$DENOTE" && pwd) | |
| T=$(mktemp -d "${TMPDIR:-/tmp}/denote-715.XXXXXX") | |
| trap 'rm -rf "$T"' EXIT | |
| # -------------------------------------------------------------------------- | |
| # A pristine init directory. Stock package.el, GNU ELPA, nothing else. | |
| # | |
| # Set DENOTE_715_EMACSD to reuse one init directory across several runs; Org is | |
| # then installed and byte-compiled only once. Left unset, the init directory | |
| # lives and dies with this run. | |
| # -------------------------------------------------------------------------- | |
| ED=${DENOTE_715_EMACSD:-"$T/emacs.d"} | |
| mkdir -p "$ED" | |
| [ -f "$ED/init.el" ] || cat > "$ED/init.el" <<'EOF' | |
| ;;; init.el --- get a current Org from GNU ELPA -*- lexical-binding: t -*- | |
| (require 'package) | |
| (setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")) | |
| package-install-upgrade-built-in t) | |
| (package-initialize) | |
| (unless (assq 'org package-alist) | |
| (package-refresh-contents) | |
| (package-install 'org)) | |
| EOF | |
| # -------------------------------------------------------------------------- | |
| # The silo: a dir-local `denote-directory', one note, one image to preview. | |
| # -------------------------------------------------------------------------- | |
| mkdir -p "$T/silo" "$T/elsewhere" | |
| cat > "$T/silo/.dir-locals.el" <<EOF | |
| ((nil . ((denote-directory . "$T/silo")))) | |
| EOF | |
| cat > "$T/silo/20260101T000000--note__test.org" <<'EOF' | |
| #+title: note | |
| #+date: [2026-01-01 Thu 00:00] | |
| #+filetags: :test: | |
| #+identifier: 20260101T000000 | |
| [[denote:20260101T000001]] | |
| EOF | |
| # 1x1 transparent PNG, denote-named so the identifier resolves in the silo. | |
| printf '%s' 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==' \ | |
| | base64 -d > "$T/silo/20260101T000001--pic__test.png" | |
| # -------------------------------------------------------------------------- | |
| # The probe. Opens the note the way any user would and reports what happened. | |
| # -------------------------------------------------------------------------- | |
| cat > "$T/probe.el" <<'EOF' | |
| ;;; probe.el --- open a silo note with startup link previews -*- lexical-binding: t -*- | |
| (let* ((dir (getenv "REPRO_DIR")) | |
| (note (expand-file-name "silo/20260101T000000--note__test.org" dir)) | |
| msgs) | |
| ;; A global `denote-directory' that is NOT the silo -- the ordinary setup of | |
| ;; someone who keeps a main notes directory plus silos. Pointed at an empty | |
| ;; scratch directory so the run cannot create anything under $HOME. | |
| (setq-default denote-directory (expand-file-name "elsewhere" dir)) | |
| (require 'denote) | |
| (setq org-startup-with-link-previews t) | |
| (ignore-errors (find-file note)) | |
| (setq msgs (with-current-buffer "*Messages*" (buffer-string))) | |
| ;; Read every field in the note's own buffer, then write. `with-temp-file' | |
| ;; would otherwise report on its own temp buffer. | |
| (let (text) | |
| (with-current-buffer (get-file-buffer note) | |
| (setq text | |
| (list | |
| (format "Org version %s\n" (org-version)) | |
| (format "graphical frame %s\n" (if (display-graphic-p) "yes" "NO -- bug cannot appear")) | |
| (format "major mode %s\n" major-mode) | |
| (format "dir-locals applied %s\n" | |
| (if (local-variable-p 'denote-directory) "yes" "NO <-- hack-local-variables never ran")) | |
| (format "denote-directory %s\n" denote-directory) | |
| (format "link previews rendered %d\n" | |
| (length (seq-filter (lambda (o) (overlay-get o 'org-image-overlay)) | |
| (overlays-in (point-min) (point-max))))) | |
| (format "error in *Messages* %s\n" | |
| (if (string-match "File mode specification error.*" msgs) | |
| (match-string 0 msgs) | |
| "none"))))) | |
| (with-temp-file (expand-file-name "out.txt" dir) | |
| (apply #'insert text)))) | |
| (kill-emacs 0) | |
| EOF | |
| # -------------------------------------------------------------------------- | |
| # Run. First hop is batch and only installs Org; the second opens a frame. | |
| # -------------------------------------------------------------------------- | |
| emacs -Q --batch --init-directory="$ED" -l "$ED/init.el" \ | |
| --eval '(require (quote org))' >/dev/null 2>&1 | |
| REPRO_DIR="$T" emacs -Q --init-directory="$ED" -l "$ED/init.el" \ | |
| -L "$DENOTE" -l "$T/probe.el" >/dev/null 2>&1 | |
| echo "denote $DENOTE" | |
| echo "denote revision $(git -C "$DENOTE" rev-parse --short HEAD 2>/dev/null || echo 'not a git checkout')" | |
| cat "$T/out.txt" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment