From f079a39cbc254fd6e114a1ca6935d8445d35d343 Mon Sep 17 00:00:00 2001 From: Aner Zakobar Date: Thu, 8 Oct 2026 13:14:14 +0300 Subject: [PATCH] Make elfeed-protocol Nextcloud password fetch retriable A failed pass/gpg fetch (e.g. YubiKey not plugged in yet) used to pass process output straight to string-trim, which signals instead of returning nil on empty output, aborting the sentinel before elfeed-feeds or elfeed-protocol-enable ran. That left elfeed-feeds nil for the rest of the session with no visible error beyond a *Messages* line, and every later elfeed-update silently had nothing to fetch. Wrap the fetch in azos/elfeed-protocol-init-feeds so a failed attempt can be retried interactively instead of requiring a full reload of the elfeed-protocol feature. --- features/lauretta/emacs/config.org | 51 ++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/features/lauretta/emacs/config.org b/features/lauretta/emacs/config.org index d2504e2..d165c15 100644 --- a/features/lauretta/emacs/config.org +++ b/features/lauretta/emacs/config.org @@ -207,12 +207,9 @@ deprecation warning, and =elfeed-feeds= ends up with the bare URL and no =:password=, so requests silently authenticate with an empty password and nothing ever lands in the db. -This =:config= block runs synchronously the first time =elfeed= is -loaded (i.e. the first =M-x elfeed= of the session), with no user -keypress behind it the way =azos/caldav-sync= has. Fetching the -password with =shell-command-to-string= there used to deadlock -Emacs whenever the GPG PIN cache had expired: that call blocks -Emacs's single thread on the =pass|gpg= subprocess, but +Fetching the password with =shell-command-to-string= used to +deadlock Emacs whenever the GPG PIN cache had expired: that call +blocks Emacs's single thread on the =pass|gpg= subprocess, but =pinentry-emacs= (see the GPG Pinentry section above) needs Emacs's command loop running to answer its loopback prompt — so Emacs waits on gpg-agent while gpg-agent waits on Emacs. Fetching the password @@ -222,11 +219,27 @@ with =make-process= instead keeps the command loop alive, so fires. Same stderr-redirect reasoning as before, to keep a stray gpg/pass warning off the captured password. +The fetch is wrapped in a named, interactive function rather than +inlined in =:config= so a failed attempt (e.g. =pass= produced no +output because the YubiKey wasn't plugged in yet) can be retried +with =M-x azos/elfeed-protocol-init-feeds= — re-running =:config= +itself would require reloading the =elfeed-protocol= feature +entirely. An earlier version passed =(process-get proc 'output)= +straight to =string-trim=, which signals (not just returns nil) when +no output was ever read, aborting the sentinel before =elfeed-feeds= +or =elfeed-protocol-enable= ran — so a failed first attempt left +=elfeed-feeds= permanently =nil= for the rest of the session with no +visible error beyond a =*Messages*= line, and every subsequent +=elfeed-update= silently had nothing to fetch. + #+begin_src emacs-lisp -(use-package elfeed-protocol - :after elfeed - :config - (setq elfeed-protocol-enabled-protocols '(owncloud)) +(defun azos/elfeed-protocol-init-feeds () + "Fetch the Nextcloud password and (re)enable elfeed-protocol sync. +Unlike the one-shot `use-package' :config form this is called from, +safe to call again (e.g. via \\[azos/elfeed-protocol-init-feeds]) if +a previous attempt failed, such as the YubiKey not being plugged in +yet — it re-spawns the `pass' process and re-prompts for the PIN." + (interactive) (make-process :name "elfeed-protocol-pass" :command '("sh" "-c" "pass zakobar.com 2>/dev/null | head -1") @@ -234,10 +247,20 @@ gpg/pass warning off the captured password. :filter (lambda (proc chunk) (process-put proc 'output (concat (or (process-get proc 'output) "") chunk))) :sentinel (lambda (proc _event) - (setq elfeed-feeds - `(("owncloud+https://aner@nextcloud.zakobar.com" - :password ,(string-trim (process-get proc 'output))))) - (elfeed-protocol-enable)))) + (let ((password (string-trim (or (process-get proc 'output) "")))) + (if (string-empty-p password) + (message "elfeed-protocol: `pass zakobar.com' produced no output; retry with M-x azos/elfeed-protocol-init-feeds") + (setq elfeed-feeds + `(("owncloud+https://aner@nextcloud.zakobar.com" + :password ,password))) + (elfeed-protocol-enable) + (elfeed-update)))))) + +(use-package elfeed-protocol + :after elfeed + :config + (setq elfeed-protocol-enabled-protocols '(owncloud)) + (azos/elfeed-protocol-init-feeds)) #+end_src ** Elfeed Full Article Fetch